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 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
|
||||
|
|
|
@ -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 fromNativeGlobalPosition(const QWindow *window, const QPoint &point);
|
||||
[[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
|
||||
[[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.
|
||||
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 qreal newDpr = Utils::roundScaleFactor(qreal(newDpi) / defaultDpi);
|
||||
const QSizeF newSize = (oldSize / oldDpr * newDpr);
|
||||
const QSize oldSize = {RECT_WIDTH(clientRect), RECT_HEIGHT(clientRect)};
|
||||
const QSize newSize = Utils::rescaleSize(oldSize, data.dpi.x, newDpi);
|
||||
const auto suggestedSize = reinterpret_cast<LPSIZE>(lParam);
|
||||
suggestedSize->cx = std::round(newSize.width());
|
||||
suggestedSize->cy = std::round(newSize.height());
|
||||
suggestedSize->cx = newSize.width();
|
||||
suggestedSize->cy = newSize.height();
|
||||
// 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
|
||||
// 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))
|
||||
case WM_DPICHANGED: {
|
||||
const Dpi dpi = {UINT(LOWORD(wParam)), UINT(HIWORD(wParam))};
|
||||
DEBUG.noquote() << "New DPI for window" << hwnd2str(hWnd) << "is" << dpi;
|
||||
const Dpi oldDpi = data.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()->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();
|
||||
#if (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
||||
// 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)
|
||||
{
|
||||
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("
|
||||
<< "x: " << dpi.x << ", "
|
||||
<< "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))
|
||||
}
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue