diff --git a/include/FramelessHelper/Core/framelesshelpercore_global.h b/include/FramelessHelper/Core/framelesshelpercore_global.h index d05397e..735dc6e 100644 --- a/include/FramelessHelper/Core/framelesshelpercore_global.h +++ b/include/FramelessHelper/Core/framelesshelpercore_global.h @@ -415,10 +415,10 @@ Q_ENUM_NS(WindowCornerStyle) struct VersionNumber { - int major = 0; - int minor = 0; - int patch = 0; - int tweak = 0; + const int major = 0; + const int minor = 0; + const int patch = 0; + const int tweak = 0; [[nodiscard]] friend constexpr bool operator==(const VersionNumber &lhs, const VersionNumber &rhs) noexcept { @@ -571,39 +571,6 @@ struct SystemParameters } }; -#ifdef Q_OS_WINDOWS -[[maybe_unused]] inline constexpr const VersionNumber WindowsVersions[] = -{ - { 5, 0, 2195}, // Windows 2000 - { 5, 1, 2600}, // Windows XP - { 5, 2, 3790}, // Windows XP x64 Edition or Windows Server 2003 - { 6, 0, 6000}, // Windows Vista - { 6, 0, 6001}, // Windows Vista with Service Pack 1 or Windows Server 2008 - { 6, 0, 6002}, // Windows Vista with Service Pack 2 - { 6, 1, 7600}, // Windows 7 or Windows Server 2008 R2 - { 6, 1, 7601}, // Windows 7 with Service Pack 1 or Windows Server 2008 R2 with Service Pack 1 - { 6, 2, 9200}, // Windows 8 or Windows Server 2012 - { 6, 3, 9200}, // Windows 8.1 or Windows Server 2012 R2 - { 6, 3, 9600}, // Windows 8.1 with Update 1 - {10, 0, 10240}, // Windows 10 Version 1507 (TH1) - {10, 0, 10586}, // Windows 10 Version 1511 (November Update) (TH2) - {10, 0, 14393}, // Windows 10 Version 1607 (Anniversary Update) (RS1) or Windows Server 2016 - {10, 0, 15063}, // Windows 10 Version 1703 (Creators Update) (RS2) - {10, 0, 16299}, // Windows 10 Version 1709 (Fall Creators Update) (RS3) - {10, 0, 17134}, // Windows 10 Version 1803 (April 2018 Update) (RS4) - {10, 0, 17763}, // Windows 10 Version 1809 (October 2018 Update) (RS5) or Windows Server 2019 - {10, 0, 18362}, // Windows 10 Version 1903 (May 2019 Update) (19H1) - {10, 0, 18363}, // Windows 10 Version 1909 (November 2019 Update) (19H2) - {10, 0, 19041}, // Windows 10 Version 2004 (May 2020 Update) (20H1) - {10, 0, 19042}, // Windows 10 Version 20H2 (October 2020 Update) (20H2) - {10, 0, 19043}, // Windows 10 Version 21H1 (May 2021 Update) (21H1) - {10, 0, 19044}, // Windows 10 Version 21H2 (November 2021 Update) (21H2) - {10, 0, 19045}, // Windows 10 Version 22H2 (October 2022 Update) (22H2) - {10, 0, 22000}, // Windows 11 Version 21H2 (21H2) - {10, 0, 22621} // Windows 11 Version 22H2 (October 2022 Update) (22H2) -}; -#endif // Q_OS_WINDOWS - struct VersionInfo { const int version = 0; @@ -615,6 +582,45 @@ struct VersionInfo const bool isStatic = false; }; +struct Dpi +{ + const quint32 x = 0; + const quint32 y = 0; +}; + +#ifdef Q_OS_WINDOWS +[[maybe_unused]] inline constexpr const VersionNumber WindowsVersions[] = + { + { 5, 0, 2195}, // Windows 2000 + { 5, 1, 2600}, // Windows XP + { 5, 2, 3790}, // Windows XP x64 Edition or Windows Server 2003 + { 6, 0, 6000}, // Windows Vista + { 6, 0, 6001}, // Windows Vista with Service Pack 1 or Windows Server 2008 + { 6, 0, 6002}, // Windows Vista with Service Pack 2 + { 6, 1, 7600}, // Windows 7 or Windows Server 2008 R2 + { 6, 1, 7601}, // Windows 7 with Service Pack 1 or Windows Server 2008 R2 with Service Pack 1 + { 6, 2, 9200}, // Windows 8 or Windows Server 2012 + { 6, 3, 9200}, // Windows 8.1 or Windows Server 2012 R2 + { 6, 3, 9600}, // Windows 8.1 with Update 1 + {10, 0, 10240}, // Windows 10 Version 1507 (TH1) + {10, 0, 10586}, // Windows 10 Version 1511 (November Update) (TH2) + {10, 0, 14393}, // Windows 10 Version 1607 (Anniversary Update) (RS1) or Windows Server 2016 + {10, 0, 15063}, // Windows 10 Version 1703 (Creators Update) (RS2) + {10, 0, 16299}, // Windows 10 Version 1709 (Fall Creators Update) (RS3) + {10, 0, 17134}, // Windows 10 Version 1803 (April 2018 Update) (RS4) + {10, 0, 17763}, // Windows 10 Version 1809 (October 2018 Update) (RS5) or Windows Server 2019 + {10, 0, 18362}, // Windows 10 Version 1903 (May 2019 Update) (19H1) + {10, 0, 18363}, // Windows 10 Version 1909 (November 2019 Update) (19H2) + {10, 0, 19041}, // Windows 10 Version 2004 (May 2020 Update) (20H1) + {10, 0, 19042}, // Windows 10 Version 20H2 (October 2020 Update) (20H2) + {10, 0, 19043}, // Windows 10 Version 21H1 (May 2021 Update) (21H1) + {10, 0, 19044}, // Windows 10 Version 21H2 (November 2021 Update) (21H2) + {10, 0, 19045}, // Windows 10 Version 22H2 (October 2022 Update) (22H2) + {10, 0, 22000}, // Windows 11 Version 21H2 (21H2) + {10, 0, 22621} // Windows 11 Version 22H2 (October 2022 Update) (22H2) +}; +#endif // Q_OS_WINDOWS + } // namespace Global namespace FramelessHelper::Core @@ -633,3 +639,10 @@ FRAMELESSHELPER_END_NAMESPACE Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber) Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::SystemParameters) Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo) +Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi); + +#ifndef QT_NO_DEBUG_STREAM +FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber &); +FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo &); +FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi &); +#endif // QT_NO_DEBUG_STREAM diff --git a/include/FramelessHelper/Core/utils.h b/include/FramelessHelper/Core/utils.h index f7b7011..1fa7cda 100644 --- a/include/FramelessHelper/Core/utils.h +++ b/include/FramelessHelper/Core/utils.h @@ -92,7 +92,7 @@ FRAMELESSHELPER_CORE_API void showSystemMenu( [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThickness(const WId windowId, const bool horizontal, const bool scaled); -[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionHeight(const WId windowId, const bool scaled); +[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionBarHeight(const WId windowId, const bool scaled); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeight(const WId windowId, const bool scaled); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId windowId, const bool scaled); diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index 9815266..4b53932 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -531,8 +531,8 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms) qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data()); } g_win32Helper()->mutex.unlock(); - DEBUG.nospace().noquote() << "The DPI of window " << hwnd2str(windowId) << " is: QDpi(" - << Utils::getWindowDpi(windowId, true) << ", " << Utils::getWindowDpi(windowId, false) << ")."; + const Dpi dpi = {Utils::getWindowDpi(windowId, true), Utils::getWindowDpi(windowId, false)}; + DEBUG.noquote() << "The DPI of window" << hwnd2str(windowId) << "is" << dpi; // Some Qt internals have to be corrected. Utils::maybeFixupQtInternals(windowId); // Qt maintains a frame margin internally, we need to update it accordingly @@ -1122,22 +1122,30 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } break; #endif case WM_DPICHANGED: { - const UINT dpiX = LOWORD(wParam); - const UINT dpiY = HIWORD(wParam); - DEBUG.nospace().noquote() << "New DPI for window " - << hwnd2str(hWnd) << ": QDpi(" << dpiX << ", " << dpiY << ")."; + const Dpi dpi = {UINT(LOWORD(wParam)), UINT(HIWORD(wParam))}; + DEBUG.noquote() << "New DPI for window" << hwnd2str(hWnd) << "is" << dpi; // Sync the internal window frame margins with the latest DPI. Utils::updateInternalWindowFrameMargins(data.params.getWindowHandle(), true); // Here we need a little delay because event filters are processed before // Qt's own window message handlers. - QTimer::singleShot(50, [data](){ // Copy "data" intentionally, otherwise it'll go out of scope when Qt finally use it. + QTimer::singleShot(0, qApp, [data, windowId](){ // Copy the variables intentionally, otherwise they'll go out of scope when Qt finally use it. // For some unknown reason, Qt sometimes won't re-paint the window contents after // the DPI changes, and in my experiments the controls should be moved to our // desired geometry already, the only issue is we don't get the updated appearance // of our window. And we can workaround this issue by simply triggering a resize - // event manually. There's no need to increase/decrease the window size and then - // change it back, just give Qt our current window size is sufficient enough. - data.params.setWindowSize(data.params.getWindowSize()); + // event manually. + // For some reason the window will always expand for some pixels after the DPI + // changes, and normal Qt windows don't have this issue. It's probably caused + // by the custom margins we set, QPA may calculate a wrong frame size. It will + // always add a title bar height to the window, while it should not due to we + // have hide the title bar. For now we can simply workaround it by restoring + // to the original window size after the DPI change, but it's not ideal. Maybe + // we should reset the custom margins first and then restore it instead, but + // sadly this solution doesn't work as expected. Still need investigating. + const int titleBarHeight = Utils::getTitleBarHeight(windowId, false); + const QSize expandedSize = data.params.getWindowSize(); + const QSize correctedSize = {expandedSize.width(), expandedSize.height() - titleBarHeight}; + data.params.setWindowSize(correctedSize); }); } break; case WM_DWMCOMPOSITIONCHANGED: { diff --git a/src/core/framelesshelpercore_global.cpp b/src/core/framelesshelpercore_global.cpp index 9436c1f..64c8cd5 100644 --- a/src/core/framelesshelpercore_global.cpp +++ b/src/core/framelesshelpercore_global.cpp @@ -46,7 +46,7 @@ #endif #include #include -#include +#include #ifndef COMPILER_STRING # ifdef Q_CC_CLANG // Must be before GNU, because Clang claims to be GNU too. @@ -72,6 +72,46 @@ # endif #endif +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber &ver) +{ + const QDebugStateSaver saver(d); + d.nospace().noquote() << "VersionNumber(" + << ver.major << ", " + << ver.minor << ", " + << ver.patch << ", " + << ver.tweak << ')'; + return d; +} + +QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo &ver) +{ + const QDebugStateSaver saver(d); + int major = 0, minor = 0, patch = 0, tweak = 0; + FRAMELESSHELPER_EXTRACT_VERSION(ver.version, major, minor, patch, tweak) + const auto ver_num = FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber{major, minor, patch, tweak}; + d.nospace().noquote() << "VersionInfo(" + << "version number: " << ver_num << ", " + << "version string: " << ver.version_str << ", " + << "commit hash: " << ver.commit << ", " + << "compiler: " << ver.compiler << ", " + << "debug build: " << ver.isDebug << ", " + << "static build: " << ver.isStatic << ')'; + return d; +} + +QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi &dpi) +{ + const QDebugStateSaver saver(d); + const qreal scaleFactor = (qreal(dpi.x) / qreal(96)); + d.nospace().noquote() << "Dpi(" + << "x: " << dpi.x << ", " + << "y: " << dpi.y << ", " + << "scale factor: " << scaleFactor << ')'; + return d; +} +#endif // QT_NO_DEBUG_STREAM + FRAMELESSHELPER_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcCoreGlobal, "wangwenx190.framelesshelper.core.global") @@ -172,15 +212,6 @@ void initialize() QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif -#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - // Non-integer scale factors will cause Qt have some painting defects - // for both Qt Widgets and Qt Quick applications, and it's still not - // totally fixed till now (Qt 6.5), so we round the scale factors to - // get a better looking. Non-integer scale factors will also cause - // flicker and jitter during window resizing. - QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); -#endif - qRegisterMetaType