forked from github_mirror/framelesshelper
win: fix wrong restore geometry when after DPI changes
This commit is contained in:
parent
30d2261baf
commit
41e91bb39a
|
@ -442,6 +442,16 @@ struct Dpi
|
||||||
{
|
{
|
||||||
quint32 x = 0;
|
quint32 x = 0;
|
||||||
quint32 y = 0;
|
quint32 y = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr bool operator==(const Dpi &lhs, const Dpi &rhs) noexcept
|
||||||
|
{
|
||||||
|
return ((lhs.x == rhs.x) && (lhs.y == rhs.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr bool operator!=(const Dpi &lhs, const Dpi &rhs) noexcept
|
||||||
|
{
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Global
|
} // namespace Global
|
||||||
|
|
|
@ -81,6 +81,8 @@ FRAMELESSHELPER_CORE_API void registerThemeChangeNotification();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativeLocalPosition(const QWindow *window, const QPoint &point);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativeLocalPosition(const QWindow *window, const QPoint &point);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativeGlobalPosition(const QWindow *window, const QPoint &point);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativeGlobalPosition(const QWindow *window, const QPoint &point);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API int horizontalAdvance(const QFontMetrics &fm, const QString &str);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API int horizontalAdvance(const QFontMetrics &fm, const QString &str);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API qreal getRelativeScaleFactor(const quint32 oldDpi, const quint32 newDpi);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QSize rescaleSize(const QSize &oldSize, const quint32 oldDpi, const quint32 newDpi);
|
||||||
|
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowsVersionOrGreater(const Global::WindowsVersion version);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowsVersionOrGreater(const Global::WindowsVersion version);
|
||||||
|
|
|
@ -1144,16 +1144,12 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
*result = FALSE; // Use the default linear DPI scaling provided by Windows.
|
*result = FALSE; // Use the default linear DPI scaling provided by Windows.
|
||||||
return true; // Jump over Qt's wrong handling logic.
|
return true; // Jump over Qt's wrong handling logic.
|
||||||
}
|
}
|
||||||
const QSizeF oldSize = {qreal(RECT_WIDTH(clientRect)), qreal(RECT_HEIGHT(clientRect))};
|
|
||||||
static constexpr const auto defaultDpi = qreal(USER_DEFAULT_SCREEN_DPI);
|
|
||||||
// We need to round the scale factor according to Qt's rounding policy.
|
|
||||||
const qreal oldDpr = Utils::roundScaleFactor(qreal(data.dpi.x) / defaultDpi);
|
|
||||||
const auto newDpi = UINT(wParam);
|
const auto newDpi = UINT(wParam);
|
||||||
const qreal newDpr = Utils::roundScaleFactor(qreal(newDpi) / defaultDpi);
|
const QSize oldSize = {RECT_WIDTH(clientRect), RECT_HEIGHT(clientRect)};
|
||||||
const QSizeF newSize = (oldSize / oldDpr * newDpr);
|
const QSize newSize = Utils::rescaleSize(oldSize, data.dpi.x, newDpi);
|
||||||
const auto suggestedSize = reinterpret_cast<LPSIZE>(lParam);
|
const auto suggestedSize = reinterpret_cast<LPSIZE>(lParam);
|
||||||
suggestedSize->cx = std::round(newSize.width());
|
suggestedSize->cx = newSize.width();
|
||||||
suggestedSize->cy = std::round(newSize.height());
|
suggestedSize->cy = newSize.height();
|
||||||
// If the window frame is visible, we need to expand the suggested size, currently
|
// If the window frame is visible, we need to expand the suggested size, currently
|
||||||
// it's pure client size, we need to add the frame size to it. Windows expects a
|
// it's pure client size, we need to add the frame size to it. Windows expects a
|
||||||
// full window size, including the window frame.
|
// full window size, including the window frame.
|
||||||
|
@ -1171,10 +1167,21 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
}
|
}
|
||||||
#endif // (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
#endif // (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
||||||
case WM_DPICHANGED: {
|
case WM_DPICHANGED: {
|
||||||
const Dpi dpi = {UINT(LOWORD(wParam)), UINT(HIWORD(wParam))};
|
const Dpi oldDpi = data.dpi;
|
||||||
DEBUG.noquote() << "New DPI for window" << hwnd2str(hWnd) << "is" << dpi;
|
const Dpi newDpi = {UINT(LOWORD(wParam)), UINT(HIWORD(wParam))};
|
||||||
|
if (Q_UNLIKELY(newDpi == oldDpi)) {
|
||||||
|
WARNING << "Wrong WM_DPICHANGED received: same DPI.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DEBUG.noquote() << "New DPI for window" << hwnd2str(hWnd)
|
||||||
|
<< "is" << newDpi << "(was" << oldDpi << ").";
|
||||||
g_win32Helper()->mutex.lock();
|
g_win32Helper()->mutex.lock();
|
||||||
g_win32Helper()->data[windowId].dpi = dpi;
|
g_win32Helper()->data[windowId].dpi = newDpi;
|
||||||
|
if (data.restoreGeometry.isValid() && !data.restoreGeometry.isNull()) {
|
||||||
|
// Update the window size only. The position should not be changed.
|
||||||
|
g_win32Helper()->data[windowId].restoreGeometry.setSize(
|
||||||
|
Utils::rescaleSize(data.restoreGeometry.size(), oldDpi.x, newDpi.x));
|
||||||
|
}
|
||||||
g_win32Helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
#if (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
#if (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
||||||
// We need to wait until Qt has handled this message, otherwise everything
|
// We need to wait until Qt has handled this message, otherwise everything
|
||||||
|
|
|
@ -87,7 +87,12 @@ QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Ver
|
||||||
QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi &dpi)
|
QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi &dpi)
|
||||||
{
|
{
|
||||||
const QDebugStateSaver saver(d);
|
const QDebugStateSaver saver(d);
|
||||||
const qreal scaleFactor = (qreal(dpi.x) / qreal(96));
|
#ifdef Q_OS_MACOS
|
||||||
|
static constexpr const auto defaultDpi = quint32(72);
|
||||||
|
#else // !Q_OS_MACOS
|
||||||
|
static constexpr const auto defaultDpi = quint32(96);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
|
const qreal scaleFactor = (qreal(dpi.x) / qreal(defaultDpi));
|
||||||
d.nospace().noquote() << "Dpi("
|
d.nospace().noquote() << "Dpi("
|
||||||
<< "x: " << dpi.x << ", "
|
<< "x: " << dpi.x << ", "
|
||||||
<< "y: " << dpi.y << ", "
|
<< "y: " << dpi.y << ", "
|
||||||
|
|
|
@ -522,4 +522,42 @@ int Utils::horizontalAdvance(const QFontMetrics &fm, const QString &str)
|
||||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qreal Utils::getRelativeScaleFactor(const quint32 oldDpi, const quint32 newDpi)
|
||||||
|
{
|
||||||
|
if (newDpi == oldDpi) {
|
||||||
|
return qreal(1);
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
static constexpr const auto defaultDpi = quint32(72);
|
||||||
|
#else // !Q_OS_MACOS
|
||||||
|
static constexpr const auto defaultDpi = quint32(96);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
|
if ((oldDpi < defaultDpi) || (newDpi < defaultDpi)) {
|
||||||
|
return qreal(1);
|
||||||
|
}
|
||||||
|
// We need to round the scale factor according to Qt's rounding policy.
|
||||||
|
const qreal oldDpr = roundScaleFactor(qreal(oldDpi) / qreal(defaultDpi));
|
||||||
|
const qreal newDpr = roundScaleFactor(qreal(newDpi) / qreal(defaultDpi));
|
||||||
|
return qreal(newDpr / oldDpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize Utils::rescaleSize(const QSize &oldSize, const quint32 oldDpi, const quint32 newDpi)
|
||||||
|
{
|
||||||
|
if (oldSize.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (newDpi == oldDpi) {
|
||||||
|
return oldSize;
|
||||||
|
}
|
||||||
|
const qreal scaleFactor = getRelativeScaleFactor(oldDpi, newDpi);
|
||||||
|
if (qFuzzyIsNull(scaleFactor)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (qFuzzyCompare(scaleFactor, qreal(1))) {
|
||||||
|
return oldSize;
|
||||||
|
}
|
||||||
|
const QSizeF newSize = QSizeF(oldSize) * scaleFactor;
|
||||||
|
return newSize.toSize(); // The numbers will be rounded to the nearest integer.
|
||||||
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
Loading…
Reference in New Issue