diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e10f397..5cdd433 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,6 +80,6 @@ jobs: run: | mkdir ci cd ci - cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_C_COMPILER=${{ matrix.CC }} -DCMAKE_CXX_COMPILER=${{ matrix.CXX }} -DCMAKE_LINKER=${{ matrix.LD }} -DCMAKE_INSTALL_PREFIX=../../install -DCMAKE_BUILD_TYPE=Release -DFRAMELESSHELPER_BUILD_EXAMPLES=ON ${{ matrix.lib_type_flag }} ${{ matrix.EXTRA_FLAGS }} -GNinja .. + cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_C_COMPILER=${{ matrix.CC }} -DCMAKE_CXX_COMPILER=${{ matrix.CXX }} -DCMAKE_LINKER=${{ matrix.LD }} -DCMAKE_INSTALL_PREFIX=../../install -DCMAKE_BUILD_TYPE=Release -DFRAMELESSHELPER_BUILD_EXAMPLES=ON -DFRAMELESSHELPER_NO_SUMMARY=OFF ${{ matrix.lib_type_flag }} ${{ matrix.EXTRA_FLAGS }} -GNinja .. cmake --build . --target all --config Release --parallel cmake --install . --config Release --strip diff --git a/CMakeLists.txt b/CMakeLists.txt index d14a99c..c4b707d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,21 +37,21 @@ option(FRAMELESSHELPER_BUILD_WIDGETS "Build FramelessHelper's Widgets module." O option(FRAMELESSHELPER_BUILD_QUICK "Build FramelessHelper's Quick module." ON) option(FRAMELESSHELPER_BUILD_EXAMPLES "Build FramelessHelper demo applications." OFF) option(FRAMELESSHELPER_EXAMPLES_DEPLOYQT "Deploy the Qt framework after building the demo projects." OFF) -option(FRAMELESSHELPER_NO_DEBUG_OUTPUT "Suppress the debug messages from FramelessHelper." OFF) +option(FRAMELESSHELPER_NO_DEBUG_OUTPUT "Suppress the debug messages from FramelessHelper." ON) option(FRAMELESSHELPER_NO_BUNDLE_RESOURCE "Do not bundle any resources within FramelessHelper." OFF) option(FRAMELESSHELPER_NO_PRIVATE "Do not use any private functionalities from Qt." OFF) option(FRAMELESSHELPER_ENABLE_VCLTL "MSVC only: link to the system MSVCRT/UCRT and get rid of API sets." OFF) option(FRAMELESSHELPER_ENABLE_YYTHUNKS "MSVC only: dynamic load most Win32 APIs to give better compatibility for old Windows versions." OFF) option(FRAMELESSHELPER_NO_PERMISSIVE_CHECKS "MSVC only: disable the additional permissive checks." OFF) option(FRAMELESSHELPER_NO_INSTALL "Don't install any files." OFF) -option(FRAMELESSHELPER_NO_SUMMARY "Don't show CMake configure summary." OFF) +option(FRAMELESSHELPER_NO_SUMMARY "Don't show CMake configure summary." ON) option(FRAMELESSHELPER_ENABLE_SPECTRE "Mitigate Spectre security vulnerabilities." OFF) option(FRAMELESSHELPER_ENABLE_EHCONTGUARD "MSVC only: Enable EH Continuation (EHCONT) Metadata." OFF) option(FRAMELESSHELPER_ENABLE_INTELCET "Enable Intel CET." OFF) option(FRAMELESSHELPER_ENABLE_INTELJCC "Enable Intel JCC." OFF) option(FRAMELESSHELPER_ENABLE_CFGUARD "Enable Control Flow Guard (CFG)." OFF) option(FRAMELESSHELPER_EXAMPLES_STANDALONE "Build the demo projects as standalone CMake projects." OFF) -cmake_dependent_option(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD "macOS only: build universal library/exemple for Mac." ON APPLE OFF) +cmake_dependent_option(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD "macOS only: build universal library/example for Mac." ON APPLE OFF) include(cmake/utils.cmake) @@ -227,6 +227,6 @@ if(NOT FRAMELESSHELPER_NO_SUMMARY) message("Enable Intel JCC: ${FRAMELESSHELPER_ENABLE_INTELJCC}") message("Enable Control Flow Guard (CFG): ${FRAMELESSHELPER_ENABLE_CFGUARD}") message("Build standalone demo projects: ${FRAMELESSHELPER_EXAMPLES_STANDALONE}") - message("[macOS]: Build universal library/exemple: ${FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD}") + message("[macOS]: Build universal library/example: ${FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD}") message("-----------------------------------------------------------------") endif() diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index 4293b31..e393d7a 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -399,7 +399,7 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper) // snap layout feature introduced in Windows 11. So you may wonder, why not just // limit it to the area of the three system buttons, instead of covering the // whole title bar area? Well, I've tried that solution already and unfortunately - // it doesn't work. And according to my experiment, it won't work either even if we + // it doesn't work. And according to my experiments, it won't work either even if we // only reduce the window width for some pixels. So we have to make it expand to the // full width of the parent window to let it occupy the whole top area, and this time // it finally works. Since our current solution works well, I have no interest in digging @@ -412,6 +412,18 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper) return true; } +static inline void cleanupFallbackWindow() +{ + const HINSTANCE instance = GetModuleHandleW(nullptr); + if (!instance) { + WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW); + return; + } + if (UnregisterClassW(kFallbackTitleBarWindowClassName, instance) == FALSE) { + WARNING << Utils::getSystemErrorMessage(kUnregisterClassW); + } +} + [[nodiscard]] static inline bool createFallbackTitleBarWindow(const WId parentWindowId, const bool hide) { Q_ASSERT(parentWindowId); @@ -446,16 +458,7 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper) wcex.lpfnWndProc = FallbackTitleBarWindowProc; wcex.hInstance = instance; if (RegisterClassExW(&wcex) != INVALID_ATOM) { - registerUninitializeHook([](){ - const HINSTANCE instance = GetModuleHandleW(nullptr); - if (!instance) { - //WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW); - return; - } - if (UnregisterClassW(kFallbackTitleBarWindowClassName, instance) == FALSE) { - //WARNING << Utils::getSystemErrorMessage(kUnregisterClassW); - } - }); + qAddPostRoutine(cleanupFallbackWindow); return true; } WARNING << Utils::getSystemErrorMessage(kRegisterClassExW); diff --git a/src/core/framelesshelpercore_global.cpp b/src/core/framelesshelpercore_global.cpp index c95b3b3..9bbeff6 100644 --- a/src/core/framelesshelpercore_global.cpp +++ b/src/core/framelesshelpercore_global.cpp @@ -145,30 +145,16 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(xcb) [[maybe_unused]] static constexpr const char kNoLogoEnvVar[] = "FRAMELESSHELPER_NO_LOGO"; -struct CoreData -{ - QList initHooks = {}; - QList uninitHooks = {}; -}; - -Q_GLOBAL_STATIC(CoreData, coreData) - void registerInitializeHook(const InitializeHookCallback &cb) { - Q_ASSERT(cb); - if (!cb) { - return; - } - coreData()->initHooks.append(cb); + Q_UNUSED(cb); + WARNING << "registerInitializeHook: This function is deprecated and will be removed in a future version. Please consider using Qt's official Q_COREAPP_STARTUP_FUNCTION() macro instead."; } void registerUninitializeHook(const UninitializeHookCallback &cb) { - Q_ASSERT(cb); - if (!cb) { - return; - } - coreData()->uninitHooks.append(cb); + Q_UNUSED(cb); + WARNING << "registerUninitializeHook: This function is deprecated and will be removed in a future version. Please consider using Qt's official qAddPostRoutine() function instead."; } namespace FramelessHelper::Core @@ -227,16 +213,6 @@ void initialize() QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif - - if (!coreData()->initHooks.isEmpty()) { - for (auto &&hook : std::as_const(coreData()->initHooks)) { - Q_ASSERT(hook); - if (!hook) { - continue; - } - hook(); - } - } } void uninitialize() @@ -246,17 +222,6 @@ void uninitialize() return; } uninited = true; - - if (coreData()->uninitHooks.isEmpty()) { - return; - } - for (auto &&hook : std::as_const(coreData()->uninitHooks)) { - Q_ASSERT(hook); - if (!hook) { - continue; - } - hook(); - } } VersionInfo version() diff --git a/src/core/utils_mac.mm b/src/core/utils_mac.mm index f5eaa2f..b717643 100644 --- a/src/core/utils_mac.mm +++ b/src/core/utils_mac.mm @@ -361,8 +361,8 @@ public Q_SLOTS: nswindow.showsToolbarButton = NO; nswindow.movableByWindowBackground = NO; nswindow.movable = NO; - // For some unknown reason, we don't need the following hack in some specific Qt versions. -#if QT_VERSION > QT_VERSION_CHECK(6, 2, 4) + // For some unknown reason, we don't need the following hack in Qt versions below or equal to 6.2.4. +#if (QT_VERSION > QT_VERSION_CHECK(6, 2, 4)) [nswindow standardWindowButton:NSWindowCloseButton].hidden = (visible ? NO : YES); [nswindow standardWindowButton:NSWindowMiniaturizeButton].hidden = (visible ? NO : YES); [nswindow standardWindowButton:NSWindowZoomButton].hidden = (visible ? NO : YES); @@ -572,6 +572,21 @@ Q_GLOBAL_STATIC(MacUtilsData, g_macUtilsData); return [nsview window]; } +static inline void cleanupProxy() +{ + if (g_macUtilsData()->hash.isEmpty()) { + return; + } + for (auto &&proxy : std::as_const(g_macUtilsData()->hash)) { + Q_ASSERT(proxy); + if (!proxy) { + continue; + } + delete proxy; + } + g_macUtilsData()->hash.clear(); +} + [[nodiscard]] static inline NSWindowProxy *ensureWindowProxy(const WId windowId) { Q_ASSERT(windowId); @@ -592,25 +607,11 @@ Q_GLOBAL_STATIC(MacUtilsData, g_macUtilsData); const auto proxy = new NSWindowProxy(qwindow, nswindow); g_macUtilsData()->hash.insert(windowId, proxy); } -#if 0 - volatile static const auto hook = []() -> int { - registerUninitializeHook([](){ - if (g_macUtilsData()->hash.isEmpty()) { - return; - } - for (auto &&proxy : std::as_const(g_macUtilsData()->hash)) { - Q_ASSERT(proxy); - if (!proxy) { - continue; - } - delete proxy; - } - g_macUtilsData()->hash.clear(); - }); - return 0; - }(); - Q_UNUSED(hook); -#endif + static bool cleanerInstalled = false; + if (!cleanerInstalled) { + cleanerInstalled = true; + qAddPostRoutine(cleanupProxy); + } return g_macUtilsData()->hash.value(windowId); }