From d86f55832fd61684df86086255b1e0c7f4c6101b Mon Sep 17 00:00:00 2001 From: Yuhang Zhao Date: Thu, 14 Sep 2023 17:58:50 +0800 Subject: [PATCH] refactor --- CMakeLists.txt | 93 ++-- build.bat | 47 ++ build/msvc.bat | 37 -- include/FramelessHelper/Core/chromepalette.h | 8 +- .../FramelessHelper/Core/framelesshelper_qt.h | 14 +- .../Core/framelesshelper_win.h | 12 +- .../Core/framelesshelper_windows.h | 134 +++++- .../Core/framelesshelpercore_global.h | 86 +++- .../FramelessHelper/Core/framelessmanager.h | 13 +- include/FramelessHelper/Core/micamaterial.h | 8 +- .../Core/private/chromepalette_p.h | 9 +- .../Core/private/framelessconfig_p.h | 3 +- .../private/framelesshelpercore_global_p.h | 82 +++- .../Core/private/framelessmanager_p.h | 19 +- .../Core/private/micamaterial_p.h | 9 +- .../Core/private/registrykey_p.h | 3 +- .../Core/private/scopeguard_p.h | 2 +- .../Core/private/sysapiloader_p.h | 3 +- .../Core/private/windowborderpainter_p.h | 9 +- include/FramelessHelper/Core/utils.h | 60 +-- .../Core/windowborderpainter.h | 8 +- .../Quick/framelesshelperquick_global.h | 3 +- .../Quick/framelessquickhelper.h | 9 +- .../Quick/framelessquickutils.h | 3 +- .../framelessquickapplicationwindow_p.h | 8 +- .../framelessquickapplicationwindow_p_p.h | 10 +- .../Quick/private/framelessquickhelper_p.h | 13 +- .../Quick/private/framelessquickwindow_p.h | 8 +- .../Quick/private/framelessquickwindow_p_p.h | 10 +- .../Quick/private/quickimageitem_p.h | 3 +- .../Quick/private/quickmicamaterial_p.h | 10 +- .../private/quickstandardsystembutton_p.h | 3 +- .../Quick/private/quickstandardtitlebar_p.h | 3 +- .../Quick/private/quickwindowborder_p.h | 10 +- .../Quick/quickchromepalette.h | 5 +- .../FramelessHelper/Quick/quickmicamaterial.h | 8 +- .../FramelessHelper/Quick/quickwindowborder.h | 8 +- .../FramelessHelper/Widgets/framelessdialog.h | 8 +- .../Widgets/framelessmainwindow.h | 8 +- .../FramelessHelper/Widgets/framelesswidget.h | 8 +- .../Widgets/framelesswidgetshelper.h | 9 +- .../Widgets/private/framelessdialog_p.h | 10 +- .../Widgets/private/framelessmainwindow_p.h | 10 +- .../Widgets/private/framelesswidget_p.h | 10 +- .../private/framelesswidgetshelper_p.h | 13 +- .../Widgets/private/standardsystembutton_p.h | 9 +- .../Widgets/private/standardtitlebar_p.h | 10 +- .../Widgets/private/widgetssharedhelper_p.h | 3 +- .../Widgets/standardsystembutton.h | 8 +- .../Widgets/standardtitlebar.h | 8 +- src/core/CMakeLists.txt | 47 +- src/core/framelessconfig.cpp | 8 +- src/core/framelesshelper_qt.cpp | 211 +++++---- src/core/framelesshelper_win.cpp | 264 ++++++----- src/core/framelesshelpercore_global.cpp | 17 + src/core/framelessmanager.cpp | 271 +++++++++-- src/core/micamaterial.cpp | 10 +- src/core/platformsupport_win.cpp | 86 ++-- src/core/utils.cpp | 36 +- src/core/utils_linux.cpp | 4 +- src/core/utils_mac.mm | 9 +- src/core/utils_win.cpp | 432 ++++++++---------- src/core/winverhelper.cpp | 2 +- src/quick/CMakeLists.txt | 2 +- src/quick/framelessquickhelper.cpp | 359 ++++++++------- src/widgets/CMakeLists.txt | 2 +- src/widgets/framelesswidgetshelper.cpp | 346 ++++++++------ 67 files changed, 1696 insertions(+), 1297 deletions(-) create mode 100644 build.bat delete mode 100644 build/msvc.bat diff --git a/CMakeLists.txt b/CMakeLists.txt index c0f00abe..a3dda83f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ project(FramelessHelper ) include(CMakeDependentOption) +include(cmake/utils.cmake) # TODO: Use add_feature_info() for every option below? Is it worth doing? option(FRAMELESSHELPER_BUILD_STATIC "Build FramelessHelper as a static library." OFF) @@ -61,16 +62,7 @@ option(FRAMELESSHELPER_NO_TRANSLATION "Don't bundle the I18N translations into t option(FRAMELESSHELPER_NO_MICA_MATERIAL "Disable the cross-platform homemade Mica Material." OFF) option(FRAMELESSHELPER_NO_BORDER_PAINTER "Disable the cross-platform window frame border painter." OFF) option(FRAMELESSHELPER_NO_SYSTEM_BUTTON "Disable the pre-defined StandardSystemButton control." OFF) - -if(FRAMELESSHELPER_NO_WINDOW AND FRAMELESSHELPER_BUILD_EXAMPLES) - message(WARNING "You can't build the examples when the FramelessWindow class is disabled at the same time!") - set(FRAMELESSHELPER_BUILD_EXAMPLES OFF) -endif() - -set(FRAMELESSHELPER_64BIT_POSTFIX "") -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(FRAMELESSHELPER_64BIT_POSTFIX "64") -endif() +cmake_dependent_option(FRAMELESSHELPER_NATIVE_IMPL "Use platform native implementation instead of Qt to get best experience." ON WIN32 OFF) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Gui) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui) @@ -78,10 +70,18 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui) find_package(QT NAMES Qt6 Qt5 QUIET COMPONENTS Widgets Quick) find_package(Qt${QT_VERSION_MAJOR} QUIET COMPONENTS Widgets Quick) -include(cmake/utils.cmake) +if(FRAMELESSHELPER_NATIVE_IMPL AND NOT WIN32) + message(WARNING "FRAMELESSHELPER_NATIVE_IMPL currently only supports the Windows platform!") + set(FRAMELESSHELPER_NATIVE_IMPL OFF) +endif() -if(NOT APPLE AND FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD) - message(WARNING "Current OS is not macOS, universal build will be disabled.") +if(FRAMELESSHELPER_NO_WINDOW AND FRAMELESSHELPER_BUILD_EXAMPLES) + message(WARNING "You can't build the examples when the FramelessWindow class is disabled at the same time!") + set(FRAMELESSHELPER_BUILD_EXAMPLES OFF) +endif() + +if(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD AND NOT APPLE) + message(WARNING "Universal build is a macOS only feature, it will be disabled on current platform.") set(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD OFF) elseif(APPLE AND ((QT_VERSION VERSION_LESS "6.2" AND QT_VERSION VERSION_GREATER_EQUAL "6.0") OR (QT_VERSION VERSION_LESS "5.15.9"))) message(WARNING "Your Qt version ${QT_VERSION} doesn't support universal build, it will be disabled.") @@ -94,6 +94,29 @@ endif() if(FRAMELESSHELPER_ENABLE_VCLTL AND NOT MSVC) message(WARNING "VC-LTL is only available for the MSVC toolchain.") + set(FRAMELESSHELPER_ENABLE_VCLTL OFF) +endif() + +if(FRAMELESSHELPER_ENABLE_YYTHUNKS AND NOT MSVC) + message(WARNING "YY-Thunks is only available for the MSVC toolchain.") + set(FRAMELESSHELPER_ENABLE_YYTHUNKS OFF) +endif() + +if(NOT TARGET Qt${QT_VERSION_MAJOR}::Core OR NOT TARGET Qt${QT_VERSION_MAJOR}::Gui) + message(WARNING "Can't find the QtCore and/or QtGui module. Nothing will be built.") + set(FRAMELESSHELPER_BUILD_WIDGETS OFF) + set(FRAMELESSHELPER_BUILD_QUICK OFF) + set(FRAMELESSHELPER_BUILD_EXAMPLES OFF) +endif() + +if(FRAMELESSHELPER_BUILD_QUICK AND NOT TARGET Qt${QT_VERSION_MAJOR}::Quick) + message(WARNING "Can't find the QtQuick module. FramelessHelper's QtQuick implementation and the QtQuick demo won't be built.") + set(FRAMELESSHELPER_BUILD_QUICK OFF) +endif() + +set(FRAMELESSHELPER_64BIT_POSTFIX "") +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(FRAMELESSHELPER_64BIT_POSTFIX "64") endif() set(FRAMELESSHELPER_LICENSE_HEADER "/* @@ -144,25 +167,23 @@ if(MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(FRAMELESSHELPER_ENABLE_CFGUARD OFF) endif() -if(MSVC) - if(FRAMELESSHELPER_ENABLE_VCLTL) - include(cmake/VC-LTL.cmake) - if("x${SupportLTL}" STREQUAL "xtrue") - # Make sure we will always overwrite the previous settings. - unset(CMAKE_MSVC_RUNTIME_LIBRARY) - unset(CMAKE_MSVC_RUNTIME_LIBRARY CACHE) - #unset(CMAKE_MSVC_RUNTIME_LIBRARY PARENT_SCOPE) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" CACHE STRING "" FORCE) - endif() - endif() - if(FRAMELESSHELPER_ENABLE_YYTHUNKS) - unset(YYTHUNKS_TARGET_OS) - unset(YYTHUNKS_TARGET_OS CACHE) - #unset(YYTHUNKS_TARGET_OS PARENT_SCOPE) - set(YYTHUNKS_TARGET_OS "WinXP" CACHE STRING "" FORCE) - include(cmake/YY-Thunks.cmake) +if(FRAMELESSHELPER_ENABLE_VCLTL) + include(cmake/VC-LTL.cmake) + if("x${SupportLTL}" STREQUAL "xtrue") + # Make sure we will always overwrite the previous settings. + unset(CMAKE_MSVC_RUNTIME_LIBRARY) + unset(CMAKE_MSVC_RUNTIME_LIBRARY CACHE) + #unset(CMAKE_MSVC_RUNTIME_LIBRARY PARENT_SCOPE) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" CACHE STRING "" FORCE) endif() endif() +if(FRAMELESSHELPER_ENABLE_YYTHUNKS) + unset(YYTHUNKS_TARGET_OS) + unset(YYTHUNKS_TARGET_OS CACHE) + #unset(YYTHUNKS_TARGET_OS PARENT_SCOPE) + set(YYTHUNKS_TARGET_OS "WinXP" CACHE STRING "" FORCE) + include(cmake/YY-Thunks.cmake) +endif() set(__extra_flags "") if(FRAMELESSHELPER_NO_INSTALL) @@ -175,11 +196,6 @@ prepare_package_export( ) unset(__extra_flags) -if(FRAMELESSHELPER_BUILD_QUICK AND NOT TARGET Qt${QT_VERSION_MAJOR}::Quick) - message(WARNING "Can't find the QtQuick module. FramelessHelper's QtQuick implementation and the QtQuick demo won't be built.") - set(FRAMELESSHELPER_BUILD_QUICK OFF) -endif() - set(FRAMELESSHELPER_VERSION_FILE "${PROJECT_BINARY_DIR}/framelesshelper.version") generate_project_version( PATH "${FRAMELESSHELPER_VERSION_FILE}" @@ -202,14 +218,11 @@ add_project_config(KEY "translation" CONDITION NOT FRAMELESSHELPER_NO_TRANSLATIO add_project_config(KEY "mica_material" CONDITION NOT FRAMELESSHELPER_NO_MICA_MATERIAL) add_project_config(KEY "border_painter" CONDITION NOT FRAMELESSHELPER_NO_BORDER_PAINTER) add_project_config(KEY "system_button" CONDITION NOT FRAMELESSHELPER_NO_SYSTEM_BUTTON) +add_project_config(KEY "native_impl" CONDITION FRAMELESSHELPER_NATIVE_IMPL) generate_project_config(PATH "${FRAMELESSHELPER_CONFIG_FILE}") -if(TARGET Qt${QT_VERSION_MAJOR}::Core AND TARGET Qt${QT_VERSION_MAJOR}::Gui) +if(FRAMELESSHELPER_BUILD_WIDGETS OR FRAMELESSHELPER_BUILD_QUICK) add_subdirectory(src) -else() - message(WARNING "Can't find the QtCore and QtGui module. Nothing will be built.") - set(FRAMELESSHELPER_BUILD_WIDGETS OFF) - set(FRAMELESSHELPER_BUILD_EXAMPLES OFF) endif() if(FRAMELESSHELPER_BUILD_EXAMPLES) diff --git a/build.bat b/build.bat new file mode 100644 index 00000000..0f785241 --- /dev/null +++ b/build.bat @@ -0,0 +1,47 @@ +@echo off +title Building FramelessHelper ... +setlocal +cls +set __vs_bat=%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat +if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat +if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat +if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2015\Community\VC\Auxiliary\Build\vcvars64.bat +if not exist "%__vs_bat%" ( + echo Cannot find a valid Visual Studio toolchain! + echo Please install at least Visual Studio 2015 to the default location + echo and install the English language pack at the same time. + echo If you want to use clang-cl or MinGW to build this project, please + echo make sure you have added their directory to your PATH environment + echo variable. + echo Press the ENTER key to continue, or close this window directly. + pause +) else ( + call "%__vs_bat%" +) +cmake --version +echo ninja build +ninja --version +cd /d "%~dp0" +if exist build.user.bat call build.user.bat +if not defined CC set CC=cl.exe +if not defined CXX set CXX=cl.exe +if not defined QTDIR set QTDIR=%SystemDrive%\Qt\6.6.0\msvc2019_64 +echo CC=%CC% +echo CXX=%CXX% +echo QTDIR=%QTDIR% +if exist build rd /s /q build +md build +cd build +md cmake +cd cmake +cmake -DCMAKE_C_COMPILER="%CC%" -DCMAKE_CXX_COMPILER="%CXX%" -DCMAKE_PREFIX_PATH="%QTDIR%" -DCMAKE_INSTALL_PREFIX="%~dp0build\install" -DCMAKE_CONFIGURATION_TYPES=Release;Debug -G"Ninja Multi-Config" -DFRAMELESSHELPER_ENABLE_VCLTL=ON -DFRAMELESSHELPER_ENABLE_YYTHUNKS=ON -DFRAMELESSHELPER_ENABLE_SPECTRE=ON -DFRAMELESSHELPER_ENABLE_EHCONTGUARD=ON -DFRAMELESSHELPER_ENABLE_INTELCET=ON -DFRAMELESSHELPER_ENABLE_INTELJCC=ON -DFRAMELESSHELPER_ENABLE_CFGUARD=ON -DFRAMELESSHELPER_FORCE_LTO=ON "%~dp0" +cmake --build . --target all --config Release --parallel +cmake --build . --target all --config Debug --parallel +cmake --install . --config Release --strip +cmake --install . --config Debug +goto fin +:fin +endlocal +cd /d "%~dp0" +pause +exit /b 0 diff --git a/build/msvc.bat b/build/msvc.bat deleted file mode 100644 index ba4fcb34..00000000 --- a/build/msvc.bat +++ /dev/null @@ -1,37 +0,0 @@ -@echo off -title Building FramelessHelper ... -setlocal -cls -set __vs_bat=%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat -if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat -if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat -if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2015\Community\VC\Auxiliary\Build\vcvars64.bat -if not exist "%__vs_bat%" ( - echo Cannot find a valid Visual Studio toolchain! - echo Please install at least Visual Studio 2015 to the default location! - goto fin -) -call "%__vs_bat%" -cmake --version -echo ninja build -ninja --version -cd /d "%~dp0" -if exist "%~dp0build.user.bat" call "%~dp0build.user.bat" -if not defined QTDIR set QTDIR=C:\Qt\6.6.0\msvc2019_64 -echo QTDIR=%QTDIR% -if exist cmake rd /s /q cmake -md cmake -cd cmake -md build -cd build -cmake -DCMAKE_PREFIX_PATH="%QTDIR%" -DCMAKE_INSTALL_PREFIX="%~dp0cmake\install" -DCMAKE_CONFIGURATION_TYPES=Release;Debug -G"Ninja Multi-Config" -DFRAMELESSHELPER_ENABLE_VCLTL=ON -DFRAMELESSHELPER_ENABLE_YYTHUNKS=ON -DFRAMELESSHELPER_ENABLE_SPECTRE=ON -DFRAMELESSHELPER_ENABLE_EHCONTGUARD=ON -DFRAMELESSHELPER_ENABLE_INTELCET=ON -DFRAMELESSHELPER_ENABLE_INTELJCC=ON -DFRAMELESSHELPER_ENABLE_CFGUARD=ON -DFRAMELESSHELPER_FORCE_LTO=ON "%~dp0.." -cmake --build . --target all --config Release --parallel -cmake --build . --target all --config Debug --parallel -cmake --install . --config Release --strip -cmake --install . --config Debug -goto fin -:fin -endlocal -cd /d "%~dp0" -pause -exit /b 0 diff --git a/include/FramelessHelper/Core/chromepalette.h b/include/FramelessHelper/Core/chromepalette.h index 9e5d382f..eeb42058 100644 --- a/include/FramelessHelper/Core/chromepalette.h +++ b/include/FramelessHelper/Core/chromepalette.h @@ -31,13 +31,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class ChromePalettePrivate; - class FRAMELESSHELPER_CORE_API ChromePalette : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(ChromePalette) - Q_DISABLE_COPY_MOVE(ChromePalette) + FRAMELESSHELPER_PUBLIC_QT_CLASS(ChromePalette) Q_PROPERTY(QColor titleBarActiveBackgroundColor READ titleBarActiveBackgroundColor WRITE setTitleBarActiveBackgroundColor RESET resetTitleBarActiveBackgroundColor @@ -120,9 +117,6 @@ public Q_SLOTS: void closeButtonPressColorChanged(); void titleBarColorChanged(); void chromeButtonColorChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Core/framelesshelper_qt.h b/include/FramelessHelper/Core/framelesshelper_qt.h index c9f506ec..93a2c06c 100644 --- a/include/FramelessHelper/Core/framelesshelper_qt.h +++ b/include/FramelessHelper/Core/framelesshelper_qt.h @@ -26,25 +26,27 @@ #include -FRAMELESSHELPER_BEGIN_NAMESPACE +#if !FRAMELESSHELPER_CONFIG(native_impl) -struct SystemParameters; +FRAMELESSHELPER_BEGIN_NAMESPACE +class FramelessHelperQtPrivate; class FRAMELESSHELPER_CORE_API FramelessHelperQt : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(FramelessHelperQt) + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessHelperQt) public: explicit FramelessHelperQt(QObject *parent = nullptr); ~FramelessHelperQt() override; - static void addWindow(const SystemParameters *params); - static void removeWindow(const WId windowId); + static void addWindow(const QObject *window); + static void removeWindow(const QObject *window); protected: Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; }; FRAMELESSHELPER_END_NAMESPACE + +#endif // !native_impl diff --git a/include/FramelessHelper/Core/framelesshelper_win.h b/include/FramelessHelper/Core/framelesshelper_win.h index 51b76605..7237b8f7 100644 --- a/include/FramelessHelper/Core/framelesshelper_win.h +++ b/include/FramelessHelper/Core/framelesshelper_win.h @@ -29,24 +29,26 @@ #ifdef Q_OS_WINDOWS -FRAMELESSHELPER_BEGIN_NAMESPACE +#if FRAMELESSHELPER_CONFIG(native_impl) -struct SystemParameters; +FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_CORE_API FramelessHelperWin : public QAbstractNativeEventFilter { - Q_DISABLE_COPY_MOVE(FramelessHelperWin) + FRAMELESSHELPER_CLASS(FramelessHelperWin) public: explicit FramelessHelperWin(); ~FramelessHelperWin() override; - static void addWindow(const SystemParameters *params); - static void removeWindow(const WId windowId); + static void addWindow(const QObject *window); + static void removeWindow(const QObject *window); Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override; }; FRAMELESSHELPER_END_NAMESPACE +#endif // native_impl + #endif // Q_OS_WINDOWS diff --git a/include/FramelessHelper/Core/framelesshelper_windows.h b/include/FramelessHelper/Core/framelesshelper_windows.h index eb11d1a1..25af2bb5 100644 --- a/include/FramelessHelper/Core/framelesshelper_windows.h +++ b/include/FramelessHelper/Core/framelesshelper_windows.h @@ -86,6 +86,46 @@ #include +#ifndef SC_SIZE +# define SC_SIZE (0xF000) +#endif + +#ifndef SC_SIZELEFT +# define SC_SIZELEFT (0xF001) +#endif + +#ifndef SC_SIZERIGHT +# define SC_SIZERIGHT (0xF002) +#endif + +#ifndef SC_SIZETOP +# define SC_SIZETOP (0xF003) +#endif + +#ifndef SC_SIZETOPLEFT +# define SC_SIZETOPLEFT (0xF004) +#endif + +#ifndef SC_SIZETOPRIGHT +# define SC_SIZETOPRIGHT (0xF005) +#endif + +#ifndef SC_SIZEBOTTOM +# define SC_SIZEBOTTOM (0xF006) +#endif + +#ifndef SC_SIZEBOTTOMLEFT +# define SC_SIZEBOTTOMLEFT (0xF007) +#endif + +#ifndef SC_SIZEBOTTOMRIGHT +# define SC_SIZEBOTTOMRIGHT (0xF008) +#endif + +#ifndef SC_DRAGMOVE +# define SC_DRAGMOVE (0xF012) +#endif + #ifndef WM_SIZEWAIT # define WM_SIZEWAIT (0x0004) #endif @@ -1102,7 +1142,7 @@ _AdjustWindowRectExForDpi2( EXTERN_C_END -[[maybe_unused]] inline constexpr const int kAutoHideTaskBarThickness = 2; // The thickness of an auto-hide taskbar in pixels. +[[maybe_unused]] inline constexpr const unsigned char kAutoHideTaskBarThickness = 2; // The thickness of an auto-hide taskbar in pixels. [[maybe_unused]] inline constexpr const wchar_t kDwmRegistryKey[] = LR"(Software\Microsoft\Windows\DWM)"; [[maybe_unused]] inline constexpr const wchar_t kPersonalizeRegistryKey[] = LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)"; [[maybe_unused]] inline constexpr const wchar_t kThemeSettingChangeEventName[] = L"ImmersiveColorSet"; @@ -1111,3 +1151,95 @@ EXTERN_C_END [[maybe_unused]] inline constexpr const wchar_t kSystemLightThemeResourceName[] = L"Explorer"; [[maybe_unused]] inline constexpr const wchar_t kDesktopRegistryKey[] = LR"(Control Panel\Desktop)"; [[maybe_unused]] inline constexpr const wchar_t kDarkModePropertyName[] = L"UseImmersiveDarkModeColors"; + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator==(const POINT &lhs, const POINT &rhs) noexcept +{ + return ((lhs.x == rhs.x) && (lhs.y == rhs.y)); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator!=(const POINT &lhs, const POINT &rhs) noexcept +{ + return !operator==(lhs, rhs); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator==(const SIZE &lhs, const SIZE &rhs) noexcept +{ + return ((lhs.cx == rhs.cx) && (lhs.cy == rhs.cy)); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator!=(const SIZE &lhs, const SIZE &rhs) noexcept +{ + return !operator==(lhs, rhs); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator>(const SIZE &lhs, const SIZE &rhs) noexcept +{ + return ((lhs.cx * lhs.cy) > (rhs.cx * rhs.cy)); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator>=(const SIZE &lhs, const SIZE &rhs) noexcept +{ + return (operator>(lhs, rhs) || operator==(lhs, rhs)); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator<(const SIZE &lhs, const SIZE &rhs) noexcept +{ + return (operator!=(lhs, rhs) && !operator>(lhs, rhs)); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator<=(const SIZE &lhs, const SIZE &rhs) noexcept +{ + return (operator<(lhs, rhs) || operator==(lhs, rhs)); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator==(const RECT &lhs, const RECT &rhs) noexcept +{ + return ((lhs.left == rhs.left) && (lhs.top == rhs.top) && (lhs.right == rhs.right) && (lhs.bottom == rhs.bottom)); +} + +[[maybe_unused]] [[nodiscard]] inline constexpr bool operator!=(const RECT &lhs, const RECT &rhs) noexcept +{ + return !operator==(lhs, rhs); +} + +[[nodiscard]] inline constexpr QPoint point2qpoint(const POINT &point) +{ + return QPoint{ int(point.x), int(point.y) }; +} + +[[nodiscard]] inline constexpr POINT qpoint2point(const QPoint &point) +{ + return POINT{ LONG(point.x()), LONG(point.y()) }; +} + +[[nodiscard]] inline constexpr QSize size2qsize(const SIZE &size) +{ + return QSize{ int(size.cx), int(size.cy) }; +} + +[[nodiscard]] inline constexpr SIZE qsize2size(const QSize &size) +{ + return SIZE{ LONG(size.width()), LONG(size.height()) }; +} + +[[nodiscard]] inline constexpr QRect rect2qrect(const RECT &rect) +{ + return QRect{ QPoint{ int(rect.left), int(rect.top) }, QSize{ int(RECT_WIDTH(rect)), int(RECT_HEIGHT(rect)) } }; +} + +[[nodiscard]] inline constexpr RECT qrect2rect(const QRect &qrect) +{ + return RECT{ LONG(qrect.left()), LONG(qrect.top()), LONG(qrect.right()), LONG(qrect.bottom()) }; +} + +[[nodiscard]] inline /*constexpr*/ QString hwnd2str(const WId windowId) +{ + // NULL handle is allowed here. + return FRAMELESSHELPER_STRING_LITERAL("0x") + QString::number(windowId, 16).toUpper().rightJustified(8, u'0'); +} + +[[nodiscard]] inline /*constexpr*/ QString hwnd2str(const HWND hwnd) +{ + // NULL handle is allowed here. + return hwnd2str(reinterpret_cast(hwnd)); +} diff --git a/include/FramelessHelper/Core/framelesshelpercore_global.h b/include/FramelessHelper/Core/framelesshelpercore_global.h index 0e627a21..33b51208 100644 --- a/include/FramelessHelper/Core/framelesshelpercore_global.h +++ b/include/FramelessHelper/Core/framelesshelpercore_global.h @@ -67,11 +67,16 @@ QT_END_NAMESPACE # define Q_OS_WINDOWS // Since 5.14 #endif +#ifndef Q_DISABLE_MOVE +# define Q_DISABLE_MOVE(Class) \ + Class(Class &&) = delete; \ + Class &operator=(Class &&) = delete; +#endif + #ifndef Q_DISABLE_COPY_MOVE // Since 5.13 # define Q_DISABLE_COPY_MOVE(Class) \ Q_DISABLE_COPY(Class) \ - Class(Class &&) = delete; \ - Class &operator=(Class &&) = delete; + Q_DISABLE_MOVE(Class) #endif #if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0)) @@ -253,6 +258,83 @@ QT_END_NAMESPACE } #endif +#ifndef FRAMELESSHELPER_CLASS +# define FRAMELESSHELPER_CLASS(Class) \ + private: \ + Q_DISABLE_COPY(Class) +#endif + +#ifndef FRAMELESSHELPER_CLASS_DPTR +# define FRAMELESSHELPER_CLASS_DPTR(Class) \ + private: \ + Q_DECLARE_PRIVATE(Class) \ + const QScopedPointer d_ptr; +#endif + +#ifndef FRAMELESSHELPER_CLASS_QPTR +# define FRAMELESSHELPER_CLASS_QPTR(Class) \ + private: \ + Q_DECLARE_PUBLIC(Class) \ + public: \ + Class *q_ptr = nullptr; +#endif + +#ifndef FRAMELESSHELPER_PRIVATE_CLASS_GETTER +# define FRAMELESSHELPER_PRIVATE_CLASS_GETTER(Class) \ + public: \ + Q_NODISCARD static Class##Private *get(Class *q); \ + Q_NODISCARD static const Class##Private *get(const Class *q); +#endif + +#ifndef FRAMELESSHELPER_PRIVATE_CLASS_GETTER_IMPL +# define FRAMELESSHELPER_PRIVATE_CLASS_GETTER_IMPL(Class) \ + Class##Private *Class##Private::get(Class *q) { \ + Q_ASSERT(q); \ + return (q ? q->d_func() : nullptr); \ + } \ + const Class##Private *Class##Private::get(const Class *q) { \ + Q_ASSERT(q); \ + return (q ? q->d_func() : nullptr); \ + } +#endif + +#ifndef FRAMELESSHELPER_PUBLIC_CLASS +# define FRAMELESSHELPER_PUBLIC_CLASS(Class) \ + private: \ + FRAMELESSHELPER_CLASS(Class) \ + FRAMELESSHELPER_CLASS_DPTR(Class) +#endif + +#ifndef FRAMELESSHELPER_PRIVATE_CLASS +# define FRAMELESSHELPER_PRIVATE_CLASS(Class) \ + private: \ + FRAMELESSHELPER_CLASS(Class##Private) \ + FRAMELESSHELPER_CLASS_QPTR(Class) \ + FRAMELESSHELPER_PRIVATE_CLASS_GETTER(Class) +#endif + +#ifndef FRAMELESSHELPER_QT_CLASS +# define FRAMELESSHELPER_QT_CLASS(Class) \ + private: \ + FRAMELESSHELPER_CLASS_INFO \ + FRAMELESSHELPER_CLASS(Class) +#endif + +#ifndef FRAMELESSHELPER_PUBLIC_QT_CLASS +# define FRAMELESSHELPER_PUBLIC_QT_CLASS(Class) \ + private: \ + FRAMELESSHELPER_QT_CLASS(Class) \ + FRAMELESSHELPER_CLASS_DPTR(Class) +#endif + +#ifndef FRAMELESSHELPER_PRIVATE_QT_CLASS +# define FRAMELESSHELPER_PRIVATE_QT_CLASS(Class) \ + private: \ + FRAMELESSHELPER_QT_CLASS(Class##Private) \ + FRAMELESSHELPER_CLASS_QPTR(Class) \ + FRAMELESSHELPER_PRIVATE_CLASS_GETTER(Class) +#endif + #if FRAMELESSHELPER_CONFIG(bundle_resource) // Call this function in your main() function if you are using FramelessHelper as a static library, // it can make sure the resources bundled in the static library are correctly initialized. diff --git a/include/FramelessHelper/Core/framelessmanager.h b/include/FramelessHelper/Core/framelessmanager.h index b6ed5bd5..75ae3d55 100644 --- a/include/FramelessHelper/Core/framelessmanager.h +++ b/include/FramelessHelper/Core/framelessmanager.h @@ -28,15 +28,11 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -struct SystemParameters; class FramelessManagerPrivate; - class FRAMELESSHELPER_CORE_API FramelessManager : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(FramelessManager) - Q_DISABLE_COPY_MOVE(FramelessManager) + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessManager) Q_PROPERTY(Global::SystemTheme systemTheme READ systemTheme WRITE setOverrideTheme NOTIFY systemThemeChanged FINAL) Q_PROPERTY(QColor systemAccentColor READ systemAccentColor NOTIFY systemThemeChanged FINAL) Q_PROPERTY(QString wallpaper READ wallpaper NOTIFY wallpaperChanged FINAL) @@ -51,8 +47,8 @@ class FRAMELESSHELPER_CORE_API FramelessManager : public QObject Q_NODISCARD Global::WallpaperAspectStyle wallpaperAspectStyle() const; public Q_SLOTS: - void addWindow(const SystemParameters *params); - void removeWindow(const WId windowId); + Q_NODISCARD bool addWindow(const QObject *window, const WId windowId); + Q_NODISCARD bool removeWindow(const QObject *window); void setOverrideTheme(const Global::SystemTheme theme); Q_SIGNALS: @@ -62,9 +58,6 @@ public Q_SLOTS: private: explicit FramelessManager(QObject *parent = nullptr); ~FramelessManager() override; - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Core/micamaterial.h b/include/FramelessHelper/Core/micamaterial.h index b1920a79..19939a4d 100644 --- a/include/FramelessHelper/Core/micamaterial.h +++ b/include/FramelessHelper/Core/micamaterial.h @@ -31,13 +31,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class MicaMaterialPrivate; - class FRAMELESSHELPER_CORE_API MicaMaterial : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(MicaMaterial) - Q_DECLARE_PRIVATE(MicaMaterial) + FRAMELESSHELPER_PUBLIC_QT_CLASS(MicaMaterial) Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor NOTIFY tintColorChanged FINAL) Q_PROPERTY(qreal tintOpacity READ tintOpacity WRITE setTintOpacity NOTIFY tintOpacityChanged FINAL) @@ -80,9 +77,6 @@ public Q_SLOTS: void noiseOpacityChanged(); void fallbackEnabledChanged(); void shouldRedraw(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Core/private/chromepalette_p.h b/include/FramelessHelper/Core/private/chromepalette_p.h index 9610988e..f18cc5b9 100644 --- a/include/FramelessHelper/Core/private/chromepalette_p.h +++ b/include/FramelessHelper/Core/private/chromepalette_p.h @@ -32,24 +32,17 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class ChromePalette; - class FRAMELESSHELPER_CORE_API ChromePalettePrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(ChromePalette) - Q_DISABLE_COPY_MOVE(ChromePalettePrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(ChromePalette) public: explicit ChromePalettePrivate(ChromePalette *q); ~ChromePalettePrivate() override; - Q_NODISCARD static ChromePalettePrivate *get(ChromePalette *q); - Q_NODISCARD static const ChromePalettePrivate *get(const ChromePalette *q); - Q_SLOT void refresh(); - ChromePalette *q_ptr = nullptr; // System-defined ones: QColor titleBarActiveBackgroundColor_sys = {}; QColor titleBarInactiveBackgroundColor_sys = {}; diff --git a/include/FramelessHelper/Core/private/framelessconfig_p.h b/include/FramelessHelper/Core/private/framelessconfig_p.h index 75ea209f..1f330e71 100644 --- a/include/FramelessHelper/Core/private/framelessconfig_p.h +++ b/include/FramelessHelper/Core/private/framelessconfig_p.h @@ -31,8 +31,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_CORE_API FramelessConfig : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(FramelessConfig) + FRAMELESSHELPER_QT_CLASS(FramelessConfig) public: Q_NODISCARD static FramelessConfig *instance(); diff --git a/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h b/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h index c0d2fa56..4ce2607d 100644 --- a/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h +++ b/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h @@ -25,7 +25,10 @@ #pragma once #include +#include +#include #include +#include QT_BEGIN_NAMESPACE class QScreen; @@ -62,7 +65,7 @@ using GetWidgetHandleCallback = std::function; using ForceChildrenRepaintCallback = std::function; using ResetQtGrabbedControlCallback = std::function; -struct SystemParameters +struct FRAMELESSHELPER_CORE_API FramelessCallbacks { GetWindowFlagsCallback getWindowFlags = nullptr; SetWindowFlagsCallback setWindowFlags = nullptr; @@ -92,29 +95,90 @@ struct SystemParameters GetWidgetHandleCallback getWidgetHandle = nullptr; ForceChildrenRepaintCallback forceChildrenRepaint = nullptr; ResetQtGrabbedControlCallback resetQtGrabbedControl = nullptr; + + FramelessCallbacks(); + virtual ~FramelessCallbacks(); + + using PtrType = std::shared_ptr; + [[nodiscard]] static PtrType create(); + +private: + FRAMELESSHELPER_CLASS(FramelessCallbacks) +}; +using FramelessCallbacksPtr = FramelessCallbacks::PtrType; + +enum class ExtraDataType : quint8 +{ + WindowsUtilities, + LinuxUtilities, + MacOSUtilities, + FramelessWidgetsHelper, + FramelessQuickHelper +}; + +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) +inline uint qHash(const ExtraDataType key, const uint seed = 0) noexcept { + return ::qHash(static_cast(key), seed); +} +#endif + +struct FRAMELESSHELPER_CORE_API FramelessExtraData +{ + FramelessExtraData(); + virtual ~FramelessExtraData(); + + using PtrType = std::shared_ptr; + +private: + FRAMELESSHELPER_CLASS(FramelessExtraData) }; +using FramelessExtraDataPtr = FramelessExtraData::PtrType; +using FramelessExtraDataPtrs = QList; +using FramelessExtraDataHash = QHash; + +struct FRAMELESSHELPER_CORE_API FramelessData +{ + QObject *window = nullptr; + WId windowId = 0; + QObject *internalEventHandler = nullptr; + bool frameless = false; + FramelessCallbacksPtr callbacks = nullptr; + FramelessExtraDataHash extraData = {}; -using FramelessParams = SystemParameters *; -using FramelessParamsConst = const SystemParameters *; -using FramelessParamsRef = SystemParameters &; -using FramelessParamsConstRef = const SystemParameters &; + FramelessData(); + virtual ~FramelessData(); + + using PtrType = std::shared_ptr; + [[nodiscard]] static PtrType create(); + +private: + FRAMELESSHELPER_CLASS(FramelessData) +}; +using FramelessDataPtr = FramelessData::PtrType; +using FramelessDataPtrs = QList; +using FramelessDataHash = QHash; FRAMELESSHELPER_END_NAMESPACE #define DECLARE_SIZE_COMPARE_OPERATORS(Type1, Type2) \ - [[maybe_unused]] [[nodiscard]] static inline constexpr bool operator>(const Type1 &lhs, const Type2 &rhs) noexcept \ + [[maybe_unused]] [[nodiscard]] inline constexpr bool operator>(const Type1 &lhs, const Type2 &rhs) noexcept \ { \ return ((lhs.width() * lhs.height()) > (rhs.width() * rhs.height())); \ } \ - [[maybe_unused]] [[nodiscard]] static inline constexpr bool operator>=(const Type1 &lhs, const Type2 &rhs) noexcept \ + [[maybe_unused]] [[nodiscard]] inline constexpr bool operator>=(const Type1 &lhs, const Type2 &rhs) noexcept \ { \ return (operator>(lhs, rhs) || operator==(lhs, rhs)); \ } \ - [[maybe_unused]] [[nodiscard]] static inline constexpr bool operator<(const Type1 &lhs, const Type2 &rhs) noexcept \ + [[maybe_unused]] [[nodiscard]] inline constexpr bool operator<(const Type1 &lhs, const Type2 &rhs) noexcept \ { \ return (operator!=(lhs, rhs) && !operator>(lhs, rhs)); \ } \ - [[maybe_unused]] [[nodiscard]] static inline constexpr bool operator<=(const Type1 &lhs, const Type2 &rhs) noexcept \ + [[maybe_unused]] [[nodiscard]] inline constexpr bool operator<=(const Type1 &lhs, const Type2 &rhs) noexcept \ { \ return (operator<(lhs, rhs) || operator==(lhs, rhs)); \ } + +DECLARE_SIZE_COMPARE_OPERATORS(QSize, QSize) +DECLARE_SIZE_COMPARE_OPERATORS(QSizeF, QSizeF) +DECLARE_SIZE_COMPARE_OPERATORS(QSize, QSizeF) +DECLARE_SIZE_COMPARE_OPERATORS(QSizeF, QSize) diff --git a/include/FramelessHelper/Core/private/framelessmanager_p.h b/include/FramelessHelper/Core/private/framelessmanager_p.h index 5951a0bb..95e10c8b 100644 --- a/include/FramelessHelper/Core/private/framelessmanager_p.h +++ b/include/FramelessHelper/Core/private/framelessmanager_p.h @@ -30,23 +30,19 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -struct SystemParameters; -class FramelessManager; +struct FramelessData; +using FramelessDataPtr = std::shared_ptr; +class FramelessManager; class FRAMELESSHELPER_CORE_API FramelessManagerPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessManager) - Q_DISABLE_COPY_MOVE(FramelessManagerPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessManager) public: explicit FramelessManagerPrivate(FramelessManager *q); ~FramelessManagerPrivate() override; - Q_NODISCARD static FramelessManagerPrivate *get(FramelessManager *pub); - Q_NODISCARD static const FramelessManagerPrivate *get(const FramelessManager *pub); - static void initializeIconFont(); Q_NODISCARD static QFont getIconFont(); @@ -60,7 +56,12 @@ class FRAMELESSHELPER_CORE_API FramelessManagerPrivate : public QObject void doNotifySystemThemeHasChangedOrNot(); void doNotifyWallpaperHasChangedOrNot(); - FramelessManager *q_ptr = nullptr; + Q_NODISCARD static FramelessDataPtr getData(const QObject *window); + Q_NODISCARD static FramelessDataPtr createData(const QObject *window, const WId windowId); + Q_NODISCARD static WId getWindowId(const QObject *window); + Q_NODISCARD static QObject *getWindow(const WId windowId); + static void updateWindowId(const QObject *window, const WId newWindowId); + Global::SystemTheme systemTheme = Global::SystemTheme::Unknown; std::optional overrideTheme = std::nullopt; QColor accentColor = {}; diff --git a/include/FramelessHelper/Core/private/micamaterial_p.h b/include/FramelessHelper/Core/private/micamaterial_p.h index e90da38c..a7677fae 100644 --- a/include/FramelessHelper/Core/private/micamaterial_p.h +++ b/include/FramelessHelper/Core/private/micamaterial_p.h @@ -32,21 +32,15 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class MicaMaterial; - class FRAMELESSHELPER_CORE_API MicaMaterialPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(MicaMaterialPrivate) - Q_DECLARE_PUBLIC(MicaMaterial) + FRAMELESSHELPER_PRIVATE_QT_CLASS(MicaMaterial) public: explicit MicaMaterialPrivate(MicaMaterial *q); ~MicaMaterialPrivate() override; - Q_NODISCARD static MicaMaterialPrivate *get(MicaMaterial *q); - Q_NODISCARD static const MicaMaterialPrivate *get(const MicaMaterial *q); - Q_NODISCARD static QColor systemFallbackColor(); Q_NODISCARD QPoint mapToWallpaper(const QPoint &pos) const; @@ -60,7 +54,6 @@ class FRAMELESSHELPER_CORE_API MicaMaterialPrivate : public QObject void initialize(); void prepareGraphicsResources(); - MicaMaterial *q_ptr = nullptr; QColor tintColor = {}; qreal tintOpacity = qreal(0); QColor fallbackColor = {}; diff --git a/include/FramelessHelper/Core/private/registrykey_p.h b/include/FramelessHelper/Core/private/registrykey_p.h index 114c80bb..2ceca109 100644 --- a/include/FramelessHelper/Core/private/registrykey_p.h +++ b/include/FramelessHelper/Core/private/registrykey_p.h @@ -60,8 +60,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_CORE_API RegistryKey : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(RegistryKey) + FRAMELESSHELPER_QT_CLASS(RegistryKey) public: explicit RegistryKey(const Global::RegistryRootKey root, const QString &key, QObject *parent = nullptr); diff --git a/include/FramelessHelper/Core/private/scopeguard_p.h b/include/FramelessHelper/Core/private/scopeguard_p.h index 02983e20..0f1cb76a 100644 --- a/include/FramelessHelper/Core/private/scopeguard_p.h +++ b/include/FramelessHelper/Core/private/scopeguard_p.h @@ -37,7 +37,7 @@ using ScopeGuardCallback = std::function; class [[nodiscard]] ScopeGuard { - Q_DISABLE_COPY(ScopeGuard) + FRAMELESSHELPER_CLASS(ScopeGuard) public: ScopeGuard() diff --git a/include/FramelessHelper/Core/private/sysapiloader_p.h b/include/FramelessHelper/Core/private/sysapiloader_p.h index da33d162..e855047e 100644 --- a/include/FramelessHelper/Core/private/sysapiloader_p.h +++ b/include/FramelessHelper/Core/private/sysapiloader_p.h @@ -31,8 +31,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_CORE_API SysApiLoader : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(SysApiLoader) + FRAMELESSHELPER_QT_CLASS(SysApiLoader) public: Q_NODISCARD static SysApiLoader *instance(); diff --git a/include/FramelessHelper/Core/private/windowborderpainter_p.h b/include/FramelessHelper/Core/private/windowborderpainter_p.h index 5037cde5..a494ef46 100644 --- a/include/FramelessHelper/Core/private/windowborderpainter_p.h +++ b/include/FramelessHelper/Core/private/windowborderpainter_p.h @@ -32,22 +32,15 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class WindowBorderPainter; - class FRAMELESSHELPER_CORE_API WindowBorderPainterPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(WindowBorderPainter) - Q_DISABLE_COPY_MOVE(WindowBorderPainterPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(WindowBorderPainter) public: explicit WindowBorderPainterPrivate(WindowBorderPainter *q); ~WindowBorderPainterPrivate() override; - Q_NODISCARD static WindowBorderPainterPrivate *get(WindowBorderPainter *q); - Q_NODISCARD static const WindowBorderPainterPrivate *get(const WindowBorderPainter *q); - - WindowBorderPainter *q_ptr = nullptr; std::optional thickness = std::nullopt; std::optional edges = std::nullopt; std::optional activeColor = std::nullopt; diff --git a/include/FramelessHelper/Core/utils.h b/include/FramelessHelper/Core/utils.h index e922eac1..f726a419 100644 --- a/include/FramelessHelper/Core/utils.h +++ b/include/FramelessHelper/Core/utils.h @@ -37,30 +37,22 @@ QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE -struct SystemParameters; - namespace Utils { -[[nodiscard]] FRAMELESSHELPER_CORE_API - Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos); -[[nodiscard]] FRAMELESSHELPER_CORE_API - Qt::Edges calculateWindowEdges(const QWindow *window, const QPoint &pos); +[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos); +[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::Edges calculateWindowEdges(const QWindow *window, const QPoint &pos); [[nodiscard]] FRAMELESSHELPER_CORE_API bool startSystemMove(QWindow *window, const QPoint &globalPos); [[nodiscard]] FRAMELESSHELPER_CORE_API bool startSystemResize(QWindow *window, const Qt::Edges edges, const QPoint &globalPos); [[nodiscard]] FRAMELESSHELPER_CORE_API QString getSystemButtonGlyph(const Global::SystemButtonType button); [[nodiscard]] FRAMELESSHELPER_CORE_API QWindow *findWindow(const WId windowId); -FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter( - const SystemParameters *params, const bool considerTaskBar); -[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::WindowState windowStatesToWindowState( - const Qt::WindowStates states); +[[nodiscard]] FRAMELESSHELPER_CORE_API bool moveWindowToDesktopCenter(const WId windowId, const bool considerTaskBar); +[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::WindowState windowStatesToWindowState(const Qt::WindowStates states); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isThemeChangeEvent(const QEvent * const event); -[[nodiscard]] FRAMELESSHELPER_CORE_API QColor calculateSystemButtonBackgroundColor( - const Global::SystemButtonType button, const Global::ButtonState state); +[[nodiscard]] FRAMELESSHELPER_CORE_API QColor calculateSystemButtonBackgroundColor(const Global::SystemButtonType button, const Global::ButtonState state); [[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized(); -[[nodiscard]] FRAMELESSHELPER_CORE_API bool - setBlurBehindWindowEnabled(const WId windowId, const Global::BlurMode mode, const QColor &color); +[[nodiscard]] FRAMELESSHELPER_CORE_API bool setBlurBehindWindowEnabled(const WId windowId, const Global::BlurMode mode, const QColor &color); [[nodiscard]] FRAMELESSHELPER_CORE_API QString getWallpaperFilePath(); [[nodiscard]] FRAMELESSHELPER_CORE_API Global::WallpaperAspectStyle getWallpaperAspectStyle(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isBlurBehindWindowSupported(); @@ -100,31 +92,24 @@ FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter( [[nodiscard]] FRAMELESSHELPER_CORE_API bool isFullScreen(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowNoState(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API bool syncWmPaintWithDwm(); -[[nodiscard]] FRAMELESSHELPER_CORE_API bool showSystemMenu( - const WId windowId, const QPoint &pos, - const bool selectFirstEntry, const SystemParameters *params); +[[nodiscard]] FRAMELESSHELPER_CORE_API bool showSystemMenu(const WId windowId, const QPoint &pos, const bool selectFirstEntry); [[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmColorizationColor(bool *opaque = nullptr, bool *ok = nullptr); [[nodiscard]] FRAMELESSHELPER_CORE_API Global::DwmColorizationArea getDwmColorizationArea(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isHighContrastModeEnabled(); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getPrimaryScreenDpi(const bool horizontal); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getWindowDpi(const WId windowId, const bool horizontal); -[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThicknessForDpi - (const bool horizontal, const quint32 dpi); -[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThickness(const WId windowId, - const bool horizontal, - const bool scaled); +[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThicknessForDpi(const bool horizontal, const quint32 dpi); +[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThickness(const WId windowId, const bool horizontal, const bool scaled); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionBarHeightForDpi(const quint32 dpi); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionBarHeight(const WId windowId, const bool scaled); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeightForDpi(const quint32 dpi); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeight(const WId windowId, const bool scaled); [[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThicknessForDpi(const quint32 dpi); -[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId windowId, - const bool scaled); +[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId windowId, const bool scaled); [[nodiscard]] FRAMELESSHELPER_CORE_API bool maybeFixupQtInternals(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized(); -[[nodiscard]] FRAMELESSHELPER_CORE_API bool installWindowProcHook( - const WId windowId, const SystemParameters *params); +[[nodiscard]] FRAMELESSHELPER_CORE_API bool installWindowProcHook(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API bool uninstallWindowProcHook(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API bool setAeroSnappingEnabled(const WId windowId, const bool enable); [[nodiscard]] FRAMELESSHELPER_CORE_API bool tryToEnableHighestDpiAwarenessLevel(); @@ -132,20 +117,17 @@ FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter( [[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode_windows(); [[nodiscard]] FRAMELESSHELPER_CORE_API QColor getAccentColor_windows(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool setCornerStyleForWindow(const WId windowId, const Global::WindowCornerStyle style); -[[nodiscard]] FRAMELESSHELPER_CORE_API bool hideOriginalTitleBarElements - (const WId windowId, const bool disable = true); +[[nodiscard]] FRAMELESSHELPER_CORE_API bool hideOriginalTitleBarElements(const WId windowId, const bool disable = true); [[nodiscard]] FRAMELESSHELPER_CORE_API bool setQtDarkModeAwareEnabled(const bool enable); [[nodiscard]] FRAMELESSHELPER_CORE_API bool refreshWin32ThemeResources(const WId windowId, const bool dark); [[nodiscard]] FRAMELESSHELPER_CORE_API bool enableNonClientAreaDpiScalingForWindow(const WId windowId); -[[nodiscard]] FRAMELESSHELPER_CORE_API - Global::DpiAwareness getDpiAwarenessForCurrentProcess(bool *highest = nullptr); +[[nodiscard]] FRAMELESSHELPER_CORE_API Global::DpiAwareness getDpiAwarenessForCurrentProcess(bool *highest = nullptr); [[nodiscard]] FRAMELESSHELPER_CORE_API bool fixupChildWindowsDpiMessage(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API bool fixupDialogsDpiScaling(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool setDarkModeAllowedForApp(const bool allow = true); [[nodiscard]] FRAMELESSHELPER_CORE_API bool bringWindowToFront(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API QPoint getWindowPlacementOffset(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API QRect getWindowRestoreGeometry(const WId windowId); -[[nodiscard]] FRAMELESSHELPER_CORE_API bool removeMicaWindow(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API quint64 getKeyState(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isValidWindow(const WId windowId, const bool checkVisible, const bool checkTopLevel); [[nodiscard]] FRAMELESSHELPER_CORE_API bool updateFramebufferTransparency(const WId windowId); @@ -156,8 +138,7 @@ FRAMELESSHELPER_CORE_API void printWin32Message(void *msg); #endif // Q_OS_WINDOWS #if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) -[[nodiscard]] FRAMELESSHELPER_CORE_API QScreen *x11_findScreenForVirtualDesktop - (const int virtualDesktopNumber); +[[nodiscard]] FRAMELESSHELPER_CORE_API QScreen *x11_findScreenForVirtualDesktop(const int virtualDesktopNumber); [[nodiscard]] FRAMELESSHELPER_CORE_API x11_return_type x11_appRootWindow(const int screen); [[nodiscard]] FRAMELESSHELPER_CORE_API int x11_appScreen(); [[nodiscard]] FRAMELESSHELPER_CORE_API x11_return_type x11_appTime(); @@ -166,11 +147,8 @@ FRAMELESSHELPER_CORE_API void printWin32Message(void *msg); [[nodiscard]] FRAMELESSHELPER_CORE_API QByteArray x11_nextStartupId(); [[nodiscard]] FRAMELESSHELPER_CORE_API Display *x11_display(); [[nodiscard]] FRAMELESSHELPER_CORE_API xcb_connection_t *x11_connection(); -[[nodiscard]] FRAMELESSHELPER_CORE_API QByteArray getWindowProperty - (const WId windowId, const xcb_atom_t prop, const xcb_atom_t type, const quint32 data_len); -FRAMELESSHELPER_CORE_API void setWindowProperty - (const WId windowId, const xcb_atom_t prop, const xcb_atom_t type, - const void *data, const quint32 data_len, const uint8_t format); +[[nodiscard]] FRAMELESSHELPER_CORE_API QByteArray getWindowProperty(const WId windowId, const xcb_atom_t prop, const xcb_atom_t type, const quint32 data_len); +FRAMELESSHELPER_CORE_API void setWindowProperty(const WId windowId, const xcb_atom_t prop, const xcb_atom_t type, const void *data, const quint32 data_len, const uint8_t format); FRAMELESSHELPER_CORE_API void clearWindowProperty(const WId windowId, const xcb_atom_t prop); [[nodiscard]] FRAMELESSHELPER_CORE_API xcb_atom_t internAtom(const char *name); [[nodiscard]] FRAMELESSHELPER_CORE_API QString getWindowManagerName(); @@ -180,11 +158,9 @@ FRAMELESSHELPER_CORE_API void clearWindowProperty(const WId windowId, const xcb_ FRAMELESSHELPER_CORE_API void openSystemMenu(const WId windowId, const QPoint &globalPos); [[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode_linux(); [[nodiscard]] FRAMELESSHELPER_CORE_API QColor getAccentColor_linux(); -FRAMELESSHELPER_CORE_API void sendMoveResizeMessage - (const WId windowId, const uint32_t action, const QPoint &globalPos, const Qt::MouseButton button = Qt::LeftButton); +FRAMELESSHELPER_CORE_API void sendMoveResizeMessage(const WId windowId, const uint32_t action, const QPoint &globalPos, const Qt::MouseButton button = Qt::LeftButton); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isCustomDecorationSupported(); -[[nodiscard]] FRAMELESSHELPER_CORE_API bool - setPlatformPropertiesForWindow(QWindow *window, const QVariantHash &props); +[[nodiscard]] FRAMELESSHELPER_CORE_API bool setPlatformPropertiesForWindow(QWindow *window, const QVariantHash &props); #endif // Q_OS_LINUX #ifdef Q_OS_MACOS diff --git a/include/FramelessHelper/Core/windowborderpainter.h b/include/FramelessHelper/Core/windowborderpainter.h index 8ce9fd47..084002a8 100644 --- a/include/FramelessHelper/Core/windowborderpainter.h +++ b/include/FramelessHelper/Core/windowborderpainter.h @@ -31,13 +31,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class WindowBorderPainterPrivate; - class FRAMELESSHELPER_CORE_API WindowBorderPainter : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(WindowBorderPainter) - Q_DECLARE_PRIVATE(WindowBorderPainter) + FRAMELESSHELPER_PUBLIC_QT_CLASS(WindowBorderPainter) Q_PROPERTY(int thickness READ thickness WRITE setThickness NOTIFY thicknessChanged FINAL) Q_PROPERTY(Global::WindowEdges edges READ edges WRITE setEdges NOTIFY edgesChanged FINAL) @@ -77,9 +74,6 @@ public Q_SLOTS: void inactiveColorChanged(); void nativeBorderChanged(); void shouldRepaint(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/framelesshelperquick_global.h b/include/FramelessHelper/Quick/framelesshelperquick_global.h index 9351c95f..92488e91 100644 --- a/include/FramelessHelper/Quick/framelesshelperquick_global.h +++ b/include/FramelessHelper/Quick/framelesshelperquick_global.h @@ -84,8 +84,7 @@ FRAMELESSHELPER_QUICK_API void FramelessHelperQuickRegisterTypes(QQmlEngine *); class FRAMELESSHELPER_QUICK_API QuickGlobal : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(QuickGlobal) + FRAMELESSHELPER_QT_CLASS(QuickGlobal) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(FramelessHelperConstants) #endif diff --git a/include/FramelessHelper/Quick/framelessquickhelper.h b/include/FramelessHelper/Quick/framelessquickhelper.h index bf3ebc93..09bf85e2 100644 --- a/include/FramelessHelper/Quick/framelessquickhelper.h +++ b/include/FramelessHelper/Quick/framelessquickhelper.h @@ -36,20 +36,18 @@ class QuickMicaMaterial; #if FRAMELESSHELPER_CONFIG(border_painter) class QuickWindowBorder; #endif -class FramelessQuickHelperPrivate; +class FramelessQuickHelperPrivate; class FRAMELESSHELPER_QUICK_API FramelessQuickHelper : public QQuickItem { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessQuickHelper) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(FramelessHelper) #endif #ifdef QML_ATTACHED QML_ATTACHED(FramelessQuickHelper) #endif - Q_DECLARE_PRIVATE(FramelessQuickHelper) - Q_DISABLE_COPY_MOVE(FramelessQuickHelper) Q_PROPERTY(QQuickItem* titleBarItem READ titleBarItem WRITE setTitleBarItem NOTIFY titleBarItemChanged FINAL) Q_PROPERTY(bool windowFixedSize READ isWindowFixedSize WRITE setWindowFixedSize NOTIFY windowFixedSizeChanged FINAL) Q_PROPERTY(bool blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged FINAL) @@ -109,9 +107,6 @@ public Q_SLOTS: void blurBehindWindowEnabledChanged(); void windowChanged2(); void ready(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/framelessquickutils.h b/include/FramelessHelper/Quick/framelessquickutils.h index ba463cf2..45c51049 100644 --- a/include/FramelessHelper/Quick/framelessquickutils.h +++ b/include/FramelessHelper/Quick/framelessquickutils.h @@ -36,8 +36,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_QUICK_API FramelessQuickUtils : public QObject, public QQmlParserStatus { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(FramelessQuickUtils) + FRAMELESSHELPER_QT_CLASS(FramelessQuickUtils) Q_INTERFACES(QQmlParserStatus) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(FramelessUtils) diff --git a/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p.h b/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p.h index ae72529c..f5b2f749 100644 --- a/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p.h @@ -33,16 +33,13 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FramelessQuickApplicationWindowPrivate; - class FRAMELESSHELPER_QUICK_API FramelessQuickApplicationWindow : public QQuickApplicationWindow { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessQuickApplicationWindow) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(FramelessApplicationWindow) #endif - Q_DECLARE_PRIVATE(FramelessQuickApplicationWindow) - Q_DISABLE_COPY_MOVE(FramelessQuickApplicationWindow) Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL) Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL) Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL) @@ -77,9 +74,6 @@ public Q_SLOTS: void maximizedChanged(); void zoomedChanged(); void fullScreenChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p_p.h b/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p_p.h index 51b6acec..ab9a9762 100644 --- a/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickapplicationwindow_p_p.h @@ -35,23 +35,17 @@ FRAMELESSHELPER_BEGIN_NAMESPACE #if FRAMELESSHELPER_CONFIG(border_painter) class QuickWindowBorder; #endif -class FramelessQuickApplicationWindow; +class FramelessQuickApplicationWindow; class FRAMELESSHELPER_QUICK_API FramelessQuickApplicationWindowPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessQuickApplicationWindow) - Q_DISABLE_COPY_MOVE(FramelessQuickApplicationWindowPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessQuickApplicationWindow) public: explicit FramelessQuickApplicationWindowPrivate(FramelessQuickApplicationWindow *q); ~FramelessQuickApplicationWindowPrivate() override; - Q_NODISCARD static FramelessQuickApplicationWindowPrivate *get(FramelessQuickApplicationWindow *pub); - Q_NODISCARD static const FramelessQuickApplicationWindowPrivate *get(const FramelessQuickApplicationWindow *pub); - - FramelessQuickApplicationWindow *q_ptr = nullptr; QQuickWindow::Visibility savedVisibility = QQuickWindow::Windowed; #if FRAMELESSHELPER_CONFIG(border_painter) QuickWindowBorder *windowBorder = nullptr; diff --git a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h index ce974035..2cc17964 100644 --- a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h @@ -39,23 +39,17 @@ class QuickMicaMaterial; #if FRAMELESSHELPER_CONFIG(border_painter) class QuickWindowBorder; #endif -class FramelessQuickHelper; -struct FramelessQuickHelperData; +class FramelessQuickHelper; class FRAMELESSHELPER_QUICK_API FramelessQuickHelperPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessQuickHelper) - Q_DISABLE_COPY_MOVE(FramelessQuickHelperPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessQuickHelper) public: explicit FramelessQuickHelperPrivate(FramelessQuickHelper *q); ~FramelessQuickHelperPrivate() override; - Q_NODISCARD static FramelessQuickHelperPrivate *get(FramelessQuickHelper *pub); - Q_NODISCARD static const FramelessQuickHelperPrivate *get(const FramelessQuickHelper *pub); - void attach(); void detach(); @@ -83,11 +77,8 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickHelperPrivate : public QObject Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const; Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const; void setSystemButtonState(const QuickGlobal::SystemButtonType button, const QuickGlobal::ButtonState state); - Q_NODISCARD const FramelessQuickHelperData *getWindowData() const; - Q_NODISCARD FramelessQuickHelperData *getWindowDataMutable() const; void rebindWindow(); - FramelessQuickHelper *q_ptr = nullptr; QColor savedWindowBackgroundColor = {}; bool blurBehindWindowEnabled = false; std::optional extendIntoTitleBar = std::nullopt; diff --git a/include/FramelessHelper/Quick/private/framelessquickwindow_p.h b/include/FramelessHelper/Quick/private/framelessquickwindow_p.h index d0f8e64d..40afd29e 100644 --- a/include/FramelessHelper/Quick/private/framelessquickwindow_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickwindow_p.h @@ -33,16 +33,13 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FramelessQuickWindowPrivate; - class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindowQmlImpl { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessQuickWindow) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(FramelessWindow) #endif - Q_DECLARE_PRIVATE(FramelessQuickWindow) - Q_DISABLE_COPY_MOVE(FramelessQuickWindow) Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL) Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL) Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL) @@ -77,9 +74,6 @@ public Q_SLOTS: void maximizedChanged(); void zoomedChanged(); void fullScreenChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h b/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h index ef2ca71c..e645be54 100644 --- a/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h @@ -35,23 +35,17 @@ FRAMELESSHELPER_BEGIN_NAMESPACE #if FRAMELESSHELPER_CONFIG(border_painter) class QuickWindowBorder; #endif -class FramelessQuickWindow; +class FramelessQuickWindow; class FRAMELESSHELPER_QUICK_API FramelessQuickWindowPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessQuickWindow) - Q_DISABLE_COPY_MOVE(FramelessQuickWindowPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessQuickWindow) public: explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q); ~FramelessQuickWindowPrivate() override; - Q_NODISCARD static FramelessQuickWindowPrivate *get(FramelessQuickWindow *pub); - Q_NODISCARD static const FramelessQuickWindowPrivate *get(const FramelessQuickWindow *pub); - - FramelessQuickWindow *q_ptr = nullptr; QQuickWindow::Visibility savedVisibility = QQuickWindow::Windowed; #if FRAMELESSHELPER_CONFIG(border_painter) QuickWindowBorder *windowBorder = nullptr; diff --git a/include/FramelessHelper/Quick/private/quickimageitem_p.h b/include/FramelessHelper/Quick/private/quickimageitem_p.h index 2eec9d06..9e0a5f9c 100644 --- a/include/FramelessHelper/Quick/private/quickimageitem_p.h +++ b/include/FramelessHelper/Quick/private/quickimageitem_p.h @@ -33,11 +33,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_QUICK_API QuickImageItem : public QQuickPaintedItem { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_QT_CLASS(QuickImageItem) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(ImageItem) #endif - Q_DISABLE_COPY_MOVE(QuickImageItem) Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged FINAL) diff --git a/include/FramelessHelper/Quick/private/quickmicamaterial_p.h b/include/FramelessHelper/Quick/private/quickmicamaterial_p.h index 9fd66a34..ea56a117 100644 --- a/include/FramelessHelper/Quick/private/quickmicamaterial_p.h +++ b/include/FramelessHelper/Quick/private/quickmicamaterial_p.h @@ -31,27 +31,21 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class MicaMaterial; -class QuickMicaMaterial; +class QuickMicaMaterial; class FRAMELESSHELPER_QUICK_API QuickMicaMaterialPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(QuickMicaMaterialPrivate) - Q_DECLARE_PUBLIC(QuickMicaMaterial) + FRAMELESSHELPER_PRIVATE_QT_CLASS(QuickMicaMaterial) public: explicit QuickMicaMaterialPrivate(QuickMicaMaterial *q); ~QuickMicaMaterialPrivate() override; - Q_NODISCARD static QuickMicaMaterialPrivate *get(QuickMicaMaterial *q); - Q_NODISCARD static const QuickMicaMaterialPrivate *get(const QuickMicaMaterial *q); - Q_SLOT void rebindWindow(); void initialize(); - QuickMicaMaterial *q_ptr = nullptr; QMetaObject::Connection rootWindowXChangedConnection = {}; QMetaObject::Connection rootWindowYChangedConnection = {}; QMetaObject::Connection rootWindowActiveChangedConnection = {}; diff --git a/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h b/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h index 8370a3fe..b0bc75dd 100644 --- a/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardsystembutton_p.h @@ -40,11 +40,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_QUICK_API QuickStandardSystemButton : public QQuickButton { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_QT_CLASS(QuickStandardSystemButton) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(StandardSystemButton) #endif - Q_DISABLE_COPY_MOVE(QuickStandardSystemButton) Q_PROPERTY(QuickGlobal::SystemButtonType buttonType READ buttonType WRITE setButtonType NOTIFY buttonTypeChanged FINAL) Q_PROPERTY(QString glyph READ glyph WRITE setGlyph NOTIFY glyphChanged FINAL) Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setHoverColor NOTIFY hoverColorChanged FINAL) diff --git a/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h b/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h index 9e243834..2d8681f8 100644 --- a/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h +++ b/include/FramelessHelper/Quick/private/quickstandardtitlebar_p.h @@ -46,11 +46,10 @@ class QuickImageItem; class FRAMELESSHELPER_QUICK_API QuickStandardTitleBar : public QQuickRectangle { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_QT_CLASS(QuickStandardTitleBar) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(StandardTitleBar) #endif // QML_NAMED_ELEMENT - Q_DISABLE_COPY_MOVE(QuickStandardTitleBar) Q_PROPERTY(Qt::Alignment titleLabelAlignment READ titleLabelAlignment WRITE setTitleLabelAlignment NOTIFY titleLabelAlignmentChanged FINAL) Q_PROPERTY(QQuickLabel* titleLabel READ titleLabel CONSTANT FINAL) #if (!defined(Q_OS_MACOS) && FRAMELESSHELPER_CONFIG(system_button)) diff --git a/include/FramelessHelper/Quick/private/quickwindowborder_p.h b/include/FramelessHelper/Quick/private/quickwindowborder_p.h index 48e659a5..74dd31fd 100644 --- a/include/FramelessHelper/Quick/private/quickwindowborder_p.h +++ b/include/FramelessHelper/Quick/private/quickwindowborder_p.h @@ -30,29 +30,23 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -class QuickWindowBorder; class WindowBorderPainter; +class QuickWindowBorder; class FRAMELESSHELPER_QUICK_API QuickWindowBorderPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(QuickWindowBorderPrivate) - Q_DECLARE_PUBLIC(QuickWindowBorder) + FRAMELESSHELPER_PRIVATE_QT_CLASS(QuickWindowBorder) public: explicit QuickWindowBorderPrivate(QuickWindowBorder *q); ~QuickWindowBorderPrivate() override; - Q_NODISCARD static QuickWindowBorderPrivate *get(QuickWindowBorder *q); - Q_NODISCARD static const QuickWindowBorderPrivate *get(const QuickWindowBorder *q); - Q_SLOT void update(); void initialize(); void rebindWindow(); - QuickWindowBorder *q_ptr = nullptr; WindowBorderPainter *borderPainter = nullptr; QMetaObject::Connection activeChangeConnection = {}; QMetaObject::Connection visibilityChangeConnection = {}; diff --git a/include/FramelessHelper/Quick/quickchromepalette.h b/include/FramelessHelper/Quick/quickchromepalette.h index 9b481790..2d1c91b8 100644 --- a/include/FramelessHelper/Quick/quickchromepalette.h +++ b/include/FramelessHelper/Quick/quickchromepalette.h @@ -35,12 +35,11 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_QUICK_API QuickChromePalette : public ChromePalette, public QQmlParserStatus { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_QT_CLASS(QuickChromePalette) + Q_INTERFACES(QQmlParserStatus) #ifdef QML_ANONYMOUS QML_ANONYMOUS #endif - Q_DISABLE_COPY_MOVE(QuickChromePalette) - Q_INTERFACES(QQmlParserStatus) public: explicit QuickChromePalette(QObject *parent = nullptr); diff --git a/include/FramelessHelper/Quick/quickmicamaterial.h b/include/FramelessHelper/Quick/quickmicamaterial.h index f81d9fd4..e1c1431a 100644 --- a/include/FramelessHelper/Quick/quickmicamaterial.h +++ b/include/FramelessHelper/Quick/quickmicamaterial.h @@ -32,16 +32,13 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class QuickMicaMaterialPrivate; - class FRAMELESSHELPER_QUICK_API QuickMicaMaterial : public QQuickPaintedItem { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_PUBLIC_QT_CLASS(QuickMicaMaterial) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(MicaMaterial) #endif - Q_DISABLE_COPY_MOVE(QuickMicaMaterial) - Q_DECLARE_PRIVATE(QuickMicaMaterial) Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor NOTIFY tintColorChanged FINAL) Q_PROPERTY(qreal tintOpacity READ tintOpacity WRITE setTintOpacity NOTIFY tintOpacityChanged FINAL) @@ -81,9 +78,6 @@ class FRAMELESSHELPER_QUICK_API QuickMicaMaterial : public QQuickPaintedItem void itemChange(const ItemChange change, const ItemChangeData &value) override; void classBegin() override; void componentComplete() override; - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/quickwindowborder.h b/include/FramelessHelper/Quick/quickwindowborder.h index edc7124f..c34a9dbc 100644 --- a/include/FramelessHelper/Quick/quickwindowborder.h +++ b/include/FramelessHelper/Quick/quickwindowborder.h @@ -32,16 +32,13 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class QuickWindowBorderPrivate; - class FRAMELESSHELPER_QUICK_API QuickWindowBorder : public QQuickPaintedItem { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO + FRAMELESSHELPER_PUBLIC_QT_CLASS(QuickWindowBorder) #ifdef QML_NAMED_ELEMENT QML_NAMED_ELEMENT(WindowBorder) #endif - Q_DISABLE_COPY_MOVE(QuickWindowBorder) - Q_DECLARE_PRIVATE(QuickWindowBorder) Q_PROPERTY(qreal thickness READ thickness WRITE setThickness NOTIFY thicknessChanged FINAL) Q_PROPERTY(QuickGlobal::WindowEdges edges READ edges WRITE setEdges NOTIFY edgesChanged FINAL) @@ -86,9 +83,6 @@ public Q_SLOTS: void activeColorChanged(); void inactiveColorChanged(); void nativeBorderChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelessdialog.h b/include/FramelessHelper/Widgets/framelessdialog.h index 0c547b59..e09260ee 100644 --- a/include/FramelessHelper/Widgets/framelessdialog.h +++ b/include/FramelessHelper/Widgets/framelessdialog.h @@ -32,20 +32,14 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FramelessDialogPrivate; - class FRAMELESSHELPER_WIDGETS_API FramelessDialog : public QDialog { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(FramelessDialog) - Q_DISABLE_COPY_MOVE(FramelessDialog) + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessDialog) public: explicit FramelessDialog(QWidget *parent = nullptr); ~FramelessDialog() override; - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelessmainwindow.h b/include/FramelessHelper/Widgets/framelessmainwindow.h index 5e4a52f4..edb7aa20 100644 --- a/include/FramelessHelper/Widgets/framelessmainwindow.h +++ b/include/FramelessHelper/Widgets/framelessmainwindow.h @@ -32,13 +32,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FramelessMainWindowPrivate; - class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(FramelessMainWindow) - Q_DISABLE_COPY_MOVE(FramelessMainWindow) + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessMainWindow) Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL) Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL) Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL) @@ -58,9 +55,6 @@ public Q_SLOTS: void hiddenChanged(); void normalChanged(); void zoomedChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelesswidget.h b/include/FramelessHelper/Widgets/framelesswidget.h index f9fb997a..56f6c7fa 100644 --- a/include/FramelessHelper/Widgets/framelesswidget.h +++ b/include/FramelessHelper/Widgets/framelesswidget.h @@ -32,13 +32,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FramelessWidgetPrivate; - class FRAMELESSHELPER_WIDGETS_API FramelessWidget : public QWidget { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(FramelessWidget) - Q_DISABLE_COPY_MOVE(FramelessWidget) + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessWidget) Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL) Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL) Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL) @@ -58,9 +55,6 @@ public Q_SLOTS: void hiddenChanged(); void normalChanged(); void zoomedChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelesswidgetshelper.h b/include/FramelessHelper/Widgets/framelesswidgetshelper.h index 58128af3..4d8a95ba 100644 --- a/include/FramelessHelper/Widgets/framelesswidgetshelper.h +++ b/include/FramelessHelper/Widgets/framelesswidgetshelper.h @@ -35,14 +35,12 @@ class MicaMaterial; #if FRAMELESSHELPER_CONFIG(border_painter) class WindowBorderPainter; #endif -class FramelessWidgetsHelperPrivate; +class FramelessWidgetsHelperPrivate; class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelper : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(FramelessWidgetsHelper) - Q_DISABLE_COPY_MOVE(FramelessWidgetsHelper) + FRAMELESSHELPER_PUBLIC_QT_CLASS(FramelessWidgetsHelper) Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL) Q_PROPERTY(bool windowFixedSize READ isWindowFixedSize WRITE setWindowFixedSize NOTIFY windowFixedSizeChanged FINAL) Q_PROPERTY(bool blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged FINAL) @@ -96,9 +94,6 @@ public Q_SLOTS: void blurBehindWindowEnabledChanged(); void windowChanged(); void ready(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/framelessdialog_p.h b/include/FramelessHelper/Widgets/private/framelessdialog_p.h index 89d28173..4ca5789e 100644 --- a/include/FramelessHelper/Widgets/private/framelessdialog_p.h +++ b/include/FramelessHelper/Widgets/private/framelessdialog_p.h @@ -30,24 +30,18 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -class FramelessDialog; class WidgetsSharedHelper; +class FramelessDialog; class FRAMELESSHELPER_WIDGETS_API FramelessDialogPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessDialog) - Q_DISABLE_COPY_MOVE(FramelessDialogPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessDialog) public: explicit FramelessDialogPrivate(FramelessDialog *q); ~FramelessDialogPrivate() override; - Q_NODISCARD static FramelessDialogPrivate *get(FramelessDialog *pub); - Q_NODISCARD static const FramelessDialogPrivate *get(const FramelessDialog *pub); - - FramelessDialog *q_ptr = nullptr; WidgetsSharedHelper *sharedHelper = nullptr; }; diff --git a/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h b/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h index 3608af52..0beff06d 100644 --- a/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h +++ b/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h @@ -30,24 +30,18 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -class FramelessMainWindow; class WidgetsSharedHelper; +class FramelessMainWindow; class FRAMELESSHELPER_WIDGETS_API FramelessMainWindowPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessMainWindow) - Q_DISABLE_COPY_MOVE(FramelessMainWindowPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessMainWindow) public: explicit FramelessMainWindowPrivate(FramelessMainWindow *q); ~FramelessMainWindowPrivate() override; - Q_NODISCARD static FramelessMainWindowPrivate *get(FramelessMainWindow *pub); - Q_NODISCARD static const FramelessMainWindowPrivate *get(const FramelessMainWindow *pub); - - FramelessMainWindow *q_ptr = nullptr; Qt::WindowState savedWindowState = Qt::WindowNoState; WidgetsSharedHelper *sharedHelper = nullptr; }; diff --git a/include/FramelessHelper/Widgets/private/framelesswidget_p.h b/include/FramelessHelper/Widgets/private/framelesswidget_p.h index 5a15e1f9..aebb0545 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidget_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidget_p.h @@ -30,24 +30,18 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -class FramelessWidget; class WidgetsSharedHelper; +class FramelessWidget; class FRAMELESSHELPER_WIDGETS_API FramelessWidgetPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessWidget) - Q_DISABLE_COPY_MOVE(FramelessWidgetPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessWidget) public: explicit FramelessWidgetPrivate(FramelessWidget *q); ~FramelessWidgetPrivate() override; - Q_NODISCARD static FramelessWidgetPrivate *get(FramelessWidget *pub); - Q_NODISCARD static const FramelessWidgetPrivate *get(const FramelessWidget *pub); - - FramelessWidget *q_ptr = nullptr; Qt::WindowState savedWindowState = Qt::WindowNoState; WidgetsSharedHelper *sharedHelper = nullptr; }; diff --git a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h index 224192a0..471e8bd9 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h @@ -36,24 +36,18 @@ class MicaMaterial; #if FRAMELESSHELPER_CONFIG(border_painter) class WindowBorderPainter; #endif -class FramelessWidgetsHelper; -struct FramelessWidgetsHelperData; class WidgetsSharedHelper; +class FramelessWidgetsHelper; class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelperPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(FramelessWidgetsHelper) - Q_DISABLE_COPY_MOVE(FramelessWidgetsHelperPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(FramelessWidgetsHelper) public: explicit FramelessWidgetsHelperPrivate(FramelessWidgetsHelper *q); ~FramelessWidgetsHelperPrivate() override; - Q_NODISCARD static FramelessWidgetsHelperPrivate *get(FramelessWidgetsHelper *pub); - Q_NODISCARD static const FramelessWidgetsHelperPrivate *get(const FramelessWidgetsHelper *pub); - void attach(); void detach(); @@ -83,10 +77,7 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelperPrivate : public QObject Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const; void setSystemButtonState(const Global::SystemButtonType button, const Global::ButtonState state); Q_NODISCARD QWidget *findTopLevelWindow() const; - Q_NODISCARD const FramelessWidgetsHelperData *getWindowData() const; - Q_NODISCARD FramelessWidgetsHelperData *getWindowDataMutable() const; - FramelessWidgetsHelper *q_ptr = nullptr; QColor savedWindowBackgroundColor = {}; bool blurBehindWindowEnabled = false; QPointer window = nullptr; diff --git a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h index 060e9f5a..976c56f5 100644 --- a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h +++ b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h @@ -32,24 +32,17 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class StandardSystemButton; - class FRAMELESSHELPER_WIDGETS_API StandardSystemButtonPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(StandardSystemButton) - Q_DISABLE_COPY_MOVE(StandardSystemButtonPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(StandardSystemButton) public: explicit StandardSystemButtonPrivate(StandardSystemButton *q); ~StandardSystemButtonPrivate() override; - Q_NODISCARD static StandardSystemButtonPrivate *get(StandardSystemButton *pub); - Q_NODISCARD static const StandardSystemButtonPrivate *get(const StandardSystemButton *pub); - Q_NODISCARD static QSize getRecommendedButtonSize(); - StandardSystemButton *q_ptr = nullptr; Global::SystemButtonType buttonType = Global::SystemButtonType::Unknown; QString glyph = {}; QColor hoverColor = {}; diff --git a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h index 27837752..a7a834e4 100644 --- a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h +++ b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h @@ -40,14 +40,12 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class StandardSystemButton; #endif class ChromePalette; -class StandardTitleBar; +class StandardTitleBar; class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PUBLIC(StandardTitleBar) - Q_DISABLE_COPY_MOVE(StandardTitleBarPrivate) + FRAMELESSHELPER_PRIVATE_QT_CLASS(StandardTitleBar) public: struct FontMetrics @@ -60,9 +58,6 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject explicit StandardTitleBarPrivate(StandardTitleBar *q); ~StandardTitleBarPrivate() override; - Q_NODISCARD static StandardTitleBarPrivate *get(StandardTitleBar *pub); - Q_NODISCARD static const StandardTitleBarPrivate *get(const StandardTitleBar *pub); - Q_NODISCARD QRect windowIconRect() const; Q_NODISCARD bool windowIconVisible_real() const; Q_NODISCARD bool isInTitleBarIconArea(const QPoint &pos) const; @@ -79,7 +74,6 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject void initialize(); - StandardTitleBar *q_ptr = nullptr; #if (!defined(Q_OS_MACOS) && FRAMELESSHELPER_CONFIG(system_button)) StandardSystemButton *minimizeButton = nullptr; StandardSystemButton *maximizeButton = nullptr; diff --git a/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h b/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h index 497b7dfd..6b567789 100644 --- a/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h +++ b/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h @@ -39,8 +39,7 @@ class WindowBorderPainter; class FRAMELESSHELPER_WIDGETS_API WidgetsSharedHelper : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(WidgetsSharedHelper) + FRAMELESSHELPER_QT_CLASS(WidgetsSharedHelper) #if FRAMELESSHELPER_CONFIG(mica_material) Q_PROPERTY(bool micaEnabled READ isMicaEnabled WRITE setMicaEnabled NOTIFY micaEnabledChanged FINAL) #endif diff --git a/include/FramelessHelper/Widgets/standardsystembutton.h b/include/FramelessHelper/Widgets/standardsystembutton.h index cdaacd7e..7b8b7282 100644 --- a/include/FramelessHelper/Widgets/standardsystembutton.h +++ b/include/FramelessHelper/Widgets/standardsystembutton.h @@ -32,13 +32,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class StandardSystemButtonPrivate; - class FRAMELESSHELPER_WIDGETS_API StandardSystemButton : public QPushButton { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(StandardSystemButton) - Q_DISABLE_COPY_MOVE(StandardSystemButton) + FRAMELESSHELPER_PUBLIC_QT_CLASS(StandardSystemButton) Q_PROPERTY(Global::SystemButtonType buttonType READ buttonType WRITE setButtonType NOTIFY buttonTypeChanged FINAL) Q_PROPERTY(QString glyph READ glyph WRITE setGlyph NOTIFY glyphChanged FINAL) Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setHoverColor NOTIFY hoverColorChanged FINAL) @@ -89,9 +86,6 @@ public Q_SLOTS: void inactiveForegroundColorChanged(); void activeChanged(); void glyphSizeChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/standardtitlebar.h b/include/FramelessHelper/Widgets/standardtitlebar.h index 4ea1f499..1e8f77b3 100644 --- a/include/FramelessHelper/Widgets/standardtitlebar.h +++ b/include/FramelessHelper/Widgets/standardtitlebar.h @@ -37,13 +37,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class StandardTitleBarPrivate; - class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DECLARE_PRIVATE(StandardTitleBar) - Q_DISABLE_COPY_MOVE(StandardTitleBar) + FRAMELESSHELPER_PUBLIC_QT_CLASS(StandardTitleBar) Q_PROPERTY(Qt::Alignment titleLabelAlignment READ titleLabelAlignment WRITE setTitleLabelAlignment NOTIFY titleLabelAlignmentChanged FINAL) #if (!defined(Q_OS_MACOS) && FRAMELESSHELPER_CONFIG(system_button)) Q_PROPERTY(StandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL) @@ -104,9 +101,6 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget void windowIconSizeChanged(); void windowIconVisibleChanged(); void titleFontChanged(); - -private: - QScopedPointer d_ptr; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9afd1162..139fe3d0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -35,18 +35,18 @@ if(UNIX AND NOT APPLE) endif() find_package(X11 QUIET COMPONENTS xcb) if(TARGET X11::xcb) - message("Found system XCB. The XCB wrapper will be disabled.") + message(STATUS "--- Found system XCB. The XCB wrapper will be disabled.") else() - message("System XCB not found. The XCB wrapper will be used instead.") + message(STATUS "--- System XCB not found. The XCB wrapper will be used instead.") endif() find_package(PkgConfig QUIET) if(PkgConfig_FOUND) pkg_check_modules(GTK3 QUIET IMPORTED_TARGET gtk+-3.0) endif() if(TARGET PkgConfig::GTK3) - message("Found system GTK. The GTK wrapper will be disabled.") + message(STATUS "--- Found system GTK. The GTK wrapper will be disabled.") else() - message("System GTK not found. The GTK wrapper will be used instead.") + message(STATUS "--- System GTK not found. The GTK wrapper will be used instead.") endif() endif() @@ -61,14 +61,12 @@ set(PUBLIC_HEADERS ${FRAMELESSHELPER_VERSION_FILE} ${FRAMELESSHELPER_CONFIG_FILE} ${INCLUDE_PREFIX}/framelesshelpercore_global.h - ${INCLUDE_PREFIX}/framelesshelper_qt.h ${INCLUDE_PREFIX}/framelessmanager.h ${INCLUDE_PREFIX}/utils.h ) set(PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/Global - ${INCLUDE_PREFIX}/FramelessHelper_Qt ${INCLUDE_PREFIX}/FramelessManager ${INCLUDE_PREFIX}/Utils ) @@ -84,7 +82,6 @@ set(PRIVATE_HEADERS set(SOURCES utils.cpp - framelesshelper_qt.cpp framelessmanager.cpp framelessconfig.cpp sysapiloader.cpp @@ -92,14 +89,8 @@ set(SOURCES ) if(WIN32) - list(APPEND PUBLIC_HEADERS - ${INCLUDE_PREFIX}/framelesshelper_windows.h - ${INCLUDE_PREFIX}/framelesshelper_win.h - ) - list(APPEND PUBLIC_HEADERS_ALIAS - ${INCLUDE_PREFIX}/FramelessHelper_Windows - ${INCLUDE_PREFIX}/FramelessHelper_Win - ) + list(APPEND PUBLIC_HEADERS ${INCLUDE_PREFIX}/framelesshelper_windows.h) + list(APPEND PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/FramelessHelper_Windows) list(APPEND PRIVATE_HEADERS ${INCLUDE_PREFIX}/private/registrykey_p.h ${INCLUDE_PREFIX}/private/winverhelper_p.h @@ -107,25 +98,35 @@ if(WIN32) list(APPEND SOURCES registrykey.cpp utils_win.cpp - framelesshelper_win.cpp winverhelper.cpp platformsupport_win.cpp ) elseif(APPLE) list(APPEND SOURCES utils_mac.mm) elseif(UNIX) - list(APPEND PUBLIC_HEADERS - ${INCLUDE_PREFIX}/framelesshelper_linux.h - ) - list(APPEND PUBLIC_HEADERS_ALIAS - ${INCLUDE_PREFIX}/FramelessHelper_Linux - ) + list(APPEND PUBLIC_HEADERS ${INCLUDE_PREFIX}/framelesshelper_linux.h) + list(APPEND PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/FramelessHelper_Linux) list(APPEND SOURCES utils_linux.cpp platformsupport_linux.cpp ) endif() +if(FRAMELESSHELPER_NATIVE_IMPL) + if(WIN32) + list(APPEND PUBLIC_HEADERS ${INCLUDE_PREFIX}/framelesshelper_win.h) + list(APPEND PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/FramelessHelper_Win) + list(APPEND SOURCES framelesshelper_win.cpp) + elseif(APPLE) + elseif(UNIX) + else() + endif() +else() + list(APPEND PUBLIC_HEADERS ${INCLUDE_PREFIX}/framelesshelper_qt.h) + list(APPEND PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/FramelessHelper_Qt) + list(APPEND SOURCES framelesshelper_qt.cpp) +endif() + if(NOT FRAMELESSHELPER_NO_TITLEBAR) list(APPEND PUBLIC_HEADERS ${INCLUDE_PREFIX}/chromepalette.h) list(APPEND PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/ChromePalette) @@ -158,7 +159,7 @@ if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC) COPYRIGHT "MIT License" ORIGINAL_FILENAME "${SUB_MODULE_FULL_NAME}.dll" PRODUCT "${PROJECT_NAME}" - COMMENTS "Built from commit ${PROJECT_VERSION_COMMIT} on ${PROJECT_COMPILE_DATETIME} (UTC)." + COMMENTS "Who don't love Raiden Shogun ?" LIBRARY ) endif() diff --git a/src/core/framelessconfig.cpp b/src/core/framelessconfig.cpp index fdfaf736..575ebaa8 100644 --- a/src/core/framelessconfig.cpp +++ b/src/core/framelessconfig.cpp @@ -85,14 +85,14 @@ Q_GLOBAL_STATIC(FramelessConfigData, g_framelessConfigData) static inline void warnInappropriateOptions() { const FramelessConfig * const cfg = FramelessConfig::instance(); + if (cfg->isSet(Option::UseCrossPlatformQtImplementation)) { + WARNING << "Option::UseCrossPlatformQtImplementation is deprecated and has no effect now. It will be removed in a future version."; + } #ifdef Q_OS_WINDOWS if (cfg->isSet(Option::DisableWindowsSnapLayout)) { - WARNING << "Option::DisableWindowsSnapLayout is deprecated and will removed in a future version. It has not effect now."; + WARNING << "Option::DisableWindowsSnapLayout is deprecated and has no effect now. It will be removed in a future version."; } #else - if (cfg->isSet(Option::UseCrossPlatformQtImplementation)) { - WARNING << "Option::UseCrossPlatformQtImplementation is default on non-Windows platforms."; - } if (cfg->isSet(Option::ForceHideWindowFrameBorder)) { WARNING << "Option::ForceHideWindowFrameBorder is only available on Windows."; } diff --git a/src/core/framelesshelper_qt.cpp b/src/core/framelesshelper_qt.cpp index a5e663a5..a9667fd3 100644 --- a/src/core/framelesshelper_qt.cpp +++ b/src/core/framelesshelper_qt.cpp @@ -23,6 +23,9 @@ */ #include "framelesshelper_qt.h" + +#if !FRAMELESSHELPER_CONFIG(native_impl) + #include "framelessmanager.h" #include "framelessmanager_p.h" #include "framelessconfig_p.h" @@ -49,40 +52,80 @@ FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -struct FramelessQtHelperData +struct FramelessDataQt : public FramelessData { - SystemParameters params = {}; - FramelessHelperQt *eventFilter = nullptr; + FramelessHelperQt *framelessHelperImpl = nullptr; bool cursorShapeChanged = false; bool leftButtonPressed = false; + + FramelessDataQt(); + ~FramelessDataQt() override; }; +using FramelessDataQtPtr = std::shared_ptr; -using FramelessQtHelperInternal = QHash; +[[nodiscard]] static inline FramelessDataQtPtr tryGetData(const QObject *window) +{ + Q_ASSERT(window); + if (!window) { + return nullptr; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data) { + return nullptr; + } + return std::dynamic_pointer_cast(data); +} + +class FramelessHelperQtPrivate +{ + FRAMELESSHELPER_PRIVATE_CLASS(FramelessHelperQt) -Q_GLOBAL_STATIC(FramelessQtHelperInternal, g_framelessQtHelperData) +public: + explicit FramelessHelperQtPrivate(FramelessHelperQt *q); + ~FramelessHelperQtPrivate(); + + const QObject *window = nullptr; +}; -FramelessHelperQt::FramelessHelperQt(QObject *parent) : QObject(parent) {} +FramelessDataQt::FramelessDataQt() = default; + +FramelessDataQt::~FramelessDataQt() = default; + +[[nodiscard]] FramelessDataPtr FramelessData::create() +{ + return std::make_shared(); +} + +FramelessHelperQtPrivate::FramelessHelperQtPrivate(FramelessHelperQt *q) : q_ptr(q) +{ + Q_ASSERT(q_ptr); +} + +FramelessHelperQtPrivate::~FramelessHelperQtPrivate() = default; + +FramelessHelperQt::FramelessHelperQt(QObject *parent) : QObject(parent), d_ptr(new FramelessHelperQtPrivate(this)) +{ +} FramelessHelperQt::~FramelessHelperQt() = default; -void FramelessHelperQt::addWindow(FramelessParamsConst params) +void FramelessHelperQt::addWindow(const QObject *window) { - Q_ASSERT(params); - if (!params) { + Q_ASSERT(window); + if (!window) { + return; + } + const FramelessDataQtPtr data = tryGetData(window); + if (!data || data->frameless || !data->callbacks) { return; } - const WId windowId = params->getWindowId(); - const auto it = g_framelessQtHelperData()->constFind(windowId); - if (it != g_framelessQtHelperData()->constEnd()) { + QWindow *qWindow = data->callbacks->getWindowHandle(); + Q_ASSERT(qWindow); + if (!qWindow) { return; } - FramelessQtHelperData data = {}; - data.params = *params; - QWindow *window = params->getWindowHandle(); - // Give it a parent so that it can be automatically deleted by Qt. - data.eventFilter = new FramelessHelperQt(window); - g_framelessQtHelperData()->insert(windowId, data); - const auto shouldApplyFramelessFlag = []() -> bool { + data->frameless = true; + static const auto shouldApplyFramelessFlag = []() -> bool { #ifdef Q_OS_MACOS return false; #elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) @@ -92,35 +135,47 @@ void FramelessHelperQt::addWindow(FramelessParamsConst params) #endif // Q_OS_MACOS }(); #if (defined(Q_OS_MACOS) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))) - window->setProperty("_q_mac_wantsLayer", 1); + qWindow->setProperty("_q_mac_wantsLayer", 1); #endif // (defined(Q_OS_MACOS) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))) if (shouldApplyFramelessFlag) { - params->setWindowFlags(params->getWindowFlags() | Qt::FramelessWindowHint); + data->callbacks->setWindowFlags(data->callbacks->getWindowFlags() | Qt::FramelessWindowHint); } else { #if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) - std::ignore = Utils::tryHideSystemTitleBar(windowId, true); + std::ignore = Utils::tryHideSystemTitleBar(data->callbacks->getWindowId(), true); #elif defined(Q_OS_MACOS) - Utils::setSystemTitleBarVisible(windowId, false); + Utils::setSystemTitleBarVisible(data->callbacks->getWindowId(), false); #endif // Q_OS_LINUX } - window->installEventFilter(data.eventFilter); + if (!data->framelessHelperImpl) { + data->framelessHelperImpl = new FramelessHelperQt(qWindow); + data->framelessHelperImpl->d_func()->window = window; + qWindow->installEventFilter(data->framelessHelperImpl); + } FramelessHelperEnableThemeAware(); } -void FramelessHelperQt::removeWindow(const WId windowId) +void FramelessHelperQt::removeWindow(const QObject *window) { - Q_ASSERT(windowId); - if (!windowId) { + Q_ASSERT(window); + if (!window) { return; } - const auto it = g_framelessQtHelperData()->constFind(windowId); - if (it == g_framelessQtHelperData()->constEnd()) { + const FramelessDataQtPtr data = tryGetData(window); + if (!data || !data->frameless || !data->callbacks) { return; } - g_framelessQtHelperData()->erase(it); + if (data->framelessHelperImpl) { + QWindow *qWindow = data->callbacks->getWindowHandle(); + Q_ASSERT(qWindow); + if (qWindow) { + qWindow->removeEventFilter(data->framelessHelperImpl); + delete data->framelessHelperImpl; + data->framelessHelperImpl = nullptr; + } + } #ifdef Q_OS_MACOS - Utils::removeWindowProxy(windowId); -#endif + Utils::removeWindowProxy(data->callbacks->getWindowId()); +#endif // Q_OS_MACOS } bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) @@ -131,24 +186,22 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) return false; } #if (QT_VERSION < QT_VERSION_CHECK(6, 5, 0)) - // First detect whether we got a theme change event or not, if so, - // inform the user the system theme has changed. if (Utils::isThemeChangeEvent(event)) { // Sometimes the FramelessManager instance may be destroyed already. - if (FramelessManager * const manager = FramelessManager::instance()) { - if (FramelessManagerPrivate * const managerPriv = FramelessManagerPrivate::get(manager)) { + if (FramelessManager *manager = FramelessManager::instance()) { + if (FramelessManagerPrivate *managerPriv = FramelessManagerPrivate::get(manager)) { managerPriv->notifySystemThemeHasChangedOrNot(); } } - return QObject::eventFilter(object, event); + return false; } #endif // (QT_VERSION < QT_VERSION_CHECK(6, 5, 0)) - // We are only interested in events that are dispatched to top level windows. - if (!object->isWindowType()) { - return QObject::eventFilter(object, event); + Q_D(FramelessHelperQt); + if (!d->window || !object->isWindowType()) { + return false; } const QEvent::Type type = event->type(); - // We are only interested in some specific mouse events (plus DPR change event). + // We are only interested in some specific mouse events (plus the DPR change event). if ((type != QEvent::MouseButtonPress) && (type != QEvent::MouseButtonRelease) && (type != QEvent::MouseButtonDblClick) && (type != QEvent::MouseMove) #if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) @@ -157,25 +210,22 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) && (type != QEvent::ScreenChangeInternal) // Qt's internal event to notify screen change and DPR change. #endif // (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) ) { - return QObject::eventFilter(object, event); + return false; } - const auto window = qobject_cast(object); - const WId windowId = window->winId(); - const auto it = g_framelessQtHelperData()->find(windowId); - if (it == g_framelessQtHelperData()->end()) { - return QObject::eventFilter(object, event); + const FramelessDataQtPtr data = tryGetData(d->window); + if (!data || !data->frameless || !data->callbacks) { + return false; } - const FramelessQtHelperData &data = it.value(); - FramelessQtHelperData &muData = it.value(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) if (type == QEvent::DevicePixelRatioChange) #else // QT_VERSION < QT_VERSION_CHECK(6, 6, 0) if (type == QEvent::ScreenChangeInternal) #endif // (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) { - data.params.forceChildrenRepaint(500); - return QObject::eventFilter(object, event); + data->callbacks->forceChildrenRepaint(500); + return false; } + const auto qWindow = qobject_cast(object); const auto mouseEvent = static_cast(event); const Qt::MouseButton button = mouseEvent->button(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) @@ -185,64 +235,63 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) const QPoint scenePos = mouseEvent->windowPos().toPoint(); const QPoint globalPos = mouseEvent->screenPos().toPoint(); #endif - const bool windowFixedSize = data.params.isWindowFixedSize(); - const bool ignoreThisEvent = data.params.shouldIgnoreMouseEvents(scenePos); - const bool insideTitleBar = data.params.isInsideTitleBarDraggableArea(scenePos); - const bool dontOverrideCursor = data.params.getProperty(kDontOverrideCursorVar, false).toBool(); - const bool dontToggleMaximize = data.params.getProperty(kDontToggleMaximizeVar, false).toBool(); + const bool windowFixedSize = data->callbacks->isWindowFixedSize(); + const bool ignoreThisEvent = data->callbacks->shouldIgnoreMouseEvents(scenePos); + const bool insideTitleBar = data->callbacks->isInsideTitleBarDraggableArea(scenePos); + const bool dontOverrideCursor = data->callbacks->getProperty(kDontOverrideCursorVar, false).toBool(); + const bool dontToggleMaximize = data->callbacks->getProperty(kDontToggleMaximizeVar, false).toBool(); switch (type) { - case QEvent::MouseButtonPress: { + case QEvent::MouseButtonPress: if (button == Qt::LeftButton) { - muData.leftButtonPressed = true; + data->leftButtonPressed = true; if (!windowFixedSize) { - const Qt::Edges edges = Utils::calculateWindowEdges(window, scenePos); + const Qt::Edges edges = Utils::calculateWindowEdges(qWindow, scenePos); if (edges != Qt::Edges{}) { - std::ignore = Utils::startSystemResize(window, edges, globalPos); + std::ignore = Utils::startSystemResize(qWindow, edges, globalPos); event->accept(); return true; } } } - } break; - case QEvent::MouseButtonRelease: { + break; + case QEvent::MouseButtonRelease: if (button == Qt::LeftButton) { - muData.leftButtonPressed = false; - } - if (button == Qt::RightButton) { + data->leftButtonPressed = false; + } else if (button == Qt::RightButton) { if (!ignoreThisEvent && insideTitleBar) { - data.params.showSystemMenu(globalPos); + data->callbacks->showSystemMenu(globalPos); event->accept(); return true; } } - } break; - case QEvent::MouseButtonDblClick: { + break; + case QEvent::MouseButtonDblClick: if (!dontToggleMaximize && (button == Qt::LeftButton) && !windowFixedSize && !ignoreThisEvent && insideTitleBar) { Qt::WindowState newWindowState = Qt::WindowNoState; - if (data.params.getWindowState() != Qt::WindowMaximized) { + if (data->callbacks->getWindowState() != Qt::WindowMaximized) { newWindowState = Qt::WindowMaximized; } - data.params.setWindowState(newWindowState); + data->callbacks->setWindowState(newWindowState); event->accept(); return true; } - } break; + break; case QEvent::MouseMove: { if (!dontOverrideCursor && !windowFixedSize) { - const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos); + const Qt::CursorShape cs = Utils::calculateCursorShape(qWindow, scenePos); if (cs == Qt::ArrowCursor) { - if (data.cursorShapeChanged) { - data.params.unsetCursor(); - muData.cursorShapeChanged = false; + if (data->cursorShapeChanged) { + data->callbacks->unsetCursor(); + data->cursorShapeChanged = false; } } else { - data.params.setCursor(cs); - muData.cursorShapeChanged = true; + data->callbacks->setCursor(cs); + data->cursorShapeChanged = true; } } - if (data.leftButtonPressed) { + if (data->leftButtonPressed) { if (!ignoreThisEvent && insideTitleBar) { - std::ignore = Utils::startSystemMove(window, globalPos); + std::ignore = Utils::startSystemMove(qWindow, globalPos); event->accept(); return true; } @@ -251,7 +300,9 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) default: break; } - return QObject::eventFilter(object, event); + return false; } FRAMELESSHELPER_END_NAMESPACE + +#endif // !native_impl diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index 8f805855..663b6e29 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -26,6 +26,8 @@ #ifdef Q_OS_WINDOWS +#if FRAMELESSHELPER_CONFIG(native_impl) + #include "framelessmanager.h" #include "framelessmanager_p.h" #include "framelessconfig_p.h" @@ -60,7 +62,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -static constexpr const auto kMessageTag = WPARAM(2546789017); +static constexpr const auto kMessageTag = WPARAM(0x97CCEA99); FRAMELESSHELPER_STRING_CONSTANT(MonitorFromWindow) FRAMELESSHELPER_STRING_CONSTANT(GetMonitorInfoW) @@ -100,9 +102,8 @@ enum class WindowPart : quint8 TitleBar }; -struct FramelessWin32HelperData +struct FramelessDataWin : public FramelessData { - SystemParameters params = {}; // Store the last hit test result, it's helpful to handle WM_MOUSEMOVE and WM_NCMOUSELEAVE. WindowPart lastHitTestResult = WindowPart::Outside; // True if we blocked a WM_MOUSELEAVE when mouse moves on chrome button, false when a @@ -112,36 +113,39 @@ struct FramelessWin32HelperData #if (QT_VERSION < QT_VERSION_CHECK(6, 5, 1)) QRect restoreGeometry = {}; #endif // (QT_VERSION < QT_VERSION_CHECK(6, 5, 1)) -}; -struct FramelessWin32HelperInternal -{ - std::unique_ptr nativeEventFilter = nullptr; - QHash data = {}; + FramelessDataWin(); + ~FramelessDataWin() override; }; +using FramelessDataWinPtr = std::shared_ptr; -Q_GLOBAL_STATIC(FramelessWin32HelperInternal, g_framelessWin32HelperData) - -[[nodiscard]] extern bool operator==(const POINT &lhs, const POINT &rhs) noexcept; -[[nodiscard]] extern bool operator!=(const POINT &lhs, const POINT &rhs) noexcept; - -[[nodiscard]] extern bool operator==(const SIZE &lhs, const SIZE &rhs) noexcept; -[[nodiscard]] extern bool operator!=(const SIZE &lhs, const SIZE &rhs) noexcept; - -[[nodiscard]] extern bool operator==(const RECT &lhs, const RECT &rhs) noexcept; -[[nodiscard]] extern bool operator!=(const RECT &lhs, const RECT &rhs) noexcept; +FramelessDataWin::FramelessDataWin() = default; -[[nodiscard]] extern QPoint point2qpoint(const POINT &point); -[[nodiscard]] extern POINT qpoint2point(const QPoint &point); +FramelessDataWin::~FramelessDataWin() = default; -[[nodiscard]] extern QSize size2qsize(const SIZE &size); -[[nodiscard]] extern SIZE qsize2size(const QSize &size); +[[nodiscard]] FramelessDataPtr FramelessData::create() +{ + return std::make_shared(); +} -[[nodiscard]] extern QRect rect2qrect(const RECT &rect); -[[nodiscard]] extern RECT qrect2rect(const QRect &qrect); +[[nodiscard]] static inline FramelessDataWinPtr tryGetData(const QObject *window) +{ + Q_ASSERT(window); + if (!window) { + return nullptr; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data) { + return nullptr; + } + return std::dynamic_pointer_cast(data); +} -[[nodiscard]] extern QString hwnd2str(const WId windowId); -[[nodiscard]] extern QString hwnd2str(const HWND hwnd); +struct FramelessHelperWinInternal +{ + std::unique_ptr eventFilter = nullptr; +}; +Q_GLOBAL_STATIC(FramelessHelperWinInternal, g_internalData) [[nodiscard]] extern std::optional getMonitorForWindow(const HWND hwnd); @@ -212,49 +216,48 @@ FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {} FramelessHelperWin::~FramelessHelperWin() = default; -void FramelessHelperWin::addWindow(FramelessParamsConst params) +void FramelessHelperWin::addWindow(const QObject *window) { - Q_ASSERT(params); - if (!params) { + Q_ASSERT(window); + if (!window) { return; } - const WId windowId = params->getWindowId(); - const auto it = g_framelessWin32HelperData()->data.constFind(windowId); - if (it != g_framelessWin32HelperData()->data.constEnd()) { + const FramelessDataWinPtr data = tryGetData(window); + if (!data || data->frameless || !data->callbacks) { return; } - FramelessWin32HelperData data = {}; - data.params = *params; - data.dpi = {Utils::getWindowDpi(windowId, true), Utils::getWindowDpi(windowId, false)}; - g_framelessWin32HelperData()->data.insert(windowId, data); - if (!g_framelessWin32HelperData()->nativeEventFilter) { - g_framelessWin32HelperData()->nativeEventFilter = std::make_unique(); - qApp->installNativeEventFilter(g_framelessWin32HelperData()->nativeEventFilter.get()); + QWindow *qWindow = data->callbacks->getWindowHandle(); + Q_ASSERT(qWindow); + if (!qWindow) { + return; } - DEBUG.noquote() << "The DPI of window" << hwnd2str(windowId) << "is" << data.dpi; - const QWindow *window = params->getWindowHandle(); + data->frameless = true; + data->dpi = Dpi{ Utils::getWindowDpi(data->windowId, true), Utils::getWindowDpi(data->windowId, false) }; + DEBUG.noquote() << "The DPI of window" << hwnd2str(data->windowId) << "is" << data->dpi; // Remove the bad window styles added by Qt (it's not that "bad" though). - std::ignore = Utils::maybeFixupQtInternals(windowId); + std::ignore = Utils::maybeFixupQtInternals(data->windowId); #if 0 - params->setWindowFlags(params->getWindowFlags() | Qt::FramelessWindowHint); + data->callbacks->setWindowFlags(data->callbacks->getWindowFlags() | Qt::FramelessWindowHint); #else // Qt maintains a frame margin internally, we need to update it accordingly // otherwise we'll get lots of warning messages when we change the window // geometry, it will also affect the final window geometry because QPA will // always take it into account when setting window size and position. - std::ignore = Utils::updateInternalWindowFrameMargins(const_cast(window), true); + std::ignore = Utils::updateInternalWindowFrameMargins(qWindow, true); #endif // Tell DWM our preferred frame margin. - std::ignore = Utils::updateWindowFrameMargins(windowId, false); + std::ignore = Utils::updateWindowFrameMargins(data->windowId, false); // Tell DWM we don't use the window icon/caption/sysmenu, don't draw them. - std::ignore = Utils::hideOriginalTitleBarElements(windowId); + std::ignore = Utils::hideOriginalTitleBarElements(data->windowId); // Without this hack, the child windows can't get DPI change messages from // Windows, which means only the top level windows can be scaled to the correct // size, we of course don't want such thing from happening. - std::ignore = Utils::fixupChildWindowsDpiMessage(windowId); + std::ignore = Utils::fixupChildWindowsDpiMessage(data->windowId); #if 0 // Conflicts with our blur mode setting. - if (Utils::isWindowAccelerated(window) && Utils::isWindowTransparent(window)) { - std::ignore = Utils::updateFramebufferTransparency(windowId); + // If we are using 3D APIs (D3D, Vulkan, OpenGL, etc) to draw the window content, + // we need to setup the DWM rendering policy as well. + if (Utils::isWindowAccelerated(qWindow) && Utils::isWindowTransparent(qWindow)) { + std::ignore = Utils::updateFramebufferTransparency(data->windowId); } #endif if (WindowsVersionHelper::isWin10RS1OrGreater()) { @@ -262,42 +265,33 @@ void FramelessHelperWin::addWindow(FramelessParamsConst params) FramelessHelperEnableThemeAware(); if (WindowsVersionHelper::isWin10RS5OrGreater()) { const bool dark = (FramelessManager::instance()->systemTheme() == SystemTheme::Dark); - const auto isWidget = [params]() -> bool { - const QObject *widget = params->getWidgetHandle(); + const auto isWidget = [&data]() -> bool { + const QObject *widget = data->callbacks->getWidgetHandle(); return (widget && widget->isWidgetType()); }(); if (!isWidget) { // Tell UXTheme we may need dark theme controls. // Causes some QtWidgets paint incorrectly, so only apply to Qt Quick applications. - std::ignore = Utils::updateGlobalWin32ControlsTheme(windowId, dark); + std::ignore = Utils::updateGlobalWin32ControlsTheme(data->windowId, dark); } - std::ignore = Utils::refreshWin32ThemeResources(windowId, dark); + std::ignore = Utils::refreshWin32ThemeResources(data->windowId, dark); if (WindowsVersionHelper::isWin11OrGreater()) { + // DWM provides official API to adjust the window corner style, but only since Windows 11. if (FramelessConfig::instance()->isSet(Option::WindowUseSquareCorners)) { - std::ignore = Utils::setCornerStyleForWindow(windowId, WindowCornerStyle::Square); + std::ignore = Utils::setCornerStyleForWindow(data->windowId, WindowCornerStyle::Square); } } } } + if (!g_internalData()->eventFilter) { + g_internalData()->eventFilter = std::make_unique(); + qApp->installNativeEventFilter(g_internalData()->eventFilter.get()); + } } -void FramelessHelperWin::removeWindow(const WId windowId) +void FramelessHelperWin::removeWindow(const QObject *window) { - Q_ASSERT(windowId); - if (!windowId) { - return; - } - const auto it = g_framelessWin32HelperData()->data.constFind(windowId); - if (it == g_framelessWin32HelperData()->data.constEnd()) { - return; - } - g_framelessWin32HelperData()->data.erase(it); - if (g_framelessWin32HelperData()->data.isEmpty()) { - if (g_framelessWin32HelperData()->nativeEventFilter) { - qApp->removeNativeEventFilter(g_framelessWin32HelperData()->nativeEventFilter.get()); - g_framelessWin32HelperData()->nativeEventFilter.reset(); - } - } + Q_UNUSED(window); } bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) @@ -319,15 +313,10 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // Anyway, we should skip the entire processing in this case. return false; } - const auto windowId = reinterpret_cast(hWnd); - // Let's be extra safe. - if (!Utils::isValidWindow(windowId, false, true)) { - return false; - } - const UINT uMsg = msg->message; + const UINT uMsg = msg->message; // We should skip these messages otherwise we will get crashes. - // WM_QUIT won't be posted to the WindowProc function. + // NOTE: WM_QUIT won't be posted to the WindowProc function. switch (uMsg) { case WM_CLOSE: case WM_DESTROY: @@ -340,19 +329,30 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me break; } - const auto it = g_framelessWin32HelperData()->data.find(windowId); - if (it == g_framelessWin32HelperData()->data.end()) { + const auto windowId = reinterpret_cast(hWnd); + // Let's be extra safe. + if (!Utils::isValidWindow(windowId, false, true)) { + return false; + } + + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + if (!window) { + return false; + } + const FramelessDataWinPtr data = tryGetData(window); + if (!data || !data->frameless || !data->callbacks) { return false; } - const FramelessWin32HelperData &data = it.value(); - FramelessWin32HelperData &muData = it.value(); - const QWindow *window = data.params.getWindowHandle(); + + QWindow *qWindow = data->callbacks->getWindowHandle(); + const bool frameBorderVisible = Utils::isWindowFrameBorderVisible(); + const WPARAM wParam = msg->wParam; const LPARAM lParam = msg->lParam; #if (QT_VERSION < QT_VERSION_CHECK(6, 5, 1)) - const auto updateRestoreGeometry = [windowId, &data, &muData](const bool ignoreWindowState) -> void { + const auto updateRestoreGeometry = [windowId, &data](const bool ignoreWindowState) -> void { if (!ignoreWindowState && !Utils::isWindowNoState(windowId)) { return; } @@ -361,10 +361,10 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me WARNING << "The calculated restore geometry is invalid."; return; } - if (Utils::isValidGeometry(data.restoreGeometry) && (data.restoreGeometry == rect)) { + if (Utils::isValidGeometry(data->restoreGeometry) && (data->restoreGeometry == rect)) { return; } - muData.restoreGeometry = rect; + data->restoreGeometry = rect; }; #endif // (QT_VERSION < QT_VERSION_CHECK(6, 5, 1)) @@ -372,6 +372,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me const int myMsg = overrideMessage.value_or(uMsg); const auto wparam = [myMsg, wParam]() -> WPARAM { if (myMsg == WM_NCMOUSELEAVE) { + // wParam is always ignored in mouse leave messages, but here we + // give them a special tag to be able to distinguish which messages + // are sent by ourselves. return kMessageTag; } const quint64 keyState = Utils::getKeyState(); @@ -383,6 +386,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me }(); const auto lparam = [myMsg, lParam, hWnd]() -> LPARAM { if (myMsg == WM_NCMOUSELEAVE) { + // lParam is always ignored in mouse leave messages. return 0; } const auto screenPos = POINT{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; @@ -439,7 +443,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me case WM_NCXBUTTONDBLCLK: SEND_MESSAGE(hWnd, WM_XBUTTONDBLCLK, wparam, lparam); break; -#if 0 +#if 0 // ### TODO: How to handle touch events? case WM_NCPOINTERUPDATE: case WM_NCPOINTERDOWN: case WM_NCPOINTERUP: @@ -465,28 +469,28 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // the reason above, and these superfluous mouse leave events cause Qt to think the // mouse has left the control, and thus we actually lost the hover state. // So we filter out these superfluous mouse leave events here to avoid this issue. - const QPoint qtScenePos = Utils::fromNativeLocalPosition(window, QPoint{ msg->pt.x, msg->pt.y }); + const QPoint qtScenePos = Utils::fromNativeLocalPosition(qWindow, QPoint{ msg->pt.x, msg->pt.y }); SystemButtonType dummy = SystemButtonType::Unknown; - if (data.params.isInsideSystemButtons(qtScenePos, &dummy)) { - muData.mouseLeaveBlocked = true; + if (data->callbacks->isInsideSystemButtons(qtScenePos, &dummy)) { + data->mouseLeaveBlocked = true; *result = FALSE; return true; } } - muData.mouseLeaveBlocked = false; + data->mouseLeaveBlocked = false; } switch (uMsg) { #if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0)) // Qt has done this for us since 5.9.0 - case WM_NCCREATE: { + case WM_NCCREATE: // Enable automatic DPI scaling for the non-client area of the window, // such as the caption bar, the scrollbars, and the menu bar. We need // to do this explicitly and manually here (only inside WM_NCCREATE). // If we are using the PMv2 DPI awareness mode, the non-client area // of the window will be scaled by the OS automatically, so there will // be no need to do this in that case. - Utils::enableNonClientAreaDpiScalingForWindow(windowId); - } break; + std::ignore = Utils::enableNonClientAreaDpiScalingForWindow(windowId); + break; #endif case WM_NCCALCSIZE: { // Windows是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容) @@ -811,8 +815,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // color, our homemade top border can almost have exactly the same // appearance with the system's one. - const auto hitTestRecorder = qScopeGuard([&muData, &result](){ - muData.lastHitTestResult = getHittedWindowPart(*result); + const auto hitTestRecorder = qScopeGuard([&data, &result](){ + data->lastHitTestResult = getHittedWindowPart(*result); }); const auto nativeGlobalPos = POINT{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; @@ -830,9 +834,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me const auto clientWidth = RECT_WIDTH(clientRect); const auto clientHeight = RECT_HEIGHT(clientRect); - const QPoint qtScenePos = Utils::fromNativeLocalPosition(window, QPoint(nativeLocalPos.x, nativeLocalPos.y)); + const QPoint qtScenePos = Utils::fromNativeLocalPosition(qWindow, QPoint(nativeLocalPos.x, nativeLocalPos.y)); SystemButtonType sysButtonType = SystemButtonType::Unknown; - if (data.params.isInsideSystemButtons(qtScenePos, &sysButtonType)) { + if (data->callbacks->isInsideSystemButtons(qtScenePos, &sysButtonType)) { // Even if the mouse is inside the chrome button area now, we should still allow the user // to be able to resize the window with the top or right window border, this is also the // normal behavior of a native Win32 window. @@ -881,10 +885,10 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me const bool full = Utils::isFullScreen(windowId); const int frameSizeY = Utils::getResizeBorderThickness(windowId, false, true); const bool isTop = (nativeLocalPos.y < frameSizeY); - const bool isTitleBar = data.params.isInsideTitleBarDraggableArea(qtScenePos); - const bool isFixedSize = data.params.isWindowFixedSize(); - const bool dontOverrideCursor = data.params.getProperty(kDontOverrideCursorVar, false).toBool(); - const bool dontToggleMaximize = data.params.getProperty(kDontToggleMaximizeVar, false).toBool(); + const bool isTitleBar = data->callbacks->isInsideTitleBarDraggableArea(qtScenePos); + const bool isFixedSize = data->callbacks->isWindowFixedSize(); + const bool dontOverrideCursor = data->callbacks->getProperty(kDontOverrideCursorVar, false).toBool(); + const bool dontToggleMaximize = data->callbacks->getProperty(kDontToggleMaximizeVar, false).toBool(); if (dontToggleMaximize) { static bool once = false; @@ -995,8 +999,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me return true; } case WM_MOUSEMOVE: - if ((data.lastHitTestResult != WindowPart::ChromeButton) && data.mouseLeaveBlocked) { - muData.mouseLeaveBlocked = false; + if ((data->lastHitTestResult != WindowPart::ChromeButton) && data->mouseLeaveBlocked) { + data->mouseLeaveBlocked = false; std::ignore = requestForMouseLeaveMessage(hWnd, false); } break; @@ -1013,17 +1017,17 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me case WM_NCXBUTTONDOWN: case WM_NCXBUTTONUP: case WM_NCXBUTTONDBLCLK: -#if 0 +#if 0 // ### TODO: How to handle touch events? case WM_NCPOINTERUPDATE: case WM_NCPOINTERDOWN: case WM_NCPOINTERUP: #endif case WM_NCMOUSEHOVER: { - const WindowPart currentWindowPart = data.lastHitTestResult; + const WindowPart currentWindowPart = data->lastHitTestResult; if (uMsg == WM_NCMOUSEMOVE) { if (currentWindowPart != WindowPart::ChromeButton) { - std::ignore = data.params.resetQtGrabbedControl(); - if (muData.mouseLeaveBlocked) { + std::ignore = data->callbacks->resetQtGrabbedControl(); + if (data->mouseLeaveBlocked) { emulateClientAreaMessage(WM_NCMOUSELEAVE); } } @@ -1034,32 +1038,38 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // If the mouse is entering the client area, there must be a WM_NCHITTEST setting // it to `Client` before the WM_NCMOUSELEAVE comes; // If the mouse is leaving the window, current window part remains as `Outside`. - muData.lastHitTestResult = WindowPart::Outside; + data->lastHitTestResult = WindowPart::Outside; } if (currentWindowPart == WindowPart::ChromeButton) { emulateClientAreaMessage(); if (uMsg == WM_NCMOUSEMOVE) { + // ### FIXME FIXME FIXME + // ### FIXME: Calling DefWindowProc() here is really dangerous, investigate how to avoid doing this. + // ### FIXME FIXME FIXME *result = ::DefWindowProcW(hWnd, WM_NCMOUSEMOVE, wParam, lParam); } else { + // According to MSDN, we should return non-zero for X button messages to indicate + // we have handled these messages (due to historical reasons), for all other messages + // we should return zero instead. *result = (((uMsg >= WM_NCXBUTTONDOWN) && (uMsg <= WM_NCXBUTTONDBLCLK)) ? TRUE : FALSE); } return true; } } break; case WM_NCMOUSELEAVE: { - const WindowPart currentWindowPart = data.lastHitTestResult; + const WindowPart currentWindowPart = data->lastHitTestResult; if (currentWindowPart == WindowPart::ChromeButton) { // If we press on the chrome button and move mouse, Windows will take the pressing area // as HTCLIENT which maybe because of our former retransmission of WM_NCLBUTTONDOWN, as // a result, a WM_NCMOUSELEAVE will come immediately and a lot of WM_MOUSEMOVE will come // if we move the mouse, we should track the mouse in advance. - if (muData.mouseLeaveBlocked) { - muData.mouseLeaveBlocked = false; + if (data->mouseLeaveBlocked) { + data->mouseLeaveBlocked = false; std::ignore = requestForMouseLeaveMessage(hWnd, false); } } else { - if (data.mouseLeaveBlocked) { + if (data->mouseLeaveBlocked) { // The mouse is moving from the chrome button to other non-client area, we should // emulate a WM_MOUSELEAVE message to reset the button state. emulateClientAreaMessage(WM_NCMOUSELEAVE); @@ -1071,7 +1081,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // the mouse leaves window from client area and enters window from non-client area, // but it has no bad effect. - std::ignore = data.params.resetQtGrabbedControl(); + std::ignore = data->callbacks->resetQtGrabbedControl(); } } } break; @@ -1085,9 +1095,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // of the application a lot. const auto windowPos = reinterpret_cast(lParam); const QRect suggestedFrameGeometry{ windowPos->x, windowPos->y, windowPos->cx, windowPos->cy }; - const QMargins frameMargins = (Utils::getWindowSystemFrameMargins(windowId) + Utils::getWindowCustomFrameMargins(window)); + const QMargins frameMargins = (Utils::getWindowSystemFrameMargins(windowId) + Utils::getWindowCustomFrameMargins(qWindow)); const QRect suggestedGeometry = (suggestedFrameGeometry - frameMargins); - if (Utils::toNativePixels(window, window->size()) != suggestedGeometry.size()) { + if (Utils::toNativePixels(qWindow, qWindow->size()) != suggestedGeometry.size()) { windowPos->flags |= SWP_NOCOPYBITS; } } break; @@ -1106,7 +1116,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } const auto newDpi = UINT(wParam); const QSize oldSize = {RECT_WIDTH(clientRect), RECT_HEIGHT(clientRect)}; - const QSize newSize = Utils::rescaleSize(oldSize, data.dpi.x, newDpi); + const QSize newSize = Utils::rescaleSize(oldSize, data->dpi.x, newDpi); const auto suggestedSize = reinterpret_cast(lParam); suggestedSize->cx = newSize.width(); suggestedSize->cy = newSize.height(); @@ -1127,7 +1137,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } #endif // (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2)) case WM_DPICHANGED: { - const Dpi oldDpi = data.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."; @@ -1135,14 +1145,14 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } DEBUG.noquote() << "New DPI for window" << hwnd2str(hWnd) << "is" << newDpi << "(was" << oldDpi << ")."; - muData.dpi = newDpi; + data->dpi = newDpi; #if (QT_VERSION < QT_VERSION_CHECK(6, 5, 1)) - if (Utils::isValidGeometry(data.restoreGeometry)) { + if (Utils::isValidGeometry(data->restoreGeometry)) { // Update the window size only. The position should not be changed. - muData.restoreGeometry.setSize(Utils::rescaleSize(data.restoreGeometry.size(), oldDpi.x, newDpi.x)); + data->restoreGeometry.setSize(Utils::rescaleSize(data->restoreGeometry.size(), oldDpi.x, newDpi.x)); } #endif // (QT_VERSION < QT_VERSION_CHECK(6, 5, 1)) - data.params.forceChildrenRepaint(500); + data->callbacks->forceChildrenRepaint(500); } break; case WM_DWMCOMPOSITIONCHANGED: // Re-apply the custom window frame if recovered from the basic theme. @@ -1157,7 +1167,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me if (wParam != SIZE_MAXIMIZED) { break; } - if (!Utils::isValidGeometry(data.restoreGeometry)) { + if (!Utils::isValidGeometry(data->restoreGeometry)) { updateRestoreGeometry(true); break; } @@ -1169,11 +1179,11 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me break; } // The restore geometry is correct, no need to bother. - if (rect2qrect(wp.rcNormalPosition) == data.restoreGeometry) { + if (rect2qrect(wp.rcNormalPosition) == data->restoreGeometry) { break; } // OK, the restore geometry is wrong, let's correct it then :) - wp.rcNormalPosition = qrect2rect(data.restoreGeometry); + wp.rcNormalPosition = qrect2rect(data->restoreGeometry); if (::SetWindowPlacement(hWnd, &wp) == FALSE) { WARNING << Utils::getSystemErrorMessage(kSetWindowPlacement); } @@ -1271,7 +1281,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me #if 0 // Conflicts with our blur mode setting. if ((uMsg == WM_DWMCOMPOSITIONCHANGED) || (uMsg == WM_DWMCOLORIZATIONCOLORCHANGED)) { - if (Utils::isWindowAccelerated(window) && Utils::isWindowTransparent(window)) { + if (Utils::isWindowAccelerated(qWindow) && Utils::isWindowTransparent(qWindow)) { std::ignore = Utils::updateFramebufferTransparency(windowId); } } @@ -1288,7 +1298,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me if (WindowsVersionHelper::isWin10RS5OrGreater()) { const bool dark = (FramelessManager::instance()->systemTheme() == SystemTheme::Dark); const auto isWidget = [&data]() -> bool { - const auto widget = data.params.getWidgetHandle(); + const auto widget = data->callbacks->getWidgetHandle(); return (widget && widget->isWidgetType()); }(); if (!isWidget) { @@ -1319,4 +1329,6 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me FRAMELESSHELPER_END_NAMESPACE +#endif // native_impl + #endif // Q_OS_WINDOWS diff --git a/src/core/framelesshelpercore_global.cpp b/src/core/framelesshelpercore_global.cpp index 5aa52c25..7b50ba56 100644 --- a/src/core/framelesshelpercore_global.cpp +++ b/src/core/framelesshelpercore_global.cpp @@ -114,6 +114,23 @@ using namespace Global; static_assert(std::size(WindowsVersions) == (static_cast(WindowsVersion::Latest) + 1)); #endif +FramelessCallbacks::FramelessCallbacks() = default; + +FramelessCallbacks::~FramelessCallbacks() = default; + +FramelessCallbacksPtr FramelessCallbacks::create() +{ + return std::make_shared(); +} + +FramelessExtraData::FramelessExtraData() = default; + +FramelessExtraData::~FramelessExtraData() = default; + +FramelessData::FramelessData() = default; + +FramelessData::~FramelessData() = default; + void FramelessHelperCoreInitialize() { static bool inited = false; diff --git a/src/core/framelessmanager.cpp b/src/core/framelessmanager.cpp index 4dedaf61..4c33132d 100644 --- a/src/core/framelessmanager.cpp +++ b/src/core/framelessmanager.cpp @@ -24,12 +24,20 @@ #include "framelessmanager.h" #include "framelessmanager_p.h" -#include "framelesshelper_qt.h" -#include "framelessconfig_p.h" #include "framelesshelpercore_global_p.h" +#if FRAMELESSHELPER_CONFIG(native_impl) +# ifdef Q_OS_WINDOWS +# include "framelesshelper_win.h" +# elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) +# elif defined(Q_OS_MACOS) +# else +# endif +#else +# include "framelesshelper_qt.h" +#endif +#include "framelessconfig_p.h" #include "utils.h" #ifdef Q_OS_WINDOWS -# include "framelesshelper_win.h" # include "winverhelper_p.h" #endif #include @@ -37,6 +45,7 @@ #include #include #include +#include #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) # include # include @@ -59,11 +68,25 @@ FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -using FramelessManagerData = QList; +static constexpr const int kEventDelayInterval = 1000; + +struct InternalData +{ + FramelessDataHash dataMap = {}; + QHash windowMap = {}; -Q_GLOBAL_STATIC(FramelessManagerData, g_framelessManagerData) + InternalData(); + ~InternalData(); -static constexpr const int kEventDelayInterval = 1000; +private: + FRAMELESSHELPER_CLASS(InternalData) +}; + +InternalData::InternalData() = default; + +InternalData::~InternalData() = default; + +Q_GLOBAL_STATIC(InternalData, g_internalData) #if FRAMELESSHELPER_CONFIG(bundle_resource) [[nodiscard]] static inline QString iconFontFamilyName() @@ -83,16 +106,60 @@ static constexpr const int kEventDelayInterval = 1000; } #endif -[[nodiscard]] static inline bool usePureQtImplementation() +class InternalEventFilter : public QObject { - static const auto result = []() -> bool { -#ifdef Q_OS_WINDOWS - return FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation); -#else - return true; -#endif - }(); - return result; + Q_OBJECT + FRAMELESSHELPER_QT_CLASS(InternalEventFilter) + +public: + explicit InternalEventFilter(const QObject *window, QObject *parent = nullptr); + ~InternalEventFilter() override; + +protected: + Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; + +private: + const QObject *m_window = nullptr; +}; + +InternalEventFilter::InternalEventFilter(const QObject *window, QObject *parent) : QObject(parent), m_window(window) +{ + Q_ASSERT(m_window); + Q_ASSERT(m_window->isWidgetType() || m_window->isWindowType()); +} + +InternalEventFilter::~InternalEventFilter() = default; + +bool InternalEventFilter::eventFilter(QObject *object, QEvent *event) +{ + Q_ASSERT(object); + Q_ASSERT(event); + Q_ASSERT(m_window); + if (!object || !event || !m_window || (object != m_window)) { + return false; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(m_window); + if (!data || !data->frameless || !data->callbacks) { + return false; + } + switch (event->type()) { + case QEvent::WinIdChange: { + const WId windowId = data->callbacks->getWindowId(); + Q_ASSERT(windowId); + if (windowId) { + FramelessManagerPrivate::updateWindowId(m_window, windowId); + } + } break; + case QEvent::Close: { + const auto ce = static_cast(event); + if (ce->isAccepted()) { + std::ignore = FramelessManager::instance()->removeWindow(m_window); + } + } break; + default: + break; + } + return false; } FramelessManagerPrivate::FramelessManagerPrivate(FramelessManager *q) : QObject(q) @@ -133,7 +200,7 @@ void FramelessManagerPrivate::initializeIconFont() return; } inited = true; - framelesshelpercore_initResource(); + FramelessHelperCoreInitResource(); // We always register this font because it's our only fallback. const int id = QFontDatabase::addApplicationFont(FRAMELESSHELPER_STRING_LITERAL(":/org.wangwenx190.FramelessHelper/resources/fonts/iconfont.ttf")); if (id < 0) { @@ -229,6 +296,80 @@ void FramelessManagerPrivate::doNotifyWallpaperHasChangedOrNot() } } +FramelessDataPtr FramelessManagerPrivate::getData(const QObject *window) +{ + Q_ASSERT(window); + Q_ASSERT(window->isWidgetType() || window->isWindowType()); + if (!window || !(window->isWidgetType() || window->isWindowType())) { + return nullptr; + } + return g_internalData()->dataMap.value(const_cast(window)); +} + +FramelessDataPtr FramelessManagerPrivate::createData(const QObject *window, const WId windowId) +{ + Q_ASSERT(window); + Q_ASSERT(window->isWidgetType() || window->isWindowType()); + Q_ASSERT(windowId); + if (!window || !(window->isWidgetType() || window->isWindowType()) || !windowId) { + return nullptr; + } + const auto win = const_cast(window); + auto it = g_internalData()->dataMap.find(win); + if (it == g_internalData()->dataMap.end()) { + FramelessDataPtr data = FramelessData::create(); + data->window = win; + data->windowId = windowId; + it = g_internalData()->dataMap.insert(win, data); + g_internalData()->windowMap.insert(windowId, win); + } + return it.value(); +} + +WId FramelessManagerPrivate::getWindowId(const QObject *window) +{ + Q_ASSERT(window); + Q_ASSERT(window->isWidgetType() || window->isWindowType()); + if (!window || !(window->isWidgetType() || window->isWindowType())) { + return 0; + } + if (const FramelessDataPtr data = getData(window)) { + return data->windowId; + } + return 0; +} + +QObject *FramelessManagerPrivate::getWindow(const WId windowId) +{ + Q_ASSERT(windowId); + if (!windowId) { + return nullptr; + } + return g_internalData()->windowMap.value(windowId); +} + +void FramelessManagerPrivate::updateWindowId(const QObject *window, const WId newWindowId) +{ + Q_ASSERT(window); + Q_ASSERT(window->isWidgetType() || window->isWindowType()); + Q_ASSERT(newWindowId); + if (!window || !(window->isWidgetType() || window->isWindowType()) || !newWindowId) { + return; + } + const auto win = const_cast(window); + const FramelessDataPtr data = g_internalData()->dataMap.value(win); + Q_ASSERT(data); + if (!data) { + return; + } + const WId oldWindowId = data->windowId; + data->windowId = newWindowId; + g_internalData()->windowMap.remove(oldWindowId); + g_internalData()->windowMap.insert(newWindowId, win); + data->frameless = false; + std::ignore = FramelessManager::instance()->addWindow(window, newWindowId); +} + bool FramelessManagerPrivate::isThemeOverrided() const { return (overrideTheme.value_or(SystemTheme::Unknown) != SystemTheme::Unknown); @@ -264,8 +405,8 @@ void FramelessManagerPrivate::initialize() // We are doing some tricks in our Windows message handling code, so // we don't use Qt's theme notifier on Windows. But for other platforms // we want to use as many Qt functionalities as possible. -#if ((QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) && !defined(Q_OS_WINDOWS)) - QStyleHints * const styleHints = QGuiApplication::styleHints(); +#if ((QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) && !FRAMELESSHELPER_CONFIG(native_impl)) + QStyleHints *styleHints = QGuiApplication::styleHints(); Q_ASSERT(styleHints); if (styleHints) { connect(styleHints, &QStyleHints::colorSchemeChanged, this, [this](const Qt::ColorScheme colorScheme){ @@ -342,51 +483,81 @@ void FramelessManager::setOverrideTheme(const SystemTheme theme) Q_EMIT systemThemeChanged(); } -void FramelessManager::addWindow(FramelessParamsConst params) +bool FramelessManager::addWindow(const QObject *window, const WId windowId) { - Q_ASSERT(params); - if (!params) { - return; - } - const WId windowId = params->getWindowId(); - if (g_framelessManagerData()->contains(windowId)) { - return; + Q_ASSERT(window); + Q_ASSERT(window->isWidgetType() || window->isWindowType()); + Q_ASSERT(windowId); + if (!window || !(window->isWidgetType() || window->isWindowType()) || !windowId) { + return false; } - g_framelessManagerData()->append(windowId); - static const bool pureQt = usePureQtImplementation(); - if (pureQt) { - FramelessHelperQt::addWindow(params); + FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (data && data->frameless) { + return false; } -#ifdef Q_OS_WINDOWS - if (!pureQt) { - FramelessHelperWin::addWindow(params); + if (!data) { + data = FramelessData::create(); + data->window = const_cast(window); + data->windowId = windowId; + g_internalData()->dataMap.insert(data->window, data); + g_internalData()->windowMap.insert(windowId, data->window); } - std::ignore = Utils::installWindowProcHook(windowId, params); +#if FRAMELESSHELPER_CONFIG(native_impl) +# ifdef Q_OS_WINDOWS + std::ignore = Utils::installWindowProcHook(windowId); + FramelessHelperWin::addWindow(window); +# elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) +# elif defined(Q_OS_MACOS) +# else +# endif +#else + FramelessHelperQt::addWindow(window); #endif - connect(params->getWindowHandle(), &QWindow::destroyed, FramelessManager::instance(), [this, windowId](){ removeWindow(windowId); }); + if (!data->internalEventHandler) { + data->internalEventHandler = new InternalEventFilter(data->window, data->window); + data->window->installEventFilter(data->internalEventHandler); + } + return true; } -void FramelessManager::removeWindow(const WId windowId) +bool FramelessManager::removeWindow(const QObject *window) { - Q_ASSERT(windowId); - if (!windowId) { - return; + Q_ASSERT(window); + if (!window) { + return false; } - if (!g_framelessManagerData()->contains(windowId)) { - return; + const auto it = g_internalData()->dataMap.constFind(const_cast(window)); + if (it == g_internalData()->dataMap.constEnd()) { + return false; } - g_framelessManagerData()->removeAll(windowId); - static const bool pureQt = usePureQtImplementation(); - if (pureQt) { - FramelessHelperQt::removeWindow(windowId); + const FramelessDataPtr data = it.value(); + Q_ASSERT(data); + Q_ASSERT(data->window); + Q_ASSERT(data->windowId); + if (!data || !data->window || !data->windowId) { + return false; } -#ifdef Q_OS_WINDOWS - if (!pureQt) { - FramelessHelperWin::removeWindow(windowId); + if (data->internalEventHandler) { + data->window->removeEventFilter(data->internalEventHandler); + delete data->internalEventHandler; + data->internalEventHandler = nullptr; } - std::ignore = Utils::uninstallWindowProcHook(windowId); - std::ignore = Utils::removeMicaWindow(windowId); +#if FRAMELESSHELPER_CONFIG(native_impl) +# ifdef Q_OS_WINDOWS + FramelessHelperWin::removeWindow(window); + std::ignore = Utils::uninstallWindowProcHook(data->windowId); +# elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) +# elif defined(Q_OS_MACOS) +# else +# endif +#else + FramelessHelperQt::removeWindow(window); #endif + g_internalData()->dataMap.erase(it); + g_internalData()->windowMap.remove(data->windowId); + return true; } FRAMELESSHELPER_END_NAMESPACE + +#include "framelessmanager.moc" diff --git a/src/core/micamaterial.cpp b/src/core/micamaterial.cpp index ad9c53c5..22bcf63d 100644 --- a/src/core/micamaterial.cpp +++ b/src/core/micamaterial.cpp @@ -62,11 +62,6 @@ FRAMELESSHELPER_BEGIN_NAMESPACE # define CRITICAL QT_NO_QDEBUG_MACRO() #endif -DECLARE_SIZE_COMPARE_OPERATORS(QSize, QSize) -DECLARE_SIZE_COMPARE_OPERATORS(QSizeF, QSizeF) -DECLARE_SIZE_COMPARE_OPERATORS(QSize, QSizeF) -DECLARE_SIZE_COMPARE_OPERATORS(QSizeF, QSize) - using namespace Global; [[maybe_unused]] static constexpr const QSize kMaximumPictureSize = { 1920, 1080 }; @@ -487,8 +482,7 @@ static inline void expblur(QImage &img, qreal radius, const bool improvedQuality class WallpaperThread : public QThread { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(WallpaperThread) + FRAMELESSHELPER_QT_CLASS(WallpaperThread) public: explicit WallpaperThread(QObject *parent = nullptr) : QThread(parent) {} @@ -657,7 +651,7 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force) void MicaMaterialPrivate::updateMaterialBrush() { #if FRAMELESSHELPER_CONFIG(bundle_resource) - framelesshelpercore_initResource(); + FramelessHelperCoreInitResource(); static const QImage noiseTexture = QImage(FRAMELESSHELPER_STRING_LITERAL(":/org.wangwenx190.FramelessHelper/resources/images/noise.png")); #endif // FRAMELESSHELPER_CORE_NO_BUNDLE_RESOURCE QImage micaTexture = QImage(QSize(64, 64), kDefaultImageFormat); diff --git a/src/core/platformsupport_win.cpp b/src/core/platformsupport_win.cpp index 479f8225..a710dd1c 100644 --- a/src/core/platformsupport_win.cpp +++ b/src/core/platformsupport_win.cpp @@ -50,11 +50,11 @@ _GetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvD Q_ASSERT(hWnd); Q_ASSERT(pvData); if (!hWnd || !pvData) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (!API_USER_AVAILABLE(GetWindowCompositionAttribute)) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return API_CALL_FUNCTION4(user32, GetWindowCompositionAttribute, hWnd, pvData); @@ -66,11 +66,11 @@ _SetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvD Q_ASSERT(hWnd); Q_ASSERT(pvData); if (!hWnd || !pvData) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (!API_USER_AVAILABLE(SetWindowCompositionAttribute)) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return API_CALL_FUNCTION4(user32, SetWindowCompositionAttribute, hWnd, pvData); @@ -111,14 +111,14 @@ _ShouldAppsUseDarkMode(VOID) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } static const auto pShouldAppsUseDarkMode = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(132))); if (!pShouldAppsUseDarkMode) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pShouldAppsUseDarkMode(); @@ -129,19 +129,19 @@ _AllowDarkModeForWindow(const HWND hWnd, const BOOL bAllow) { Q_ASSERT(hWnd); if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } static const auto pAllowDarkModeForWindow = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(133))); if (!pAllowDarkModeForWindow) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pAllowDarkModeForWindow(hWnd, bAllow); @@ -152,14 +152,14 @@ _AllowDarkModeForApp(const BOOL bAllow) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } static const auto pAllowDarkModeForApp = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135))); if (!pAllowDarkModeForApp) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pAllowDarkModeForApp(bAllow); @@ -170,14 +170,14 @@ _FlushMenuThemes(VOID) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return; } static const auto pFlushMenuThemes = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(136))); if (!pFlushMenuThemes) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return; } pFlushMenuThemes(); @@ -188,14 +188,14 @@ _RefreshImmersiveColorPolicyState(VOID) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return; } static const auto pRefreshImmersiveColorPolicyState = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(104))); if (!pRefreshImmersiveColorPolicyState) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return; } pRefreshImmersiveColorPolicyState(); @@ -206,19 +206,19 @@ _IsDarkModeAllowedForWindow(const HWND hWnd) { Q_ASSERT(hWnd); if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } static const auto pIsDarkModeAllowedForWindow = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(137))); if (!pIsDarkModeAllowedForWindow) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pIsDarkModeAllowedForWindow(hWnd); @@ -229,14 +229,14 @@ _GetIsImmersiveColorUsingHighContrast(const IMMERSIVE_HC_CACHE_MODE mode) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } static const auto pGetIsImmersiveColorUsingHighContrast = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(106))); if (!pGetIsImmersiveColorUsingHighContrast) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pGetIsImmersiveColorUsingHighContrast(mode); @@ -248,19 +248,19 @@ _OpenNcThemeData(const HWND hWnd, LPCWSTR pszClassList) Q_ASSERT(hWnd); Q_ASSERT(pszClassList); if (!hWnd || !pszClassList) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return nullptr; } FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return nullptr; } static const auto pOpenNcThemeData = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(49))); if (!pOpenNcThemeData) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return nullptr; } return pOpenNcThemeData(hWnd, pszClassList); @@ -271,14 +271,14 @@ _ShouldSystemUseDarkMode(VOID) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } static const auto pShouldSystemUseDarkMode = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(138))); if (!pShouldSystemUseDarkMode) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pShouldSystemUseDarkMode(); @@ -289,14 +289,14 @@ _SetPreferredAppMode(const PREFERRED_APP_MODE mode) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return PAM_MAX; } static const auto pSetPreferredAppMode = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135))); if (!pSetPreferredAppMode) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return PAM_MAX; } return pSetPreferredAppMode(mode); @@ -307,14 +307,14 @@ _IsDarkModeAllowedForApp(VOID) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } static const auto pIsDarkModeAllowedForApp = reinterpret_cast( SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(139))); if (!pIsDarkModeAllowedForApp) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pIsDarkModeAllowedForApp(); @@ -325,12 +325,12 @@ _EnableChildWindowDpiMessage2(const HWND hWnd, const BOOL fEnable) { Q_ASSERT(hWnd); if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } using EnableChildWindowDpiMessagePtr = decltype(&::_EnableChildWindowDpiMessage); @@ -355,7 +355,7 @@ _EnableChildWindowDpiMessage2(const HWND hWnd, const BOOL fEnable) return nullptr; }(); if (!pEnableChildWindowDpiMessage) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pEnableChildWindowDpiMessage(hWnd, fEnable); @@ -366,7 +366,7 @@ _EnablePerMonitorDialogScaling2(VOID) { FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } using EnablePerMonitorDialogScalingPtr = decltype(&::_EnablePerMonitorDialogScaling); @@ -385,7 +385,7 @@ _EnablePerMonitorDialogScaling2(VOID) return nullptr; }(); if (!pEnablePerMonitorDialogScaling) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pEnablePerMonitorDialogScaling(); @@ -396,12 +396,12 @@ _GetDpiForWindow2(const HWND hWnd) { Q_ASSERT(hWnd); if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return 0; } FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } using GetDpiForWindowPtr = decltype(&::_GetDpiForWindow); @@ -424,7 +424,7 @@ _GetDpiForWindow2(const HWND hWnd) return nullptr; }(); if (!pGetDpiForWindow) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } return pGetDpiForWindow(hWnd); @@ -436,12 +436,12 @@ _GetSystemMetricsForDpi2(const int nIndex, const UINT dpi) Q_ASSERT(nIndex >= 0); Q_ASSERT(dpi != 0); if ((nIndex < 0) || (dpi == 0)) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return 0; } FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } using GetSystemMetricsForDpiPtr = decltype(&::_GetSystemMetricsForDpi); @@ -460,7 +460,7 @@ _GetSystemMetricsForDpi2(const int nIndex, const UINT dpi) return nullptr; }(); if (!pGetSystemMetricsForDpi) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } return pGetSystemMetricsForDpi(nIndex, dpi); @@ -473,12 +473,12 @@ _AdjustWindowRectExForDpi2(LPRECT lpRect, const DWORD dwStyle, Q_ASSERT(lpRect); Q_ASSERT(dpi != 0); if (!lpRect || (dpi == 0)) { - SetLastError(ERROR_INVALID_PARAMETER); + ::SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } FRAMELESSHELPER_USE_NAMESPACE if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } using AdjustWindowRectExForDpiPtr = decltype(&::_AdjustWindowRectExForDpi); @@ -496,7 +496,7 @@ _AdjustWindowRectExForDpi2(LPRECT lpRect, const DWORD dwStyle, return nullptr; }(); if (!pAdjustWindowRectExForDpi) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } return pAdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); diff --git a/src/core/utils.cpp b/src/core/utils.cpp index e3f4d085..3cf8500a 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -24,6 +24,7 @@ #include "utils.h" #include "framelesshelpercore_global_p.h" +#include "framelessmanager_p.h" #ifdef Q_OS_WINDOWS # include "winverhelper_p.h" #endif // Q_OS_WINDOWS @@ -210,29 +211,38 @@ QWindow *Utils::findWindow(const WId windowId) return nullptr; } -void Utils::moveWindowToDesktopCenter(FramelessParamsConst params, const bool considerTaskBar) +bool Utils::moveWindowToDesktopCenter(const WId windowId, const bool considerTaskBar) { - Q_ASSERT(params); - if (!params) { - return; + Q_ASSERT(windowId); + if (!windowId) { + return false; } - const QSize windowSize = params->getWindowSize(); - if (windowSize.isEmpty() || (windowSize == kDefaultWindowSize)) { - return; + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + if (!window) { + return false; } - const QScreen *screen = params->getWindowScreen(); + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data || !data->callbacks) { + return false; + } + const QSize windowSize = data->callbacks->getWindowSize(); + if (windowSize.isEmpty() || (windowSize <= kDefaultWindowSize)) { + return false; + } + const QScreen *screen = data->callbacks->getWindowScreen(); if (!screen) { screen = QGuiApplication::primaryScreen(); } Q_ASSERT(screen); if (!screen) { - return; + return false; } const QSize screenSize = (considerTaskBar ? screen->availableSize() : screen->size()); const QPoint offset = (considerTaskBar ? screen->availableGeometry().topLeft() : QPoint(0, 0)); const int newX = std::round(qreal(screenSize.width() - windowSize.width()) / qreal(2)); const int newY = std::round(qreal(screenSize.height() - windowSize.height()) / qreal(2)); - params->setWindowPosition(QPoint(newX + offset.x(), newY + offset.y())); + data->callbacks->setWindowPosition(QPoint(newX + offset.x(), newY + offset.y())); + return true; } Qt::WindowState Utils::windowStatesToWindowState(const Qt::WindowStates states) @@ -314,9 +324,9 @@ bool Utils::shouldAppsUseDarkMode() qreal Utils::roundScaleFactor(const qreal factor) { // Qt can't handle scale factors less than 1.0 (according to the comments in qhighdpiscaling.cpp). - Q_ASSERT((factor > 1) || qFuzzyCompare(factor, qreal(1))); - if (factor < 1) { - return 1; + Q_ASSERT((factor > qreal(1)) || qFuzzyCompare(factor, qreal(1))); + if (factor < qreal(1)) { + return qreal(1); } #if (!FRAMELESSHELPER_CONFIG(private_qt) || (QT_VERSION < QT_VERSION_CHECK(6, 2, 1))) # if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) diff --git a/src/core/utils_linux.cpp b/src/core/utils_linux.cpp index 7d0ee692..a3ec94a1 100644 --- a/src/core/utils_linux.cpp +++ b/src/core/utils_linux.cpp @@ -132,7 +132,7 @@ extern QString gtkSettings(const gchar *); // https://bugreports.qt.io/browse/QTBUG-102488 const QPoint localPos = window->mapFromGlobal(globalPos); const QPoint scenePos = localPos; // windowPos in Qt5. - const auto event = std::make_unique( + const auto event = new QMouseEvent( QEvent::MouseButtonRelease, localPos, scenePos, @@ -140,7 +140,7 @@ extern QString gtkSettings(const gchar *); Qt::LeftButton, QGuiApplication::mouseButtons() ^ Qt::LeftButton, QGuiApplication::keyboardModifiers()); - QGuiApplication::sendEvent(window, event.get()); + QGuiApplication::postEvent(window, event); } QScreen *Utils::x11_findScreenForVirtualDesktop(const int virtualDesktopNumber) diff --git a/src/core/utils_mac.mm b/src/core/utils_mac.mm index 085c0512..7093254f 100644 --- a/src/core/utils_mac.mm +++ b/src/core/utils_mac.mm @@ -87,7 +87,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object class MacOSNotificationObserver { - Q_DISABLE_COPY_MOVE(MacOSNotificationObserver) + FRAMELESSHELPER_CLASS(MacOSNotificationObserver) public: explicit MacOSNotificationObserver(NSObject *object, NSNotificationName name, const Callback &callback) { @@ -125,7 +125,7 @@ void remove() class MacOSKeyValueObserver { - Q_DISABLE_COPY_MOVE(MacOSKeyValueObserver) + FRAMELESSHELPER_CLASS(MacOSKeyValueObserver) public: // Note: MacOSKeyValueObserver must not outlive the object observed! @@ -176,7 +176,7 @@ void addObserver(const NSKeyValueObservingOptions options) class MacOSThemeObserver { - Q_DISABLE_COPY_MOVE(MacOSThemeObserver) + FRAMELESSHELPER_CLASS(MacOSThemeObserver) public: explicit MacOSThemeObserver() @@ -223,8 +223,7 @@ static void notifySystemThemeChange() class NSWindowProxy : public QObject { Q_OBJECT - FRAMELESSHELPER_CLASS_INFO - Q_DISABLE_COPY_MOVE(NSWindowProxy) + FRAMELESSHELPER_QT_CLASS(NSWindowProxy) public: explicit NSWindowProxy(QWindow *qtWindow, NSWindow *macWindow, QObject *parent = nil) : QObject(parent) diff --git a/src/core/utils_win.cpp b/src/core/utils_win.cpp index 85d9ddcb..c65bc1ca 100644 --- a/src/core/utils_win.cpp +++ b/src/core/utils_win.cpp @@ -28,6 +28,7 @@ #include "framelesshelper_windows.h" #include "framelessmanager.h" +#include "framelessmanager_p.h" #include "framelessconfig_p.h" #include "sysapiloader_p.h" #include "registrykey_p.h" @@ -193,19 +194,44 @@ FRAMELESSHELPER_STRING_CONSTANT(ScreenToClient) FRAMELESSHELPER_STRING_CONSTANT(DwmFlush) FRAMELESSHELPER_STRING_CONSTANT(GetCursorPos) -struct Win32UtilsData +struct UtilsWinExtraData : public FramelessExtraData { - SystemParameters params = {}; + WNDPROC qtWindowProc = nullptr; + bool windowProcHooked = false; + bool mica = false; + + UtilsWinExtraData(); + ~UtilsWinExtraData() override; + + [[nodiscard]] static FramelessExtraDataPtr create(); }; +using UtilsWinExtraDataPtr = std::shared_ptr; + +UtilsWinExtraData::UtilsWinExtraData() = default; + +UtilsWinExtraData::~UtilsWinExtraData() = default; -struct Win32UtilsInternal +FramelessExtraDataPtr UtilsWinExtraData::create() { - QHash data = {}; - WNDPROC qtWindowProc = nullptr; - QList micaWindowIds = {}; -}; + return std::make_shared(); +} -Q_GLOBAL_STATIC(Win32UtilsInternal, g_win32UtilsData) +[[nodiscard]] static inline UtilsWinExtraDataPtr tryGetExtraData(const FramelessDataPtr &data, const bool create) +{ + Q_ASSERT(data); + if (!data) { + return nullptr; + } + auto it = data->extraData.find(ExtraDataType::WindowsUtilities); + if (it == data->extraData.end()) { + if (create) { + it = data->extraData.insert(ExtraDataType::WindowsUtilities, UtilsWinExtraData::create()); + } else { + return nullptr; + } + } + return std::dynamic_pointer_cast(it.value()); +} struct Win32Message { @@ -583,99 +609,6 @@ static constexpr const std::array g_win32MessageMap = }; #undef DEFINE_WIN32_MESSAGE -[[nodiscard]] bool operator==(const POINT &lhs, const POINT &rhs) noexcept -{ - return ((lhs.x == rhs.x) && (lhs.y == rhs.y)); -} - -[[nodiscard]] bool operator!=(const POINT &lhs, const POINT &rhs) noexcept -{ - return !operator==(lhs, rhs); -} - -[[nodiscard]] bool operator==(const SIZE &lhs, const SIZE &rhs) noexcept -{ - return ((lhs.cx == rhs.cx) && (lhs.cy == rhs.cy)); -} - -[[nodiscard]] bool operator!=(const SIZE &lhs, const SIZE &rhs) noexcept -{ - return !operator==(lhs, rhs); -} - -[[nodiscard]] bool operator>(const SIZE &lhs, const SIZE &rhs) noexcept -{ - return ((lhs.cx * lhs.cy) > (rhs.cx * rhs.cy)); -} - -[[nodiscard]] bool operator>=(const SIZE &lhs, const SIZE &rhs) noexcept -{ - return (operator>(lhs, rhs) || operator==(lhs, rhs)); -} - -[[nodiscard]] bool operator<(const SIZE &lhs, const SIZE &rhs) noexcept -{ - return (operator!=(lhs, rhs) && !operator>(lhs, rhs)); -} - -[[nodiscard]] bool operator<=(const SIZE &lhs, const SIZE &rhs) noexcept -{ - return (operator<(lhs, rhs) || operator==(lhs, rhs)); -} - -[[nodiscard]] bool operator==(const RECT &lhs, const RECT &rhs) noexcept -{ - return ((lhs.left == rhs.left) && (lhs.top == rhs.top) - && (lhs.right == rhs.right) && (lhs.bottom == rhs.bottom)); -} - -[[nodiscard]] bool operator!=(const RECT &lhs, const RECT &rhs) noexcept -{ - return !operator==(lhs, rhs); -} - -[[nodiscard]] QPoint point2qpoint(const POINT &point) -{ - return QPoint{ int(point.x), int(point.y) }; -} - -[[nodiscard]] POINT qpoint2point(const QPoint &point) -{ - return POINT{ LONG(point.x()), LONG(point.y()) }; -} - -[[nodiscard]] QSize size2qsize(const SIZE &size) -{ - return QSize{ int(size.cx), int(size.cy) }; -} - -[[nodiscard]] SIZE qsize2size(const QSize &size) -{ - return SIZE{ LONG(size.width()), LONG(size.height()) }; -} - -[[nodiscard]] QRect rect2qrect(const RECT &rect) -{ - return QRect{ QPoint{ int(rect.left), int(rect.top) }, QSize{ int(RECT_WIDTH(rect)), int(RECT_HEIGHT(rect)) } }; -} - -[[nodiscard]] RECT qrect2rect(const QRect &qrect) -{ - return RECT{ LONG(qrect.left()), LONG(qrect.top()), LONG(qrect.right()), LONG(qrect.bottom()) }; -} - -[[nodiscard]] QString hwnd2str(const WId windowId) -{ - // NULL handle is allowed here. - return FRAMELESSHELPER_STRING_LITERAL("0x") + QString::number(windowId, 16).toUpper().rightJustified(8, u'0'); -} - -[[nodiscard]] QString hwnd2str(const HWND hwnd) -{ - // NULL handle is allowed here. - return hwnd2str(reinterpret_cast(hwnd)); -} - [[nodiscard]] std::optional getMonitorForWindow(const HWND hwnd) { Q_ASSERT(hwnd); @@ -734,8 +667,7 @@ static constexpr const std::array g_win32MessageMap = static const auto currentOsVer = []() -> std::optional { if (API_NT_AVAILABLE(RtlGetVersion)) { using RtlGetVersionPtr = _NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW); - const auto pRtlGetVersion = - reinterpret_cast(SysApiLoader::instance()->get(kntdll, kRtlGetVersion)); + const auto pRtlGetVersion = reinterpret_cast(SysApiLoader::instance()->get(kntdll, kRtlGetVersion)); RTL_OSVERSIONINFOEXW osvi; SecureZeroMemory(&osvi, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(osvi); @@ -785,8 +717,7 @@ static constexpr const std::array g_win32MessageMap = return kErrorMessageTemplate.arg(function, QString::number(code), errorText); #else // !FRAMELESSHELPER_CONFIG(private_qt) LPWSTR buf = nullptr; - if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&buf), 0, nullptr) == 0) { + if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&buf), 0, nullptr) == 0) { return FRAMELESSHELPER_STRING_LITERAL("FormatMessageW() returned empty string."); } const QString errorText = QString::fromWCharArray(buf).trimmed(); @@ -839,16 +770,14 @@ static constexpr const std::array g_win32MessageMap = const int newWindowY = (activeMonitorRect.top + currentWindowOffsetY); static constexpr const UINT flags = (SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER); - if (::SetWindowPos(hwnd, nullptr, newWindowX, newWindowY, - currentWindowWidth, currentWindowHeight, flags) == FALSE) { + if (::SetWindowPos(hwnd, nullptr, newWindowX, newWindowY, currentWindowWidth, currentWindowHeight, flags) == FALSE) { WARNING << Utils::getSystemErrorMessage(kSetWindowPos); return false; } return true; } -[[nodiscard]] static inline int getSystemMetrics2(const int index, const bool horizontal, - const quint32 dpi) +[[nodiscard]] static inline int getSystemMetrics2(const int index, const bool horizontal, const quint32 dpi) { Q_ASSERT(dpi != 0); if (dpi == 0) { @@ -863,8 +792,7 @@ static constexpr const std::array g_win32MessageMap = return std::round(qreal(::GetSystemMetrics(index)) / currentDpr * requestedDpr); } -[[nodiscard]] static inline int getSystemMetrics2(const WId windowId, const int index, - const bool horizontal, const bool scaled) +[[nodiscard]] static inline int getSystemMetrics2(const WId windowId, const int index, const bool horizontal, const bool scaled) { Q_ASSERT(windowId); if (!windowId) { @@ -883,29 +811,29 @@ static constexpr const std::array g_win32MessageMap = return std::round(qreal(::GetSystemMetrics(index)) / dpr); } -[[maybe_unused]] [[nodiscard]] static inline +[[maybe_unused]] [[nodiscard]] static inline constexpr DWORD qtEdgesToWin32Orientation(const Qt::Edges edges) { if (edges == Qt::Edges{}) { return 0; } else if (edges == (Qt::LeftEdge)) { - return 0xF001; // SC_SIZELEFT + return SC_SIZELEFT; } else if (edges == (Qt::RightEdge)) { - return 0xF002; // SC_SIZERIGHT + return SC_SIZERIGHT; } else if (edges == (Qt::TopEdge)) { - return 0xF003; // SC_SIZETOP + return SC_SIZETOP; } else if (edges == (Qt::TopEdge | Qt::LeftEdge)) { - return 0xF004; // SC_SIZETOPLEFT + return SC_SIZETOPLEFT; } else if (edges == (Qt::TopEdge | Qt::RightEdge)) { - return 0xF005; // SC_SIZETOPRIGHT + return SC_SIZETOPRIGHT; } else if (edges == (Qt::BottomEdge)) { - return 0xF006; // SC_SIZEBOTTOM + return SC_SIZEBOTTOM; } else if (edges == (Qt::BottomEdge | Qt::LeftEdge)) { - return 0xF007; // SC_SIZEBOTTOMLEFT + return SC_SIZEBOTTOMLEFT; } else if (edges == (Qt::BottomEdge | Qt::RightEdge)) { - return 0xF008; // SC_SIZEBOTTOMRIGHT + return SC_SIZEBOTTOMRIGHT; } else { - return 0xF000; // SC_SIZE + return SC_SIZE; } } @@ -923,7 +851,7 @@ static constexpr const std::array g_win32MessageMap = return result; } -[[nodiscard]] static inline bool isNonClientMessage(const UINT message) +[[nodiscard]] static inline constexpr bool isNonClientMessage(const UINT message) { if (((message >= WM_NCCREATE) && (message <= WM_NCACTIVATE)) || ((message >= WM_NCMOUSEMOVE) && (message <= WM_NCMBUTTONDBLCLK)) @@ -936,7 +864,7 @@ static constexpr const std::array g_win32MessageMap = } } -[[nodiscard]] static inline bool isMouseMessage(const UINT message, bool *isNonClient = nullptr) +[[nodiscard]] static inline constexpr bool isMouseMessage(const UINT message, bool *isNonClient = nullptr) { if (((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST)) || ((message == WM_MOUSEHOVER) || (message == WM_MOUSELEAVE))) { @@ -956,18 +884,12 @@ static constexpr const std::array g_win32MessageMap = } } -[[nodiscard]] static inline bool usePureQtImplementation() -{ - static const bool result = FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation); - return result; -} - [[nodiscard]] static inline LRESULT CALLBACK FramelessHelperHookWindowProc (const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam) { Q_ASSERT(hWnd); if (!hWnd) { - return 0; + return FALSE; } #if FRAMELESSHELPER_CONFIG(debug_output) if (isWin32MessageDebuggingEnabled()) { @@ -981,11 +903,27 @@ static constexpr const std::array g_win32MessageMap = Utils::printWin32Message(&message); } #endif + const auto defaultWindowProcessing = [hWnd, uMsg, wParam, lParam]() -> LRESULT { return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); }; const auto windowId = reinterpret_cast(hWnd); - const auto it = g_win32UtilsData()->data.constFind(windowId); - if (it == g_win32UtilsData()->data.constEnd()) { - return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + if (!window) { + return defaultWindowProcessing(); + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data || !data->frameless || !data->callbacks) { + return defaultWindowProcessing(); } + const UtilsWinExtraDataPtr extraData = tryGetExtraData(data, false); + Q_ASSERT(extraData); + if (!extraData) { + return defaultWindowProcessing(); + } + const QWindow *qWindow = data->callbacks->getWindowHandle(); + Q_ASSERT(qWindow); + if (!qWindow) { + return defaultWindowProcessing(); + } +#if FRAMELESSHELPER_CONFIG(native_impl) // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/plugins/platforms/windows/qwindowscontext.cpp#L1025 // We can see from the source code that Qt will filter out some messages first and then send the unfiltered // messages to the event dispatcher. To activate the Snap Layout feature on Windows 11, we must process @@ -1004,7 +942,7 @@ static constexpr const std::array g_win32MessageMap = // (and correct client area size, especially when the window is maximized/fullscreen). So we still go through // the normal code path of the original qWindowsWndProc() function, but only for this specific message. It should // be OK because Qt won't prevent us from handling WM_NCCALCSIZE. - if (!usePureQtImplementation() && (uMsg != WM_NCCALCSIZE)) { + if (uMsg != WM_NCCALCSIZE) { MSG message; SecureZeroMemory(&message, sizeof(message)); message.hwnd = hWnd; @@ -1034,7 +972,7 @@ static constexpr const std::array g_win32MessageMap = return LRESULT(filterResult); } } - const Win32UtilsData &data = it.value(); +#endif // native_impl const auto getNativePosFromMouse = [lParam]() -> QPoint { return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; }; @@ -1073,8 +1011,8 @@ static constexpr const std::array g_win32MessageMap = switch (uMsg) { case WM_RBUTTONUP: { const QPoint nativeLocalPos = getNativePosFromMouse(); - const QPoint qtScenePos = Utils::fromNativeLocalPosition(data.params.getWindowHandle(), nativeLocalPos); - if (data.params.isInsideTitleBarDraggableArea(qtScenePos)) { + const QPoint qtScenePos = Utils::fromNativeLocalPosition(qWindow, nativeLocalPos); + if (data->callbacks->isInsideTitleBarDraggableArea(qtScenePos)) { POINT pos = {nativeLocalPos.x(), nativeLocalPos.y()}; if (::ClientToScreen(hWnd, &pos) == FALSE) { WARNING << Utils::getSystemErrorMessage(kClientToScreen); @@ -1084,12 +1022,12 @@ static constexpr const std::array g_win32MessageMap = nativeGlobalPos = {pos.x, pos.y}; } } break; - case WM_NCRBUTTONUP: { + case WM_NCRBUTTONUP: if (wParam == HTCAPTION) { shouldShowSystemMenu = true; nativeGlobalPos = getNativePosFromMouse(); } - } break; + break; case WM_SYSCOMMAND: { const WPARAM filteredWParam = (wParam & 0xFFF0); if ((filteredWParam == SC_KEYMENU) && (lParam == VK_SPACE)) { @@ -1112,20 +1050,20 @@ static constexpr const std::array g_win32MessageMap = break; } if (shouldShowSystemMenu) { - std::ignore = Utils::showSystemMenu(windowId, nativeGlobalPos, broughtByKeyboard, &data.params); + std::ignore = Utils::showSystemMenu(windowId, nativeGlobalPos, broughtByKeyboard); // QPA's internal code will handle system menu events separately, and its // behavior is not what we would want to see because it doesn't know our // window doesn't have any window frame now, so return early here to avoid // entering Qt's own handling logic. - return 0; // Return 0 means we have handled this event. + return FALSE; // Return 0 means we have handled this event. } - Q_ASSERT(g_win32UtilsData()->qtWindowProc); - if (g_win32UtilsData()->qtWindowProc) { + Q_ASSERT(extraData->qtWindowProc); + if (extraData->qtWindowProc) { // Hand over to Qt's original window proc function for events we are not // interested in. - return ::CallWindowProcW(g_win32UtilsData()->qtWindowProc, hWnd, uMsg, wParam, lParam); + return ::CallWindowProcW(extraData->qtWindowProc, hWnd, uMsg, wParam, lParam); } else { - return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); + return defaultWindowProcessing(); } } @@ -1167,16 +1105,12 @@ bool Utils::triggerFrameChange(const WId windowId) return false; } const auto hwnd = reinterpret_cast(windowId); - static constexpr const UINT swpFlags = - (SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE - | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); + static constexpr const UINT swpFlags = (SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); if (::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, swpFlags) == FALSE) { WARNING << getSystemErrorMessage(kSetWindowPos); return false; } - static constexpr const UINT rdwFlags = - (RDW_ERASE | RDW_FRAME | RDW_INVALIDATE - | RDW_UPDATENOW | RDW_ALLCHILDREN); + static constexpr const UINT rdwFlags = (RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); if (::RedrawWindow(hwnd, nullptr, nullptr, rdwFlags) == FALSE) { WARNING << getSystemErrorMessage(kRedrawWindow); return false; @@ -1193,19 +1127,31 @@ bool Utils::updateWindowFrameMargins(const WId windowId, const bool reset) if (!API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea)) { return false; } - // We can't extend the window frame when DWM composition is disabled. + // We can't extend the window frame when DWM composition is disabled anyway. // No need to try further in this case. if (!isDwmCompositionEnabled()) { return false; } - const bool micaEnabled = g_win32UtilsData()->micaWindowIds.contains(windowId); - const auto margins = [micaEnabled, reset]() -> MARGINS { + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + if (!window) { + return false; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data) { + return false; + } + const UtilsWinExtraDataPtr extraData = tryGetExtraData(data, false); + Q_ASSERT(extraData); + if (!extraData) { + return false; + } + const auto margins = [&extraData, reset]() -> MARGINS { // To make Mica/Mica Alt work for normal Win32 windows, we have to // let the window frame extend to the whole window (or disable the // redirection surface, but this will break GDI's rendering, so we // can't do this, unfortunately), so we can't change the window frame // margins in this case, otherwise Mica/Mica Alt will be broken. - if (micaEnabled) { + if (extraData->mica) { return {-1, -1, -1, -1}; } if (reset || isWindowFrameBorderVisible()) { @@ -1275,9 +1221,9 @@ QString Utils::getSystemErrorMessage(const QString &function) if (function.isEmpty()) { return {}; } - const DWORD code = GetLastError(); + const DWORD code = ::GetLastError(); if (code == ERROR_SUCCESS) { - return {}; + return kSuccessMessageText; } return getSystemErrorMessageImpl(function, code); } @@ -1342,12 +1288,19 @@ DwmColorizationArea Utils::getDwmColorizationArea() return DwmColorizationArea::None; } -bool Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool selectFirstEntry, - FramelessParamsConst params) +bool Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool selectFirstEntry) { Q_ASSERT(windowId); - Q_ASSERT(params); - if (!windowId || !params) { + if (!windowId) { + return false; + } + + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + if (!window) { + return false; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data || !data->frameless || !data->callbacks) { return false; } @@ -1361,11 +1314,11 @@ bool Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool sel } // Tweak the menu items according to the current window status and user settings. - const bool disableRestore = params->getProperty(kSysMenuDisableRestoreVar, false).toBool(); - const bool disableMinimize = params->getProperty(kSysMenuDisableMinimizeVar, false).toBool(); - const bool disableMaximize = params->getProperty(kSysMenuDisableMaximizeVar, false).toBool(); + const bool disableRestore = data->callbacks->getProperty(kSysMenuDisableRestoreVar, false).toBool(); + const bool disableMinimize = data->callbacks->getProperty(kSysMenuDisableMinimizeVar, false).toBool(); + const bool disableMaximize = data->callbacks->getProperty(kSysMenuDisableMaximizeVar, false).toBool(); const bool maxOrFull = (IsMaximized(hWnd) || isFullScreen(windowId)); - const bool fixedSize = params->isWindowFixedSize(); + const bool fixedSize = data->callbacks->isWindowFixedSize(); ::EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize && !disableRestore) ? MFS_ENABLED : MFS_DISABLED))); // The first menu item should be selected by default if the menu is brought // up by keyboard. I don't know how to pre-select a menu item but it seems @@ -1399,14 +1352,13 @@ bool Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool sel ::SetMenuDefaultItem(hMenu, defaultItemId, FALSE); // Popup the system menu at the required position. - const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() - ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), pos.x(), pos.y(), 0, hWnd, nullptr); + const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), pos.x(), pos.y(), 0, hWnd, nullptr); // Unhighlight the first menu item after the popup menu is closed, otherwise it will keep // highlighting until we unhighlight it manually. ::HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | MFS_UNHILITE)); - if (result == 0) { + if (result == FALSE) { // The user canceled the menu, no need to continue. return true; } @@ -1614,13 +1566,10 @@ quint32 Utils::getPrimaryScreenDpi(const bool horizontal) // Using Direct2D to get the primary monitor's DPI is only available on Windows 7 // and onwards, but it has been marked as deprecated by Microsoft. 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(kd2d1, kD2D1CreateFactory)); + using D2D1CreateFactoryPtr = HRESULT(WINAPI *)(D2D1_FACTORY_TYPE, REFIID, CONST D2D1_FACTORY_OPTIONS *, void **); + const auto pD2D1CreateFactory = reinterpret_cast(SysApiLoader::instance()->get(kd2d1, kD2D1CreateFactory)); ID2D1Factory *d2dFactory = nullptr; - HRESULT hr = pD2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), - nullptr, reinterpret_cast(&d2dFactory)); + HRESULT hr = pD2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), nullptr, reinterpret_cast(&d2dFactory)); if (SUCCEEDED(hr)) { // We want to get the newest system DPI, so refresh the system metrics // manually to ensure that. @@ -1740,11 +1689,9 @@ quint32 Utils::getResizeBorderThicknessForDpi(const bool horizontal, const quint return 0; } if (horizontal) { - return (getSystemMetrics2(SM_CXSIZEFRAME, true, dpi) - + getSystemMetrics2(SM_CXPADDEDBORDER, true, dpi)); + return (getSystemMetrics2(SM_CXSIZEFRAME, true, dpi) + getSystemMetrics2(SM_CXPADDEDBORDER, true, dpi)); } else { - return (getSystemMetrics2(SM_CYSIZEFRAME, false, dpi) - + getSystemMetrics2(SM_CYPADDEDBORDER, false, dpi)); + return (getSystemMetrics2(SM_CYSIZEFRAME, false, dpi) + getSystemMetrics2(SM_CYPADDEDBORDER, false, dpi)); } } @@ -1755,11 +1702,9 @@ quint32 Utils::getResizeBorderThickness(const WId windowId, const bool horizonta return 0; } if (horizontal) { - return (getSystemMetrics2(windowId, SM_CXSIZEFRAME, true, scaled) - + getSystemMetrics2(windowId, SM_CXPADDEDBORDER, true, scaled)); + return (getSystemMetrics2(windowId, SM_CXSIZEFRAME, true, scaled) + getSystemMetrics2(windowId, SM_CXPADDEDBORDER, true, scaled)); } else { - return (getSystemMetrics2(windowId, SM_CYSIZEFRAME, false, scaled) - + getSystemMetrics2(windowId, SM_CYPADDEDBORDER, false, scaled)); + return (getSystemMetrics2(windowId, SM_CYSIZEFRAME, false, scaled) + getSystemMetrics2(windowId, SM_CYPADDEDBORDER, false, scaled)); } } @@ -1830,13 +1775,12 @@ quint32 Utils::getFrameBorderThickness(const WId windowId, const bool scaled) const qreal scaleFactor = (qreal(dpi) / qreal(USER_DEFAULT_SCREEN_DPI)); const auto hwnd = reinterpret_cast(windowId); UINT value = 0; - const HRESULT hr = API_CALL_FUNCTION(dwmapi, DwmGetWindowAttribute, hwnd, - _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &value, sizeof(value)); + const HRESULT hr = API_CALL_FUNCTION(dwmapi, DwmGetWindowAttribute, hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &value, sizeof(value)); if (SUCCEEDED(hr)) { - const qreal dpr = (scaled ? 1.0 : scaleFactor); + const qreal dpr = (scaled ? qreal(1) : scaleFactor); return std::round(qreal(value) / dpr); } else { - const qreal dpr = (scaled ? scaleFactor : 1.0); + const qreal dpr = (scaled ? scaleFactor : qreal(1)); return std::round(qreal(kDefaultWindowFrameBorderThickness) * dpr); } } @@ -1949,7 +1893,7 @@ bool Utils::startSystemMove(QWindow *window, const QPoint &globalPos) return false; } const auto hwnd = reinterpret_cast(window->winId()); - if (::PostMessageW(hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0) == FALSE) { + if (::PostMessageW(hwnd, WM_SYSCOMMAND, SC_DRAGMOVE, 0) == FALSE) { WARNING << getSystemErrorMessage(kPostMessageW); return false; } @@ -1986,10 +1930,8 @@ bool Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoi bool Utils::isWindowFrameBorderVisible() { static const auto result = []() -> bool { +#if FRAMELESSHELPER_CONFIG(native_impl) const FramelessConfig * const config = FramelessConfig::instance(); - if (config->isSet(Option::UseCrossPlatformQtImplementation)) { - return false; - } if (config->isSet(Option::ForceShowWindowFrameBorder)) { return true; } @@ -1997,6 +1939,9 @@ bool Utils::isWindowFrameBorderVisible() return false; } return WindowsVersionHelper::isWin10OrGreater(); +#else + return false; +#endif }(); return result; } @@ -2016,15 +1961,29 @@ bool Utils::isFrameBorderColorized() return isTitleBarColorized(); } -bool Utils::installWindowProcHook(const WId windowId, FramelessParamsConst params) +bool Utils::installWindowProcHook(const WId windowId) { Q_ASSERT(windowId); - Q_ASSERT(params); - if (!windowId || !params) { + if (!windowId) { + return false; + } + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + Q_ASSERT(window); + if (!window) { + return false; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + Q_ASSERT(data); + if (!data || data->frameless) { + return false; + } + const UtilsWinExtraDataPtr extraData = tryGetExtraData(data, true); + Q_ASSERT(extraData); + if (!extraData) { return false; } const auto hwnd = reinterpret_cast(windowId); - if (!g_win32UtilsData()->qtWindowProc) { + if (!extraData->qtWindowProc) { ::SetLastError(ERROR_SUCCESS); const auto qtWindowProc = reinterpret_cast(::GetWindowLongPtrW(hwnd, GWLP_WNDPROC)); Q_ASSERT(qtWindowProc); @@ -2032,18 +1991,15 @@ bool Utils::installWindowProcHook(const WId windowId, FramelessParamsConst param WARNING << getSystemErrorMessage(kGetWindowLongPtrW); return false; } - g_win32UtilsData()->qtWindowProc = qtWindowProc; + extraData->qtWindowProc = qtWindowProc; } - const auto it = g_win32UtilsData()->data.constFind(windowId); - if (it == g_win32UtilsData()->data.constEnd()) { - Win32UtilsData data = {}; - data.params = *params; - g_win32UtilsData()->data.insert(windowId, data); + if (!extraData->windowProcHooked) { ::SetLastError(ERROR_SUCCESS); if (::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast(FramelessHelperHookWindowProc)) == 0) { WARNING << getSystemErrorMessage(kSetWindowLongPtrW); return false; } + extraData->windowProcHooked = true; } return true; } @@ -2054,19 +2010,30 @@ bool Utils::uninstallWindowProcHook(const WId windowId) if (!windowId) { return false; } - const auto it = g_win32UtilsData()->data.constFind(windowId); - if (it != g_win32UtilsData()->data.constEnd()) { - g_win32UtilsData()->data.erase(it); + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + if (!window) { + return false; } - if (g_win32UtilsData()->data.isEmpty() && g_win32UtilsData()->qtWindowProc) { - const auto hwnd = reinterpret_cast(windowId); - ::SetLastError(ERROR_SUCCESS); - if (::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast(g_win32UtilsData()->qtWindowProc)) == 0) { - WARNING << getSystemErrorMessage(kSetWindowLongPtrW); - return false; - } - g_win32UtilsData()->qtWindowProc = nullptr; + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data || !data->frameless) { + return false; } + const UtilsWinExtraDataPtr extraData = tryGetExtraData(data, false); + if (!extraData || !extraData->windowProcHooked) { + return false; + } + Q_ASSERT(extraData->qtWindowProc); + if (!extraData->qtWindowProc) { + return false; + } + const auto hwnd = reinterpret_cast(windowId); + ::SetLastError(ERROR_SUCCESS); + if (::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast(extraData->qtWindowProc)) == 0) { + WARNING << getSystemErrorMessage(kSetWindowLongPtrW); + return false; + } + extraData->qtWindowProc = nullptr; + extraData->windowProcHooked = false; return true; } @@ -2323,6 +2290,19 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, if (!windowId) { return false; } + const QObject *window = FramelessManagerPrivate::getWindow(windowId); + if (!window) { + return false; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data) { + return false; + } + const UtilsWinExtraDataPtr extraData = tryGetExtraData(data, false); + // Don't assert here, the user may be using pure Qt solution. + if (!extraData) { + return false; + } const auto hwnd = reinterpret_cast(windowId); if (WindowsVersionHelper::isWin8OrGreater()) { if (!(API_DWM_AVAILABLE(DwmSetWindowAttribute) @@ -2330,8 +2310,8 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, WARNING << "Blur behind window is not available on current platform."; return false; } - const auto restoreWindowFrameMargins = [windowId]() -> void { - g_win32UtilsData()->micaWindowIds.removeAll(windowId); + const auto restoreWindowFrameMargins = [windowId, &extraData]() -> void { + extraData->mica = false; std::ignore = updateWindowFrameMargins(windowId, false); }; static const auto userPreferredBlurMode = []() -> std::optional { @@ -2372,7 +2352,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, return mode; } if (((mode == BlurMode::Windows_Mica) || (mode == BlurMode::Windows_MicaAlt)) - && !WindowsVersionHelper::isWin11OrGreater()) { + && !WindowsVersionHelper::isWin11OrGreater()) { WARNING << "The Mica material is not supported on your system, fallback to the Acrylic blur instead..."; if (WindowsVersionHelper::isWin10OrGreater()) { return BlurMode::Windows_Acrylic; @@ -2438,7 +2418,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, return result; } else { if ((blurMode == BlurMode::Windows_Mica) || (blurMode == BlurMode::Windows_MicaAlt)) { - g_win32UtilsData()->micaWindowIds.append(windowId); + extraData->mica = true; // By giving a negative value, DWM will extend the window frame into the whole // client area. We need this step because the Mica material can only be applied // to the non-client area of a window. Without this step, you'll get a window @@ -2682,9 +2662,9 @@ bool Utils::setQtDarkModeAwareEnabled(const bool enable) // flag has no effect for pure Qt Quick applications. return {App::DarkModeWindowFrames | App::DarkModeStyle}; # else // (QT_VERSION < QT_VERSION_CHECK(6, 5, 0)) \ - // Don't try to use the broken dark theme for Qt Widgets applications. \ - // For Qt Quick applications this is also enough. There's no global dark \ - // theme for them anyway. + // Don't try to use the broken dark theme for Qt Widgets applications. \ + // For Qt Quick applications this is also enough. There's no global dark \ + // theme for them anyway. return {App::DarkModeWindowFrames}; # endif // (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) }()); @@ -3107,16 +3087,6 @@ QRect Utils::getWindowRestoreGeometry(const WId windowId) return rect2qrect(wp.rcNormalPosition).translated(getWindowPlacementOffset(windowId)); } -bool Utils::removeMicaWindow(const WId windowId) -{ - Q_ASSERT(windowId); - if (!windowId) { - return false; - } - g_win32UtilsData()->micaWindowIds.removeAll(windowId); - return true; -} - quint64 Utils::getKeyState() { quint64 result = 0; @@ -3163,7 +3133,7 @@ bool Utils::isValidWindow(const WId windowId, const bool checkVisible, const boo return false; } const LONG_PTR exStyles = ::GetWindowLongPtrW(hwnd, GWL_EXSTYLE); - if ((exStyles != 0) && (exStyles & WS_EX_TOOLWINDOW)) { + if ((exStyles == 0) || (exStyles & WS_EX_TOOLWINDOW)) { return false; } RECT rect = { 0, 0, 0, 0 }; @@ -3209,11 +3179,11 @@ bool Utils::updateFramebufferTransparency(const WId windowId) DWM_BLURBEHIND bb; SecureZeroMemory(&bb, sizeof(bb)); bb.dwFlags = (DWM_BB_ENABLE | DWM_BB_BLURREGION); - bb.hRgnBlur = CreateRectRgn(0, 0, -1, -1); + bb.hRgnBlur = ::CreateRectRgn(0, 0, -1, -1); bb.fEnable = TRUE; const HRESULT hr = API_CALL_FUNCTION(dwmapi, DwmEnableBlurBehindWindow, hwnd, &bb); if (bb.hRgnBlur) { - if (DeleteObject(bb.hRgnBlur) == FALSE) { + if (::DeleteObject(bb.hRgnBlur) == FALSE) { WARNING << getSystemErrorMessage(kDeleteObject); } } diff --git a/src/core/winverhelper.cpp b/src/core/winverhelper.cpp index 9ab7a470..dbee1ea5 100644 --- a/src/core/winverhelper.cpp +++ b/src/core/winverhelper.cpp @@ -35,7 +35,7 @@ using namespace Global; class WinVerHelper { - Q_DISABLE_COPY_MOVE(WinVerHelper) + FRAMELESSHELPER_CLASS(WinVerHelper) public: explicit WinVerHelper(); diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt index c76bea05..6b81b7ac 100644 --- a/src/quick/CMakeLists.txt +++ b/src/quick/CMakeLists.txt @@ -109,7 +109,7 @@ if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC) COPYRIGHT "MIT License" ORIGINAL_FILENAME "${SUB_MODULE_FULL_NAME}.dll" PRODUCT "${PROJECT_NAME}" - COMMENTS "Built from commit ${PROJECT_VERSION_COMMIT} on ${PROJECT_COMPILE_DATETIME} (UTC)." + COMMENTS "Who don't love Raiden Shogun ?" LIBRARY ) endif() diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index 0b937227..3fb76610 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -32,6 +32,7 @@ #endif #include #include +#include #include #include #ifdef Q_OS_WINDOWS @@ -72,10 +73,8 @@ FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -struct FramelessQuickHelperData +struct FramelessQuickHelperExtraData : public FramelessExtraData { - bool ready = false; - SystemParameters params = {}; QPointer titleBarItem = nullptr; QList> hitTestVisibleItems = {}; QPointer windowIconButton = nullptr; @@ -84,11 +83,52 @@ struct FramelessQuickHelperData QPointer maximizeButton = nullptr; QPointer closeButton = nullptr; QList hitTestVisibleRects = {}; + + FramelessQuickHelperExtraData(); + ~FramelessQuickHelperExtraData() override; + + [[nodiscard]] static FramelessExtraDataPtr create(); }; +using FramelessQuickHelperExtraDataPtr = std::shared_ptr; + +FramelessQuickHelperExtraData::FramelessQuickHelperExtraData() = default; + +FramelessQuickHelperExtraData::~FramelessQuickHelperExtraData() = default; -using FramelessQuickHelperInternal = QHash; +FramelessExtraDataPtr FramelessQuickHelperExtraData::create() +{ + return std::make_shared(); +} + +[[nodiscard]] static inline FramelessQuickHelperExtraDataPtr tryGetExtraData(const FramelessDataPtr &data, const bool create) +{ + Q_ASSERT(data); + if (!data) { + return nullptr; + } + auto it = data->extraData.find(ExtraDataType::FramelessQuickHelper); + if (it == data->extraData.end()) { + if (create) { + it = data->extraData.insert(ExtraDataType::FramelessQuickHelper, FramelessQuickHelperExtraData::create()); + } else { + return nullptr; + } + } + return std::dynamic_pointer_cast(it.value()); +} -Q_GLOBAL_STATIC(FramelessQuickHelperInternal, g_framelessQuickHelperData) +[[nodiscard]] static inline FramelessQuickHelperExtraDataPtr tryGetExtraData(const QQuickWindow *window, const bool create) +{ + Q_ASSERT(window); + if (!window) { + return nullptr; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data) { + return nullptr; + } + return tryGetExtraData(data, create); +} FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q) : QObject(q) { @@ -124,59 +164,61 @@ const FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(const Framel void FramelessQuickHelperPrivate::attach() { Q_Q(FramelessQuickHelper); - QQuickWindow * const window = q->window(); + QQuickWindow *window = q->window(); Q_ASSERT(window); if (!window) { return; } + const WId windowId = window->winId(); - FramelessQuickHelperData * const data = getWindowDataMutable(); - if (!data || data->ready) { - return; - } - - SystemParameters params = {}; - params.getWindowId = [window]() -> WId { return window->winId(); }; - params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); }; - params.setWindowFlags = [window](const Qt::WindowFlags flags) -> void { window->setFlags(flags); }; - params.getWindowSize = [window]() -> QSize { return window->size(); }; - params.setWindowSize = [window](const QSize &size) -> void { window->resize(size); }; - params.getWindowPosition = [window]() -> QPoint { return window->position(); }; - params.setWindowPosition = [window](const QPoint &pos) -> void { window->setX(pos.x()); window->setY(pos.y()); }; - params.getWindowScreen = [window]() -> QScreen * { return window->screen(); }; - params.isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); }; - params.setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); }; - params.getWindowState = [window]() -> Qt::WindowState { return window->windowState(); }; - params.setWindowState = [window](const Qt::WindowState state) -> void { window->setWindowState(state); }; - params.getWindowHandle = [window]() -> QWindow * { return window; }; - params.windowToScreen = [window](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); }; - params.screenToWindow = [window](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); }; - params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { - QuickGlobal::SystemButtonType button2 = QuickGlobal::SystemButtonType::Unknown; - const bool result = isInSystemButtons(pos, &button2); - *button = FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button2); - return result; - }; - params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); }; - params.getWindowDevicePixelRatio = [window]() -> qreal { return window->effectiveDevicePixelRatio(); }; - params.setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void { - setSystemButtonState(FRAMELESSHELPER_ENUM_CORE_TO_QUICK(SystemButtonType, button), - FRAMELESSHELPER_ENUM_CORE_TO_QUICK(ButtonState, state)); - }; - params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); }; - params.showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); }; - params.setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); }; - params.getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); }; - params.setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); }; - params.unsetCursor = [window]() -> void { window->unsetCursor(); }; - params.getWidgetHandle = []() -> QObject * { return nullptr; }; - params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); }; - params.resetQtGrabbedControl = []() -> bool { return false; }; - - FramelessManager::instance()->addWindow(¶ms); + const FramelessDataPtr data = FramelessManagerPrivate::createData(window, windowId); + Q_ASSERT(data); + if (!data || data->frameless) { + return; + } - data->params = params; - data->ready = true; + if (!data->callbacks) { + data->callbacks = FramelessCallbacks::create(); + data->callbacks->getWindowId = [window]() -> WId { return window->winId(); }; + data->callbacks->getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); }; + data->callbacks->setWindowFlags = [window](const Qt::WindowFlags flags) -> void { window->setFlags(flags); }; + data->callbacks->getWindowSize = [window]() -> QSize { return window->size(); }; + data->callbacks->setWindowSize = [window](const QSize &size) -> void { window->resize(size); }; + data->callbacks->getWindowPosition = [window]() -> QPoint { return window->position(); }; + data->callbacks->setWindowPosition = [window](const QPoint &pos) -> void { window->setX(pos.x()); window->setY(pos.y()); }; + data->callbacks->getWindowScreen = [window]() -> QScreen * { return window->screen(); }; + data->callbacks->isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); }; + data->callbacks->setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); }; + data->callbacks->getWindowState = [window]() -> Qt::WindowState { return window->windowState(); }; + data->callbacks->setWindowState = [window](const Qt::WindowState state) -> void { window->setWindowState(state); }; + data->callbacks->getWindowHandle = [q]() -> QWindow * { return q->window(); }; + data->callbacks->windowToScreen = [window](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); }; + data->callbacks->screenToWindow = [window](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); }; + data->callbacks->isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { + QuickGlobal::SystemButtonType button2 = QuickGlobal::SystemButtonType::Unknown; + const bool result = isInSystemButtons(pos, &button2); + *button = FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button2); + return result; + }; + data->callbacks->isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); }; + data->callbacks->getWindowDevicePixelRatio = [window]() -> qreal { return window->effectiveDevicePixelRatio(); }; + data->callbacks->setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void { + setSystemButtonState(FRAMELESSHELPER_ENUM_CORE_TO_QUICK(SystemButtonType, button), FRAMELESSHELPER_ENUM_CORE_TO_QUICK(ButtonState, state)); + }; + data->callbacks->shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); }; + data->callbacks->showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); }; + data->callbacks->setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); }; + data->callbacks->getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); }; + data->callbacks->setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); }; + data->callbacks->unsetCursor = [window]() -> void { window->unsetCursor(); }; + data->callbacks->getWidgetHandle = []() -> QObject * { return nullptr; }; + data->callbacks->forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); }; + data->callbacks->resetQtGrabbedControl = []() -> bool { return false; }; + } + + std::ignore = tryGetExtraData(data, true); + + std::ignore = FramelessManager::instance()->addWindow(window, windowId); // We have to wait for a little time before moving the top level window // , because the platform window may not finish initializing by the time @@ -198,17 +240,11 @@ void FramelessQuickHelperPrivate::attach() void FramelessQuickHelperPrivate::detach() { Q_Q(FramelessQuickHelper); - QQuickWindow * const w = q->window(); - if (!w) { - return; - } - const WId windowId = w->winId(); - const auto it = g_framelessQuickHelperData()->constFind(windowId); - if (it == g_framelessQuickHelperData()->constEnd()) { + const QQuickWindow *window = q->window(); + if (!window) { return; } - g_framelessQuickHelperData()->erase(it); - FramelessManager::instance()->removeWindow(windowId); + std::ignore = FramelessManager::instance()->removeWindow(window); } void FramelessQuickHelperPrivate::emitSignalForAllInstances(const char *signal) @@ -433,37 +469,43 @@ bool FramelessQuickHelperPrivate::isInSystemButtons(const QPoint &pos, QuickGlob if (!button) { return false; } - const FramelessQuickHelperData *data = getWindowData(); - if (!data) { + Q_Q(const FramelessQuickHelper); + const QQuickWindow * const window = q->window(); + if (!window) { + return false; + } + const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(window, false); + Q_ASSERT(extraData); + if (!extraData) { return false; } *button = QuickGlobal::SystemButtonType::Unknown; - if (data->windowIconButton && data->windowIconButton->isVisible() && data->windowIconButton->isEnabled()) { - if (mapItemGeometryToScene(data->windowIconButton).contains(pos)) { + if (extraData->windowIconButton && extraData->windowIconButton->isVisible() && extraData->windowIconButton->isEnabled()) { + if (mapItemGeometryToScene(extraData->windowIconButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::WindowIcon; return true; } } - if (data->contextHelpButton && data->contextHelpButton->isVisible() && data->contextHelpButton->isEnabled()) { - if (mapItemGeometryToScene(data->contextHelpButton).contains(pos)) { + if (extraData->contextHelpButton && extraData->contextHelpButton->isVisible() && extraData->contextHelpButton->isEnabled()) { + if (mapItemGeometryToScene(extraData->contextHelpButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Help; return true; } } - if (data->minimizeButton && data->minimizeButton->isVisible() && data->minimizeButton->isEnabled()) { - if (mapItemGeometryToScene(data->minimizeButton).contains(pos)) { + if (extraData->minimizeButton && extraData->minimizeButton->isVisible() && extraData->minimizeButton->isEnabled()) { + if (mapItemGeometryToScene(extraData->minimizeButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Minimize; return true; } } - if (data->maximizeButton && data->maximizeButton->isVisible() && data->maximizeButton->isEnabled()) { - if (mapItemGeometryToScene(data->maximizeButton).contains(pos)) { + if (extraData->maximizeButton && extraData->maximizeButton->isVisible() && extraData->maximizeButton->isEnabled()) { + if (mapItemGeometryToScene(extraData->maximizeButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Maximize; return true; } } - if (data->closeButton && data->closeButton->isVisible() && data->closeButton->isEnabled()) { - if (mapItemGeometryToScene(data->closeButton).contains(pos)) { + if (extraData->closeButton && extraData->closeButton->isVisible() && extraData->closeButton->isEnabled()) { + if (mapItemGeometryToScene(extraData->closeButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Close; return true; } @@ -473,27 +515,28 @@ bool FramelessQuickHelperPrivate::isInSystemButtons(const QPoint &pos, QuickGlob bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) const { - const FramelessQuickHelperData *data = getWindowData(); - if (!data) { + Q_Q(const FramelessQuickHelper); + const QQuickWindow * const window = q->window(); + if (!window) { + // The FramelessQuickHelper item has not been attached to a specific window yet, + // so we assume there's no title bar. return false; } - if (!data->titleBarItem) { - // There's no title bar at all, the mouse will always be in the client area. + const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(window, false); + Q_ASSERT(extraData); + if (!extraData) { return false; } - if (!data->titleBarItem->isVisible() || !data->titleBarItem->isEnabled()) { - // The title bar is hidden or disabled for some reason, treat it as there's no title bar. + if (!extraData->titleBarItem) { + // There's no title bar at all, the mouse will always be in the client area. return false; } - Q_Q(const FramelessQuickHelper); - const QQuickWindow * const window = q->window(); - if (!window) { - // The FramelessQuickHelper item has not been attached to a specific window yet, - // so we assume there's no title bar. + if (!extraData->titleBarItem->isVisible() || !extraData->titleBarItem->isEnabled()) { + // The title bar is hidden or disabled for some reason, treat it as there's no title bar. return false; } const QRect windowRect = {QPoint(0, 0), window->size()}; - const QRect titleBarRect = mapItemGeometryToScene(data->titleBarItem); + const QRect titleBarRect = mapItemGeometryToScene(extraData->titleBarItem); if (!titleBarRect.intersects(windowRect)) { // The title bar is totally outside of the window for some reason, // also treat it as there's no title bar. @@ -501,24 +544,24 @@ bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) c } QRegion region = titleBarRect; const auto systemButtons = { - data->windowIconButton, data->contextHelpButton, - data->minimizeButton, data->maximizeButton, - data->closeButton + extraData->windowIconButton, extraData->contextHelpButton, + extraData->minimizeButton, extraData->maximizeButton, + extraData->closeButton }; for (auto &&button : std::as_const(systemButtons)) { if (button && button->isVisible() && button->isEnabled()) { region -= mapItemGeometryToScene(button); } } - if (!data->hitTestVisibleItems.isEmpty()) { - for (auto &&item : std::as_const(data->hitTestVisibleItems)) { + if (!extraData->hitTestVisibleItems.isEmpty()) { + for (auto &&item : std::as_const(extraData->hitTestVisibleItems)) { if (item && item->isVisible() && item->isEnabled()) { region -= mapItemGeometryToScene(item); } } } - if (!data->hitTestVisibleRects.isEmpty()) { - for (auto &&rect : std::as_const(data->hitTestVisibleRects)) { + if (!extraData->hitTestVisibleRects.isEmpty()) { + for (auto &&rect : std::as_const(extraData->hitTestVisibleRects)) { if (rect.isValid()) { region -= rect; } @@ -556,38 +599,6 @@ void FramelessQuickHelperPrivate::setSystemButtonState(const QuickGlobal::System Q_UNUSED(state); } -const FramelessQuickHelperData *FramelessQuickHelperPrivate::getWindowData() const -{ - Q_Q(const FramelessQuickHelper); - const QQuickWindow * const window = q->window(); - //Q_ASSERT(window); - if (!window) { - return nullptr; - } - const WId windowId = window->winId(); - auto it = g_framelessQuickHelperData()->find(windowId); - if (it == g_framelessQuickHelperData()->end()) { - it = g_framelessQuickHelperData()->insert(windowId, {}); - } - return &it.value(); -} - -FramelessQuickHelperData *FramelessQuickHelperPrivate::getWindowDataMutable() const -{ - Q_Q(const FramelessQuickHelper); - const QQuickWindow * const window = q->window(); - //Q_ASSERT(window); - if (!window) { - return nullptr; - } - const WId windowId = window->winId(); - auto it = g_framelessQuickHelperData()->find(windowId); - if (it == g_framelessQuickHelperData()->end()) { - it = g_framelessQuickHelperData()->insert(windowId, {}); - } - return &it.value(); -} - void FramelessQuickHelperPrivate::rebindWindow() { Q_Q(FramelessQuickHelper); @@ -668,33 +679,41 @@ void FramelessQuickHelper::setHitTestVisible_item(QQuickItem *item, const bool v if (!item) { return; } - Q_D(FramelessQuickHelper); - FramelessQuickHelperData *data = d->getWindowDataMutable(); - if (!data) { + const QQuickWindow * const w = window(); + if (!w) { + return; + } + const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false); + Q_ASSERT(extraData); + if (!extraData) { return; } if (visible) { - data->hitTestVisibleItems.append(item); + extraData->hitTestVisibleItems.append(item); } else { - data->hitTestVisibleItems.removeAll(item); + extraData->hitTestVisibleItems.removeAll(item); } } void FramelessQuickHelper::setHitTestVisible_rect(const QRect &rect, const bool visible) { - Q_ASSERT(rect.isValid()); - if (!rect.isValid()) { + Q_ASSERT(Utils::isValidGeometry(rect)); + if (!Utils::isValidGeometry(rect)) { return; } - Q_D(FramelessQuickHelper); - FramelessQuickHelperData *data = d->getWindowDataMutable(); - if (!data) { + const QQuickWindow * const w = window(); + if (!w) { + return; + } + const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false); + Q_ASSERT(extraData); + if (!extraData) { return; } if (visible) { - data->hitTestVisibleRects.append(rect); + extraData->hitTestVisibleRects.append(rect); } else { - data->hitTestVisibleRects.removeAll(rect); + extraData->hitTestVisibleRects.removeAll(rect); } } @@ -714,9 +733,12 @@ void FramelessQuickHelper::setHitTestVisible_object(QObject *object, const bool bool FramelessQuickHelper::isContentExtendedIntoTitleBar() const { - Q_D(const FramelessQuickHelper); - const FramelessQuickHelperData *data = d->getWindowData(); - return (data ? data->ready : false); + const QQuickWindow * const w = window(); + if (!w) { + return false; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(w); + return (data && data->frameless); } void FramelessQuickHelper::extendsContentIntoTitleBar(const bool value) @@ -736,9 +758,16 @@ void FramelessQuickHelper::extendsContentIntoTitleBar(const bool value) QQuickItem *FramelessQuickHelper::titleBarItem() const { - Q_D(const FramelessQuickHelper); - const FramelessQuickHelperData *data = d->getWindowData(); - return (data ? data->titleBarItem : nullptr); + const QQuickWindow * const w = window(); + if (!w) { + return nullptr; + } + const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false); + Q_ASSERT(extraData); + if (!extraData) { + return nullptr; + } + return extraData->titleBarItem; } void FramelessQuickHelper::setTitleBarItem(QQuickItem *value) @@ -747,12 +776,17 @@ void FramelessQuickHelper::setTitleBarItem(QQuickItem *value) if (!value) { return; } - Q_D(FramelessQuickHelper); - FramelessQuickHelperData *data = d->getWindowDataMutable(); - if (!data || (data->titleBarItem == value)) { + const QQuickWindow * const w = window(); + if (!w) { return; } - data->titleBarItem = value; + const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false); + Q_ASSERT(extraData); + if (!extraData || (extraData->titleBarItem == value)) { + return; + } + extraData->titleBarItem = value; + Q_D(FramelessQuickHelper); d->emitSignalForAllInstances("titleBarItemChanged"); } @@ -763,27 +797,31 @@ void FramelessQuickHelper::setSystemButton(QQuickItem *item, const QuickGlobal:: if (!item || (buttonType == QuickGlobal::SystemButtonType::Unknown)) { return; } - Q_D(FramelessQuickHelper); - FramelessQuickHelperData *data = d->getWindowDataMutable(); - if (!data) { + const QQuickWindow * const w = window(); + if (!w) { + return; + } + const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false); + Q_ASSERT(extraData); + if (!extraData) { return; } switch (buttonType) { case QuickGlobal::SystemButtonType::WindowIcon: - data->windowIconButton = item; + extraData->windowIconButton = item; break; case QuickGlobal::SystemButtonType::Help: - data->contextHelpButton = item; + extraData->contextHelpButton = item; break; case QuickGlobal::SystemButtonType::Minimize: - data->minimizeButton = item; + extraData->minimizeButton = item; break; case QuickGlobal::SystemButtonType::Maximize: case QuickGlobal::SystemButtonType::Restore: - data->maximizeButton = item; + extraData->maximizeButton = item; break; case QuickGlobal::SystemButtonType::Close: - data->closeButton = item; + extraData->closeButton = item; break; case QuickGlobal::SystemButtonType::Unknown: Q_UNREACHABLE(); @@ -799,8 +837,7 @@ void FramelessQuickHelper::showSystemMenu(const QPoint &pos) const WId windowId = w->winId(); const QPoint nativePos = Utils::toNativeGlobalPosition(w, pos); #ifdef Q_OS_WINDOWS - Q_D(FramelessQuickHelper); - std::ignore = Utils::showSystemMenu(windowId, nativePos, false, &d->getWindowData()->params); + std::ignore = Utils::showSystemMenu(windowId, nativePos, false); #elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) Utils::openSystemMenu(windowId, nativePos); #else @@ -832,11 +869,11 @@ void FramelessQuickHelper::windowStartSystemResize2(const Qt::Edges edges, const void FramelessQuickHelper::moveWindowToDesktopCenter() { - if (!window()) { + const QQuickWindow * const w = window(); + if (!w) { return; } - Q_D(FramelessQuickHelper); - Utils::moveWindowToDesktopCenter(&d->getWindowData()->params, true); + std::ignore = Utils::moveWindowToDesktopCenter(w->winId(), true); } void FramelessQuickHelper::bringWindowToFront() @@ -912,6 +949,7 @@ bool FramelessQuickHelper::isBlurBehindWindowEnabled() const void FramelessQuickHelper::setBlurBehindWindowEnabled(const bool value) { +#if (!defined(Q_OS_WINDOWS) || FRAMELESSHELPER_CONFIG(native_impl)) QQuickWindow * const w = window(); if (!w) { return; @@ -948,6 +986,9 @@ void FramelessQuickHelper::setBlurBehindWindowEnabled(const bool value) #endif d->emitSignalForAllInstances("blurBehindWindowEnabledChanged"); } +#else // Windows && !native_impl + Q_UNUSED(value); +#endif } bool FramelessQuickHelper::isReady() const diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 7fa5b816..73d88cc3 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -102,7 +102,7 @@ if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC) COPYRIGHT "MIT License" ORIGINAL_FILENAME "${SUB_MODULE_FULL_NAME}.dll" PRODUCT "${PROJECT_NAME}" - COMMENTS "Built from commit ${PROJECT_VERSION_COMMIT} on ${PROJECT_COMPILE_DATETIME} (UTC)." + COMMENTS "Who don't love Raiden Shogun ?" LIBRARY ) endif() diff --git a/src/widgets/framelesswidgetshelper.cpp b/src/widgets/framelesswidgetshelper.cpp index 9208e951..ea1b950e 100644 --- a/src/widgets/framelesswidgetshelper.cpp +++ b/src/widgets/framelesswidgetshelper.cpp @@ -35,6 +35,7 @@ #include "widgetssharedhelper_p.h" #include #include +#include #include #include #include @@ -71,10 +72,8 @@ FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -struct FramelessWidgetsHelperData +struct FramelessWidgetsHelperExtraData : public FramelessExtraData { - bool ready = false; - SystemParameters params = {}; QPointer titleBarWidget = nullptr; QList> hitTestVisibleWidgets = {}; QPointer windowIconButton = nullptr; @@ -83,13 +82,54 @@ struct FramelessWidgetsHelperData QPointer maximizeButton = nullptr; QPointer closeButton = nullptr; QList hitTestVisibleRects = {}; + + FramelessWidgetsHelperExtraData(); + ~FramelessWidgetsHelperExtraData() override; + + [[nodiscard]] static FramelessExtraDataPtr create(); }; +using FramelessWidgetsHelperExtraDataPtr = std::shared_ptr; + +FramelessWidgetsHelperExtraData::FramelessWidgetsHelperExtraData() = default; -using FramelessWidgetsHelperInternal = QHash; +FramelessWidgetsHelperExtraData::~FramelessWidgetsHelperExtraData() = default; + +FramelessExtraDataPtr FramelessWidgetsHelperExtraData::create() +{ + return std::make_shared(); +} -Q_GLOBAL_STATIC(FramelessWidgetsHelperInternal, g_framelessWidgetsHelperData) +[[nodiscard]] static inline FramelessWidgetsHelperExtraDataPtr tryGetExtraData(const FramelessDataPtr &data, const bool create) +{ + Q_ASSERT(data); + if (!data) { + return nullptr; + } + auto it = data->extraData.find(ExtraDataType::FramelessWidgetsHelper); + if (it == data->extraData.end()) { + if (create) { + it = data->extraData.insert(ExtraDataType::FramelessWidgetsHelper, FramelessWidgetsHelperExtraData::create()); + } else { + return nullptr; + } + } + return std::dynamic_pointer_cast(it.value()); +} + +[[nodiscard]] static inline FramelessWidgetsHelperExtraDataPtr tryGetExtraData(const QWidget *window, const bool create) +{ + Q_ASSERT(window); + if (!window) { + return nullptr; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(window); + if (!data) { + return nullptr; + } + return tryGetExtraData(data, create); +} -[[nodiscard]] static inline bool isWidgetFixedSize(const QWidget * const widget) +[[nodiscard]] static inline bool isWidgetFixedSize(const QWidget *widget) { Q_ASSERT(widget); if (!widget) { @@ -114,7 +154,7 @@ Q_GLOBAL_STATIC(FramelessWidgetsHelperInternal, g_framelessWidgetsHelperData) return false; } -static inline void forceWidgetRepaint(QWidget * const widget) +static inline void forceWidgetRepaint(QWidget *widget) { Q_ASSERT(widget); if (!widget) { @@ -360,7 +400,7 @@ void FramelessWidgetsHelperPrivate::setReadyWaitTime(const quint32 time) void FramelessWidgetsHelperPrivate::attach() { - QWidget * const tlw = findTopLevelWindow(); + QWidget *tlw = findTopLevelWindow(); Q_ASSERT(tlw); if (!tlw) { return; @@ -377,69 +417,72 @@ void FramelessWidgetsHelperPrivate::attach() window->setAttribute(Qt::WA_NativeWindow); } - FramelessWidgetsHelperData * const data = getWindowDataMutable(); - if (!data || data->ready) { + const WId windowId = window->winId(); + const FramelessDataPtr data = FramelessManagerPrivate::createData(window, windowId); + Q_ASSERT(data); + if (!data || data->frameless) { return; } Q_Q(FramelessWidgetsHelper); - SystemParameters params = {}; - params.getWindowId = [this]() -> WId { return window->winId(); }; - params.getWindowFlags = [this]() -> Qt::WindowFlags { return window->windowFlags(); }; - params.setWindowFlags = [this](const Qt::WindowFlags flags) -> void { window->setWindowFlags(flags); }; - params.getWindowSize = [this]() -> QSize { return window->size(); }; - params.setWindowSize = [this](const QSize &size) -> void { window->resize(size); }; - params.getWindowPosition = [this]() -> QPoint { return window->pos(); }; - params.setWindowPosition = [this](const QPoint &pos) -> void { window->move(pos); }; - params.getWindowScreen = [this]() -> QScreen * { + if (!data->callbacks) { + data->callbacks = FramelessCallbacks::create(); + data->callbacks->getWindowId = [this]() -> WId { return window->winId(); }; + data->callbacks->getWindowFlags = [this]() -> Qt::WindowFlags { return window->windowFlags(); }; + data->callbacks->setWindowFlags = [this](const Qt::WindowFlags flags) -> void { window->setWindowFlags(flags); }; + data->callbacks->getWindowSize = [this]() -> QSize { return window->size(); }; + data->callbacks->setWindowSize = [this](const QSize &size) -> void { window->resize(size); }; + data->callbacks->getWindowPosition = [this]() -> QPoint { return window->pos(); }; + data->callbacks->setWindowPosition = [this](const QPoint &pos) -> void { window->move(pos); }; + data->callbacks->getWindowScreen = [this]() -> QScreen * { #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - return window->screen(); + return window->screen(); #else - return window->windowHandle()->screen(); + return window->windowHandle()->screen(); #endif - }; - params.isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); }; - params.setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); }; - params.getWindowState = [this]() -> Qt::WindowState { return Utils::windowStatesToWindowState(window->windowState()); }; - params.setWindowState = [this](const Qt::WindowState state) -> void { window->setWindowState(state); }; - params.getWindowHandle = [this]() -> QWindow * { return window->windowHandle(); }; - params.windowToScreen = [this](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); }; - params.screenToWindow = [this](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); }; - params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { return isInSystemButtons(pos, button); }; - params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); }; - params.getWindowDevicePixelRatio = [this]() -> qreal { return window->devicePixelRatioF(); }; - params.setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void { setSystemButtonState(button, state); }; - params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); }; - params.showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); }; - params.setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); }; - params.getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); }; - params.setCursor = [this](const QCursor &cursor) -> void { window->setCursor(cursor); }; - params.unsetCursor = [this]() -> void { window->unsetCursor(); }; - params.getWidgetHandle = [this]() -> QObject * { return window; }; - params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); }; - params.resetQtGrabbedControl = []() -> bool { - if (qt_button_down) { - static constexpr const auto invalidPos = QPoint{ -99999, -99999 }; - const auto event = std::make_unique( - QEvent::MouseButtonRelease, - invalidPos, - invalidPos, - invalidPos, - Qt::LeftButton, - QGuiApplication::mouseButtons() ^ Qt::LeftButton, - QGuiApplication::keyboardModifiers()); - QApplication::sendEvent(qt_button_down, event.get()); - qt_button_down = nullptr; - return true; - } - return false; - }; + }; + data->callbacks->isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); }; + data->callbacks->setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); }; + data->callbacks->getWindowState = [this]() -> Qt::WindowState { return Utils::windowStatesToWindowState(window->windowState()); }; + data->callbacks->setWindowState = [this](const Qt::WindowState state) -> void { window->setWindowState(state); }; + data->callbacks->getWindowHandle = [this]() -> QWindow * { return window->windowHandle(); }; + data->callbacks->windowToScreen = [this](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); }; + data->callbacks->screenToWindow = [this](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); }; + data->callbacks->isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { return isInSystemButtons(pos, button); }; + data->callbacks->isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); }; + data->callbacks->getWindowDevicePixelRatio = [this]() -> qreal { return window->devicePixelRatioF(); }; + data->callbacks->setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void { setSystemButtonState(button, state); }; + data->callbacks->shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); }; + data->callbacks->showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); }; + data->callbacks->setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); }; + data->callbacks->getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); }; + data->callbacks->setCursor = [this](const QCursor &cursor) -> void { window->setCursor(cursor); }; + data->callbacks->unsetCursor = [this]() -> void { window->unsetCursor(); }; + data->callbacks->getWidgetHandle = [this]() -> QObject * { return window; }; + data->callbacks->forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); }; + data->callbacks->resetQtGrabbedControl = []() -> bool { + if (qt_button_down) { + static constexpr const auto invalidPos = QPoint{ -99999, -99999 }; + const auto event = new QMouseEvent( + QEvent::MouseButtonRelease, + invalidPos, + invalidPos, + invalidPos, + Qt::LeftButton, + QGuiApplication::mouseButtons() ^ Qt::LeftButton, + QGuiApplication::keyboardModifiers()); + QApplication::postEvent(qt_button_down, event); + qt_button_down = nullptr; + return true; + } + return false; + }; + } - FramelessManager::instance()->addWindow(¶ms); + std::ignore = tryGetExtraData(data, true); - data->params = params; - data->ready = true; + std::ignore = FramelessManager::instance()->addWindow(window, windowId); // We have to wait for a little time before moving the top level window // , because the platform window may not finish initializing by the time @@ -464,13 +507,7 @@ void FramelessWidgetsHelperPrivate::detach() if (!window) { return; } - const WId windowId = window->winId(); - const auto it = g_framelessWidgetsHelperData()->constFind(windowId); - if (it == g_framelessWidgetsHelperData()->constEnd()) { - return; - } - g_framelessWidgetsHelperData()->erase(it); - FramelessManager::instance()->removeWindow(windowId); + std::ignore = FramelessManager::instance()->removeWindow(window); window = nullptr; emitSignalForAllInstances("windowChanged"); } @@ -488,34 +525,6 @@ QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const return nullptr; } -const FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowData() const -{ - //Q_ASSERT(window); - if (!window) { - return nullptr; - } - const WId windowId = window->winId(); - auto it = g_framelessWidgetsHelperData()->find(windowId); - if (it == g_framelessWidgetsHelperData()->end()) { - it = g_framelessWidgetsHelperData()->insert(windowId, {}); - } - return &it.value(); -} - -FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowDataMutable() const -{ - //Q_ASSERT(window); - if (!window) { - return nullptr; - } - const WId windowId = window->winId(); - auto it = g_framelessWidgetsHelperData()->find(windowId); - if (it == g_framelessWidgetsHelperData()->end()) { - it = g_framelessWidgetsHelperData()->insert(windowId, {}); - } - return &it.value(); -} - QRect FramelessWidgetsHelperPrivate::mapWidgetGeometryToScene(const QWidget * const widget) const { Q_ASSERT(widget); @@ -536,37 +545,41 @@ bool FramelessWidgetsHelperPrivate::isInSystemButtons(const QPoint &pos, SystemB if (!button) { return false; } - const FramelessWidgetsHelperData *data = getWindowData(); - if (!data) { + if (!window) { + return false; + } + const FramelessWidgetsHelperExtraDataPtr extraData = tryGetExtraData(window, false); + Q_ASSERT(extraData); + if (!extraData) { return false; } *button = SystemButtonType::Unknown; - if (data->windowIconButton && data->windowIconButton->isVisible() && data->windowIconButton->isEnabled()) { - if (mapWidgetGeometryToScene(data->windowIconButton).contains(pos)) { + if (extraData->windowIconButton && extraData->windowIconButton->isVisible() && extraData->windowIconButton->isEnabled()) { + if (mapWidgetGeometryToScene(extraData->windowIconButton).contains(pos)) { *button = SystemButtonType::WindowIcon; return true; } } - if (data->contextHelpButton && data->contextHelpButton->isVisible() && data->contextHelpButton->isEnabled()) { - if (mapWidgetGeometryToScene(data->contextHelpButton).contains(pos)) { + if (extraData->contextHelpButton && extraData->contextHelpButton->isVisible() && extraData->contextHelpButton->isEnabled()) { + if (mapWidgetGeometryToScene(extraData->contextHelpButton).contains(pos)) { *button = SystemButtonType::Help; return true; } } - if (data->minimizeButton && data->minimizeButton->isVisible() && data->minimizeButton->isEnabled()) { - if (mapWidgetGeometryToScene(data->minimizeButton).contains(pos)) { + if (extraData->minimizeButton && extraData->minimizeButton->isVisible() && extraData->minimizeButton->isEnabled()) { + if (mapWidgetGeometryToScene(extraData->minimizeButton).contains(pos)) { *button = SystemButtonType::Minimize; return true; } } - if (data->maximizeButton && data->maximizeButton->isVisible() && data->maximizeButton->isEnabled()) { - if (mapWidgetGeometryToScene(data->maximizeButton).contains(pos)) { + if (extraData->maximizeButton && extraData->maximizeButton->isVisible() && extraData->maximizeButton->isEnabled()) { + if (mapWidgetGeometryToScene(extraData->maximizeButton).contains(pos)) { *button = SystemButtonType::Maximize; return true; } } - if (data->closeButton && data->closeButton->isVisible() && data->closeButton->isEnabled()) { - if (mapWidgetGeometryToScene(data->closeButton).contains(pos)) { + if (extraData->closeButton && extraData->closeButton->isVisible() && extraData->closeButton->isEnabled()) { + if (mapWidgetGeometryToScene(extraData->closeButton).contains(pos)) { *button = SystemButtonType::Close; return true; } @@ -576,25 +589,26 @@ bool FramelessWidgetsHelperPrivate::isInSystemButtons(const QPoint &pos, SystemB bool FramelessWidgetsHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) const { - const FramelessWidgetsHelperData *data = getWindowData(); - if (!data) { + if (!window) { + // The FramelessWidgetsHelper object has not been attached to a specific window yet, + // so we assume there's no title bar. return false; } - if (!data->titleBarWidget) { - // There's no title bar at all, the mouse will always be in the client area. + const FramelessWidgetsHelperExtraDataPtr extraData = tryGetExtraData(window, false); + Q_ASSERT(extraData); + if (!extraData) { return false; } - if (!data->titleBarWidget->isVisible() || !data->titleBarWidget->isEnabled()) { - // The title bar is hidden or disabled for some reason, treat it as there's no title bar. + if (!extraData->titleBarWidget) { + // There's no title bar at all, the mouse will always be in the client area. return false; } - if (!window) { - // The FramelessWidgetsHelper object has not been attached to a specific window yet, - // so we assume there's no title bar. + if (!extraData->titleBarWidget->isVisible() || !extraData->titleBarWidget->isEnabled()) { + // The title bar is hidden or disabled for some reason, treat it as there's no title bar. return false; } const QRect windowRect = {QPoint(0, 0), window->size()}; - const QRect titleBarRect = mapWidgetGeometryToScene(data->titleBarWidget); + const QRect titleBarRect = mapWidgetGeometryToScene(extraData->titleBarWidget); if (!titleBarRect.intersects(windowRect)) { // The title bar is totally outside of the window for some reason, // also treat it as there's no title bar. @@ -602,24 +616,24 @@ bool FramelessWidgetsHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) } QRegion region = titleBarRect; const auto systemButtons = { - data->windowIconButton, data->contextHelpButton, - data->minimizeButton, data->maximizeButton, - data->closeButton + extraData->windowIconButton, extraData->contextHelpButton, + extraData->minimizeButton, extraData->maximizeButton, + extraData->closeButton }; for (auto &&button : std::as_const(systemButtons)) { if (button && button->isVisible() && button->isEnabled()) { region -= mapWidgetGeometryToScene(button); } } - if (!data->hitTestVisibleWidgets.isEmpty()) { - for (auto &&widget : std::as_const(data->hitTestVisibleWidgets)) { + if (!extraData->hitTestVisibleWidgets.isEmpty()) { + for (auto &&widget : std::as_const(extraData->hitTestVisibleWidgets)) { if (widget && widget->isVisible() && widget->isEnabled()) { region -= mapWidgetGeometryToScene(widget); } } } - if (!data->hitTestVisibleRects.isEmpty()) { - for (auto &&rect : std::as_const(data->hitTestVisibleRects)) { + if (!extraData->hitTestVisibleRects.isEmpty()) { + for (auto &&rect : std::as_const(extraData->hitTestVisibleRects)) { if (rect.isValid()) { region -= rect; } @@ -660,7 +674,7 @@ void FramelessWidgetsHelper::moveWindowToDesktopCenter() if (!d->window) { return; } - Utils::moveWindowToDesktopCenter(&d->getWindowData()->params, true); + std::ignore = Utils::moveWindowToDesktopCenter(d->window->winId(), true); } void FramelessWidgetsHelper::bringWindowToFront() @@ -692,7 +706,7 @@ void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos) const WId windowId = d->window->winId(); const QPoint nativePos = Utils::toNativeGlobalPosition(d->window->windowHandle(), pos); #ifdef Q_OS_WINDOWS - std::ignore = Utils::showSystemMenu(windowId, nativePos, false, &d->getWindowData()->params); + std::ignore = Utils::showSystemMenu(windowId, nativePos, false); #elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) Utils::openSystemMenu(windowId, nativePos); #else @@ -730,26 +744,30 @@ void FramelessWidgetsHelper::setSystemButton(QWidget *widget, const SystemButton return; } Q_D(FramelessWidgetsHelper); - FramelessWidgetsHelperData *data = d->getWindowDataMutable(); - if (!data) { + if (!d->window) { + return; + } + const FramelessWidgetsHelperExtraDataPtr extraData = tryGetExtraData(d->window, false); + Q_ASSERT(extraData); + if (!extraData) { return; } switch (buttonType) { case SystemButtonType::WindowIcon: - data->windowIconButton = widget; + extraData->windowIconButton = widget; break; case SystemButtonType::Help: - data->contextHelpButton = widget; + extraData->contextHelpButton = widget; break; case SystemButtonType::Minimize: - data->minimizeButton = widget; + extraData->minimizeButton = widget; break; case SystemButtonType::Maximize: case SystemButtonType::Restore: - data->maximizeButton = widget; + extraData->maximizeButton = widget; break; case SystemButtonType::Close: - data->closeButton = widget; + extraData->closeButton = widget; break; case SystemButtonType::Unknown: Q_UNREACHABLE(); @@ -835,6 +853,7 @@ bool FramelessWidgetsHelper::isBlurBehindWindowEnabled() const void FramelessWidgetsHelper::setBlurBehindWindowEnabled(const bool enable) { +#if (!defined(Q_OS_WINDOWS) || FRAMELESSHELPER_CONFIG(native_impl)) Q_D(FramelessWidgetsHelper); if (!d->window) { return; @@ -866,6 +885,9 @@ void FramelessWidgetsHelper::setBlurBehindWindowEnabled(const bool enable) DEBUG << "Blur behind window is not supported on current platform."; } } +#else // Windows && !native_impl + Q_UNUSED(enable); +#endif } bool FramelessWidgetsHelper::isReady() const @@ -895,8 +917,11 @@ void FramelessWidgetsHelper::waitForReady() bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const { Q_D(const FramelessWidgetsHelper); - const FramelessWidgetsHelperData *data = d->getWindowData(); - return (data ? data->ready : false); + if (!d->window) { + return false; + } + const FramelessDataPtr data = FramelessManagerPrivate::getData(d->window); + return (data && data->frameless); } void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget) @@ -906,19 +931,30 @@ void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget) return; } Q_D(FramelessWidgetsHelper); - FramelessWidgetsHelperData *data = d->getWindowDataMutable(); - if (!data || (data->titleBarWidget == widget)) { + if (!d->window) { + return; + } + const FramelessWidgetsHelperExtraDataPtr extraData = tryGetExtraData(d->window, false); + Q_ASSERT(extraData); + if (!extraData || (extraData->titleBarWidget == widget)) { return; } - data->titleBarWidget = widget; + extraData->titleBarWidget = widget; d->emitSignalForAllInstances("titleBarWidgetChanged"); } QWidget *FramelessWidgetsHelper::titleBarWidget() const { Q_D(const FramelessWidgetsHelper); - const FramelessWidgetsHelperData *data = d->getWindowData(); - return (data ? data->titleBarWidget : nullptr); + if (!d->window) { + return nullptr; + } + const FramelessWidgetsHelperExtraDataPtr extraData = tryGetExtraData(d->window, false); + Q_ASSERT(extraData); + if (!extraData) { + return nullptr; + } + return extraData->titleBarWidget; } void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visible) @@ -928,32 +964,40 @@ void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visib return; } Q_D(FramelessWidgetsHelper); - FramelessWidgetsHelperData *data = d->getWindowDataMutable(); - if (!data) { + if (!d->window) { + return; + } + const FramelessWidgetsHelperExtraDataPtr extraData = tryGetExtraData(d->window, false); + Q_ASSERT(extraData); + if (!extraData) { return; } if (visible) { - data->hitTestVisibleWidgets.append(widget); + extraData->hitTestVisibleWidgets.append(widget); } else { - data->hitTestVisibleWidgets.removeAll(widget); + extraData->hitTestVisibleWidgets.removeAll(widget); } } void FramelessWidgetsHelper::setHitTestVisible(const QRect &rect, const bool visible) { - Q_ASSERT(rect.isValid()); - if (!rect.isValid()) { + Q_ASSERT(Utils::isValidGeometry(rect)); + if (!Utils::isValidGeometry(rect)) { return; } Q_D(FramelessWidgetsHelper); - FramelessWidgetsHelperData *data = d->getWindowDataMutable(); - if (!data) { + if (!d->window) { + return; + } + const FramelessWidgetsHelperExtraDataPtr extraData = tryGetExtraData(d->window, false); + Q_ASSERT(extraData); + if (!extraData) { return; } if (visible) { - data->hitTestVisibleRects.append(rect); + extraData->hitTestVisibleRects.append(rect); } else { - data->hitTestVisibleRects.removeAll(rect); + extraData->hitTestVisibleRects.removeAll(rect); } }