diff --git a/include/FramelessHelper/Core/utils.h b/include/FramelessHelper/Core/utils.h index 3b99561..019be7b 100644 --- a/include/FramelessHelper/Core/utils.h +++ b/include/FramelessHelper/Core/utils.h @@ -128,6 +128,7 @@ FRAMELESSHELPER_CORE_API void setQtDarkModeAwareEnabled(const bool enable); [[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode_macos(); FRAMELESSHELPER_CORE_API void setSystemTitleBarVisible(const WId windowId, const bool visible); [[nodiscard]] FRAMELESSHELPER_CORE_API QColor getControlsAccentColor(); +FRAMELESSHELPER_CORE_API void removeWindowProxy(const WId windowId); #endif // Q_OS_MACOS } // namespace Utils diff --git a/src/core/framelesshelper_qt.cpp b/src/core/framelesshelper_qt.cpp index 421d38c..169d1c0 100644 --- a/src/core/framelesshelper_qt.cpp +++ b/src/core/framelesshelper_qt.cpp @@ -116,12 +116,16 @@ void FramelessHelperQt::removeWindow(const WId windowId) if (!g_qtHelper()->data.contains(windowId)) { return; } - const QtHelperData data = g_qtHelper()->data.value(windowId); - g_qtHelper()->data.remove(windowId); - if (QWindow * const window = Utils::findWindow(windowId)) { - window->removeEventFilter(data.eventFilter); + if (const auto eventFilter = g_qtHelper()->data.value(windowId).eventFilter) { + if (QWindow * const window = Utils::findWindow(windowId)) { + window->removeEventFilter(eventFilter); + } + delete eventFilter; } - delete data.eventFilter; + g_qtHelper()->data.remove(windowId); +#ifdef Q_OS_MACOS + Utils::removeWindowProxy(windowId); +#endif } bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) diff --git a/src/core/registrykey.cpp b/src/core/registrykey.cpp index 13d5275..115b76c 100644 --- a/src/core/registrykey.cpp +++ b/src/core/registrykey.cpp @@ -123,6 +123,9 @@ QVariant RegistryKey::value(const QString &name) const return {}; } #if REGISTRYKEY_QWINREGISTRYKEY +# if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) + return m_registryKey->value(name); +# else // (QT_VERSION < QT_VERSION_CHECK(6, 5, 0)) const QPair dwVal = m_registryKey->dwordValue(name); if (dwVal.second) { return qulonglong(dwVal.first); @@ -132,9 +135,10 @@ QVariant RegistryKey::value(const QString &name) const return strVal; } return {}; -#else +# endif // (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) +#else // !REGISTRYKEY_QWINREGISTRYKEY return m_settings->value(name); -#endif +#endif // REGISTRYKEY_QWINREGISTRYKEY } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/core/utils_mac.mm b/src/core/utils_mac.mm index 2649140..8919143 100644 --- a/src/core/utils_mac.mm +++ b/src/core/utils_mac.mm @@ -757,6 +757,24 @@ void Utils::registerThemeChangeNotification() Q_UNUSED(observer); } +void Utils::removeWindowProxy(const WId windowId) +{ + Q_ASSERT(windowId); + if (!windowId) { + return; + } + const QMutexLocker locker(&g_macUtilsData()->mutex); + if (!g_macUtilsData()->hash.contains(windowId)) { + return; + } + if (const auto proxy = g_macUtilsData()->hash.value(windowId)) { + // We'll restore everything to default in the destructor, + // so no need to do it manually here. + delete proxy; + } + g_macUtilsData()->hash.remove(windowId); +} + FRAMELESSHELPER_END_NAMESPACE #include "utils_mac.moc" diff --git a/src/core/utils_win.cpp b/src/core/utils_win.cpp index 0c4b983..4789ad9 100644 --- a/src/core/utils_win.cpp +++ b/src/core/utils_win.cpp @@ -43,7 +43,6 @@ #include "sysapiloader_p.h" #include "registrykey_p.h" #include -#include EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API HRESULT WINAPI SetWindowThemeAttribute2(const HWND hWnd, const _WINDOWTHEMEATTRIBUTETYPE attrib, @@ -86,7 +85,6 @@ Q_LOGGING_CATEGORY(lcUtilsWin, "wangwenx190.framelesshelper.core.utils.win") using namespace Global; static constexpr const char kNoFixQtInternalEnvVar[] = "FRAMELESSHELPER_WINDOWS_DONT_FIX_QT"; -static constexpr const wchar_t kDummyWindowClassName[] = L"org.wangwenx190.FramelessHelper.DummyWindow\0"; static const QString qDwmColorKeyName = QString::fromWCharArray(kDwmColorKeyName); FRAMELESSHELPER_STRING_CONSTANT2(SuccessMessageText, "The operation completed successfully.") FRAMELESSHELPER_STRING_CONSTANT2(EmptyMessageText, "FormatMessageW() returned empty string.") @@ -99,7 +97,6 @@ FRAMELESSHELPER_STRING_CONSTANT(user32) FRAMELESSHELPER_STRING_CONSTANT(dwmapi) FRAMELESSHELPER_STRING_CONSTANT(winmm) FRAMELESSHELPER_STRING_CONSTANT(shcore) -FRAMELESSHELPER_STRING_CONSTANT(d2d1) FRAMELESSHELPER_STRING_CONSTANT(uxtheme) FRAMELESSHELPER_STRING_CONSTANT(GetWindowRect) FRAMELESSHELPER_STRING_CONSTANT(DwmIsCompositionEnabled) @@ -135,9 +132,6 @@ FRAMELESSHELPER_STRING_CONSTANT(SetProcessDpiAwarenessContext) FRAMELESSHELPER_STRING_CONSTANT(SetProcessDpiAwareness) FRAMELESSHELPER_STRING_CONSTANT(SetProcessDPIAware) FRAMELESSHELPER_STRING_CONSTANT(GetDpiForMonitor) -FRAMELESSHELPER_STRING_CONSTANT(MonitorFromPoint) -FRAMELESSHELPER_STRING_CONSTANT(D2D1CreateFactory) -FRAMELESSHELPER_STRING_CONSTANT(ReloadSystemMetrics) FRAMELESSHELPER_STRING_CONSTANT(GetDC) FRAMELESSHELPER_STRING_CONSTANT(ReleaseDC) FRAMELESSHELPER_STRING_CONSTANT(GetDeviceCaps) @@ -169,6 +163,8 @@ FRAMELESSHELPER_STRING_CONSTANT(TileWallpaper) FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW) FRAMELESSHELPER_STRING_CONSTANT(DestroyWindow) FRAMELESSHELPER_STRING_CONSTANT(SetWindowThemeAttribute) +FRAMELESSHELPER_STRING_CONSTANT(CreateDCW) +FRAMELESSHELPER_STRING_CONSTANT(DeleteDC) struct Win32UtilsHelperData { @@ -213,61 +209,6 @@ struct SYSTEM_METRIC {SM_CXPADDEDBORDER, { 4, 5, 5, 6, 6, 6, 7, 7, 8, 9, 10, 12, 14, 16, 18, 20}} }; -template -class HumbleComPtr -{ - Q_DISABLE_COPY_MOVE(HumbleComPtr) - -public: - explicit HumbleComPtr() = default; - - explicit HumbleComPtr(T *ptr) - { - p = ptr; - } - - ~HumbleComPtr() - { - if (p) { - p->Release(); - p = nullptr; - } - } - - [[nodiscard]] operator T*() const - { - return p; - } - - [[nodiscard]] T &operator*() const - { - Q_ASSERT(p); - return *p; - } - - // The assert on operator& usually indicates a bug. If this is really - // what is needed, however, take the address of the p member explicitly. - [[nodiscard]] T **operator&() - { - Q_ASSERT(false); - return &p; - } - - [[nodiscard]] T *operator->() const - { - Q_ASSERT(p); - return p; - } - - [[nodiscard]] bool operator!() const - { - return (p == nullptr); - } - -private: - T *p = nullptr; -}; - [[nodiscard]] static inline QString dwmRegistryKey() { static const QString key = QString::fromWCharArray(kDwmRegistryKey); @@ -286,51 +227,6 @@ private: return key; } -[[nodiscard]] static inline HWND ensureDummyWindow() -{ - static const HWND hwnd = []() -> HWND { - const HINSTANCE instance = GetModuleHandleW(nullptr); - if (!instance) { - WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW); - return nullptr; - } - WNDCLASSEXW wcex = {}; - if (GetClassInfoExW(instance, kDummyWindowClassName, &wcex) == FALSE) { - SecureZeroMemory(&wcex, sizeof(wcex)); - wcex.cbSize = sizeof(wcex); - wcex.lpfnWndProc = DefWindowProcW; - wcex.hInstance = instance; - wcex.lpszClassName = kDummyWindowClassName; - if (RegisterClassExW(&wcex) == INVALID_ATOM) { - WARNING << Utils::getSystemErrorMessage(kRegisterClassExW); - return nullptr; - } - } - const HWND window = CreateWindowExW(0, kDummyWindowClassName, nullptr, - WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, nullptr, nullptr, instance, nullptr); - if (!window) { - WARNING << Utils::getSystemErrorMessage(kCreateWindowExW); - return nullptr; - } - FramelessHelper::Core::registerUninitializeHook([window](){ - if (window && (DestroyWindow(window) == FALSE)) { - //WARNING << Utils::getSystemErrorMessage(kDestroyWindow); - return; - } - const HINSTANCE instance = GetModuleHandleW(nullptr); - if (!instance) { - //WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW); - return; - } - if (UnregisterClassW(kDummyWindowClassName, instance) == FALSE) { - //WARNING << Utils::getSystemErrorMessage(kUnregisterClassW); - } - }); - return window; - }(); - return hwnd; -} - [[nodiscard]] static inline bool doCompareWindowsVersion(const VersionNumber &targetOsVer) { static const std::optional currentOsVer = []() -> std::optional { @@ -947,48 +843,61 @@ bool Utils::isHighContrastModeEnabled() quint32 Utils::getPrimaryScreenDpi(const bool horizontal) { - const auto getPrimaryMonitor = []() -> HMONITOR { - const HWND window = ensureDummyWindow(); - if (window) { - return MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY); - } - static constexpr const int kTaskBarSize = 100; - return MonitorFromPoint(POINT{kTaskBarSize, kTaskBarSize}, MONITOR_DEFAULTTOPRIMARY); - }; - if (API_SHCORE_AVAILABLE(GetDpiForMonitor)) { - const HMONITOR monitor = getPrimaryMonitor(); - if (monitor) { + if (const HMONITOR hMonitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY)) { + if (API_SHCORE_AVAILABLE(GetDpiForMonitor)) { UINT dpiX = 0, dpiY = 0; - const HRESULT hr = API_CALL_FUNCTION(GetDpiForMonitor, monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + const HRESULT hr = API_CALL_FUNCTION(GetDpiForMonitor, hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); if (SUCCEEDED(hr) && (dpiX > 0) && (dpiY > 0)) { return (horizontal ? dpiX : dpiY); } else { WARNING << __getSystemErrorMessage(kGetDpiForMonitor, hr); } - } else { - WARNING << getSystemErrorMessage(kMonitorFromPoint); } - } - if (API_SHCORE_AVAILABLE(GetScaleFactorForMonitor)) { - const HMONITOR monitor = getPrimaryMonitor(); - if (monitor) { + if (API_SHCORE_AVAILABLE(GetScaleFactorForMonitor)) { DEVICE_SCALE_FACTOR factor = DEVICE_SCALE_FACTOR_INVALID; - const HRESULT hr = API_CALL_FUNCTION(GetScaleFactorForMonitor, monitor, &factor); + const HRESULT hr = API_CALL_FUNCTION(GetScaleFactorForMonitor, hMonitor, &factor); if (SUCCEEDED(hr) && (factor != DEVICE_SCALE_FACTOR_INVALID)) { return quint32(qRound(qreal(USER_DEFAULT_SCREEN_DPI) * qreal(factor) / qreal(100))); } else { WARNING << __getSystemErrorMessage(kGetScaleFactorForMonitor, hr); } - } else { - WARNING << getSystemErrorMessage(kMonitorFromPoint); } + MONITORINFOEXW monitorInfo; + SecureZeroMemory(&monitorInfo, sizeof(monitorInfo)); + monitorInfo.cbSize = sizeof(monitorInfo); + if (GetMonitorInfoW(hMonitor, &monitorInfo) != FALSE) { + if (const HDC hdc = CreateDCW(monitorInfo.szDevice, monitorInfo.szDevice, nullptr, nullptr)) { + bool valid = false; + const int dpiX = GetDeviceCaps(hdc, LOGPIXELSX); + const int dpiY = GetDeviceCaps(hdc, LOGPIXELSY); + if ((dpiX > 0) && (dpiY > 0)) { + valid = true; + } else { + WARNING << getSystemErrorMessage(kGetDeviceCaps); + } + if (DeleteDC(hdc) == FALSE) { + WARNING << getSystemErrorMessage(kDeleteDC); + } + if (valid) { + return (horizontal ? dpiX : dpiY); + } + } else { + WARNING << getSystemErrorMessage(kCreateDCW); + } + } else { + WARNING << getSystemErrorMessage(kGetMonitorInfoW); + } + } else { + WARNING << getSystemErrorMessage(kMonitorFromWindow); } + +#if 0 // The above solutions should be sufficient enough, no need to pull in a new dependency. if (API_D2D_AVAILABLE(D2D1CreateFactory)) { using D2D1CreateFactoryPtr = HRESULT(WINAPI *)(D2D1_FACTORY_TYPE, REFIID, CONST D2D1_FACTORY_OPTIONS *, void **); const auto pD2D1CreateFactory = reinterpret_cast(SysApiLoader::instance()->get(kD2D1CreateFactory)); - auto d2dFactory = HumbleComPtr(nullptr); + auto d2dFactory = CComPtr(nullptr); HRESULT hr = pD2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), nullptr, reinterpret_cast(&d2dFactory)); if (SUCCEEDED(hr)) { @@ -1011,8 +920,9 @@ quint32 Utils::getPrimaryScreenDpi(const bool horizontal) WARNING << __getSystemErrorMessage(kD2D1CreateFactory, hr); } } - const HDC hdc = GetDC(nullptr); - if (hdc) { +#endif + + if (const HDC hdc = GetDC(nullptr)) { bool valid = false; const int dpiX = GetDeviceCaps(hdc, LOGPIXELSX); const int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);