From 92415fb61cee14b26b80eeebc9b8d130de7f0d76 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Sat, 8 Oct 2022 16:14:40 +0800 Subject: [PATCH] Add WindowBorderPainter and WindowBorder 1. Added WindowBorderPainter for QtWidgets 2. Added WindowBorder for QtQuick (uses WindowBorderPainter internally) 3. Adjust some header includes 4. Limit a Linux workaround to the appropriate Qt versions Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/quick/MainWindow.qml | 5 +- examples/quick/settings.h | 8 +- .../FramelessHelper/Core/WindowBorderPainter | 1 + include/FramelessHelper/Core/chromepalette.h | 2 - .../FramelessHelper/Core/framelesshelper_qt.h | 2 - .../Core/framelesshelper_win.h | 1 - .../Core/framelesshelpercore_global.h | 17 + .../FramelessHelper/Core/framelessmanager.h | 2 - include/FramelessHelper/Core/micamaterial.h | 2 - .../Core/private/chromepalette_p.h | 3 - .../Core/private/framelessconfig_p.h | 2 - .../Core/private/framelessmanager_p.h | 2 - .../Core/private/micamaterial_p.h | 2 - .../Core/private/registrykey_p.h | 2 - .../Core/private/sysapiloader_p.h | 3 - .../Core/private/windowborderpainter_p.h | 65 ++++ include/FramelessHelper/Core/utils.h | 2 - .../Core/windowborderpainter.h | 86 ++++++ .../FramelessHelper/Quick/QuickWindowBorder | 1 + .../Quick/framelesshelperquick_global.h | 17 +- .../Quick/framelessquickhelper.h | 6 +- .../Quick/framelessquickmodule.h | 1 - .../Quick/framelessquickutils.h | 4 - .../Quick/private/framelessquickhelper_p.h | 6 +- .../Quick/private/framelessquickwindow_p.h | 7 +- .../Quick/private/framelessquickwindow_p_p.h | 22 +- .../Quick/private/quickimageitem_p.h | 2 - .../Quick/private/quickmicamaterial_p.h | 2 - .../Quick/private/quickwindowborder_p.h | 59 ++++ .../Quick/quickchromepalette.h | 4 +- .../FramelessHelper/Quick/quickimageitem.h | 1 - .../FramelessHelper/Quick/quickmicamaterial.h | 1 - .../FramelessHelper/Quick/quickwindowborder.h | 95 ++++++ .../FramelessHelper/Widgets/framelessdialog.h | 1 - .../Widgets/framelesshelperwidgets_global.h | 1 - .../Widgets/framelessmainwindow.h | 1 - .../FramelessHelper/Widgets/framelesswidget.h | 1 - .../Widgets/framelesswidgetshelper.h | 7 +- .../Widgets/private/framelessdialog_p.h | 2 - .../Widgets/private/framelessmainwindow_p.h | 2 - .../Widgets/private/framelesswidget_p.h | 2 - .../private/framelesswidgetshelper_p.h | 5 +- .../Widgets/private/standardsystembutton_p.h | 3 - .../Widgets/private/standardtitlebar_p.h | 3 - .../Widgets/private/widgetssharedhelper_p.h | 9 +- .../Widgets/standardsystembutton.h | 1 - .../Widgets/standardtitlebar.h | 1 - qmake/core.pri | 7 +- qmake/quick.pri | 7 +- src/core/CMakeLists.txt | 4 + src/core/framelesshelper_win.cpp | 2 - src/core/framelesshelpercore_global.cpp | 6 + src/core/framelessmanager.cpp | 1 - src/core/micamaterial.cpp | 1 - src/core/registrykey.cpp | 1 - src/core/sysapiloader.cpp | 1 - src/core/utils.cpp | 1 - src/core/utils_linux.cpp | 8 +- src/core/utils_mac.mm | 1 - src/core/utils_win.cpp | 1 - src/core/windowborderpainter.cpp | 290 ++++++++++++++++++ src/core/windowborderpainter.h | 1 + src/core/windowborderpainter_p.h | 1 + src/quick/CMakeLists.txt | 4 + src/quick/framelesshelperquick_global.cpp | 7 + src/quick/framelessquickhelper.cpp | 56 +++- src/quick/framelessquickmodule.cpp | 10 +- src/quick/framelessquickwindow.cpp | 70 +---- src/quick/quickimageitem.cpp | 1 - src/quick/quickmicamaterial.cpp | 1 - src/quick/quickwindowborder.cpp | 265 ++++++++++++++++ src/quick/quickwindowborder.h | 1 + src/quick/quickwindowborder_p.h | 1 + src/widgets/framelesswidgetshelper.cpp | 35 ++- src/widgets/widgetssharedhelper.cpp | 51 +-- 75 files changed, 1106 insertions(+), 203 deletions(-) create mode 100644 include/FramelessHelper/Core/WindowBorderPainter create mode 100644 include/FramelessHelper/Core/private/windowborderpainter_p.h create mode 100644 include/FramelessHelper/Core/windowborderpainter.h create mode 100644 include/FramelessHelper/Quick/QuickWindowBorder create mode 100644 include/FramelessHelper/Quick/private/quickwindowborder_p.h create mode 100644 include/FramelessHelper/Quick/quickwindowborder.h create mode 100644 src/core/windowborderpainter.cpp create mode 100644 src/core/windowborderpainter.h create mode 100644 src/core/windowborderpainter_p.h create mode 100644 src/quick/quickwindowborder.cpp create mode 100644 src/quick/quickwindowborder.h create mode 100644 src/quick/quickwindowborder_p.h diff --git a/examples/quick/MainWindow.qml b/examples/quick/MainWindow.qml index 07f6311..7660166 100644 --- a/examples/quick/MainWindow.qml +++ b/examples/quick/MainWindow.qml @@ -46,7 +46,7 @@ FramelessWindow { title: qsTr("FramelessHelper demo application - Qt Quick") color: { if (FramelessHelper.blurBehindWindowEnabled) { - return Qt.color("transparent"); + return "transparent"; } if (FramelessUtils.systemTheme === FramelessHelperConstants.Dark) { return FramelessUtils.defaultSystemDarkColor; @@ -107,7 +107,8 @@ FramelessWindow { StandardTitleBar { id: titleBar anchors { - top: window.topBorderBottom // VERY IMPORTANT! + top: parent.top + topMargin: window.visibility === Window.Windowed ? 1 : 0 left: parent.left right: parent.right } diff --git a/examples/quick/settings.h b/examples/quick/settings.h index f07d135..2fb5b89 100644 --- a/examples/quick/settings.h +++ b/examples/quick/settings.h @@ -24,14 +24,8 @@ #pragma once -#include #include -#include -#if __has_include() -# include -#else -# include -#endif +#include QT_BEGIN_NAMESPACE class QSettings; diff --git a/include/FramelessHelper/Core/WindowBorderPainter b/include/FramelessHelper/Core/WindowBorderPainter new file mode 100644 index 0000000..726fd0a --- /dev/null +++ b/include/FramelessHelper/Core/WindowBorderPainter @@ -0,0 +1 @@ +#include diff --git a/include/FramelessHelper/Core/chromepalette.h b/include/FramelessHelper/Core/chromepalette.h index 1ebc57d..95e5d1d 100644 --- a/include/FramelessHelper/Core/chromepalette.h +++ b/include/FramelessHelper/Core/chromepalette.h @@ -25,8 +25,6 @@ #pragma once #include "framelesshelpercore_global.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/framelesshelper_qt.h b/include/FramelessHelper/Core/framelesshelper_qt.h index a4cb324..711912e 100644 --- a/include/FramelessHelper/Core/framelesshelper_qt.h +++ b/include/FramelessHelper/Core/framelesshelper_qt.h @@ -25,8 +25,6 @@ #pragma once #include "framelesshelpercore_global.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/framelesshelper_win.h b/include/FramelessHelper/Core/framelesshelper_win.h index 3fc093e..2d737fa 100644 --- a/include/FramelessHelper/Core/framelesshelper_win.h +++ b/include/FramelessHelper/Core/framelesshelper_win.h @@ -26,7 +26,6 @@ #include "framelesshelpercore_global.h" #include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/framelesshelpercore_global.h b/include/FramelessHelper/Core/framelesshelpercore_global.h index c9157de..9928182 100644 --- a/include/FramelessHelper/Core/framelesshelpercore_global.h +++ b/include/FramelessHelper/Core/framelesshelpercore_global.h @@ -28,10 +28,14 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include QT_BEGIN_NAMESPACE class QScreen; @@ -366,6 +370,19 @@ enum class RegistryRootKey Q_ENUM_NS(RegistryRootKey) #endif // Q_OS_WINDOWS +enum class WindowEdge +{ + Unspecified = 0x00000000, + Left = 0x00000002, + Top = 0x00000004, + Right = 0x00000008, + Bottom = 0x00000010 +}; +Q_ENUM_NS(WindowEdge) +Q_DECLARE_FLAGS(WindowEdges, WindowEdge) +Q_FLAG_NS(WindowEdges) +Q_DECLARE_OPERATORS_FOR_FLAGS(WindowEdges) + struct VersionNumber { int major = 0; diff --git a/include/FramelessHelper/Core/framelessmanager.h b/include/FramelessHelper/Core/framelessmanager.h index 7295c0f..88f762e 100644 --- a/include/FramelessHelper/Core/framelessmanager.h +++ b/include/FramelessHelper/Core/framelessmanager.h @@ -25,8 +25,6 @@ #pragma once #include "framelesshelpercore_global.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/micamaterial.h b/include/FramelessHelper/Core/micamaterial.h index c04dcea..92550d7 100644 --- a/include/FramelessHelper/Core/micamaterial.h +++ b/include/FramelessHelper/Core/micamaterial.h @@ -25,8 +25,6 @@ #pragma once #include "framelesshelpercore_global.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/private/chromepalette_p.h b/include/FramelessHelper/Core/private/chromepalette_p.h index 1ab14f1..fb0f2e1 100644 --- a/include/FramelessHelper/Core/private/chromepalette_p.h +++ b/include/FramelessHelper/Core/private/chromepalette_p.h @@ -26,9 +26,6 @@ #include "framelesshelpercore_global.h" #include "chromepalette.h" -#include -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/private/framelessconfig_p.h b/include/FramelessHelper/Core/private/framelessconfig_p.h index 4c5db0b..f5c0ca4 100644 --- a/include/FramelessHelper/Core/private/framelessconfig_p.h +++ b/include/FramelessHelper/Core/private/framelessconfig_p.h @@ -25,9 +25,7 @@ #pragma once #include "framelesshelpercore_global.h" -#include #include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/private/framelessmanager_p.h b/include/FramelessHelper/Core/private/framelessmanager_p.h index 68b75f3..5fd7801 100644 --- a/include/FramelessHelper/Core/private/framelessmanager_p.h +++ b/include/FramelessHelper/Core/private/framelessmanager_p.h @@ -26,8 +26,6 @@ #include "framelesshelpercore_global.h" #include "framelessmanager.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/private/micamaterial_p.h b/include/FramelessHelper/Core/private/micamaterial_p.h index 49552d0..9a7613c 100644 --- a/include/FramelessHelper/Core/private/micamaterial_p.h +++ b/include/FramelessHelper/Core/private/micamaterial_p.h @@ -26,8 +26,6 @@ #include "framelesshelpercore_global.h" #include "micamaterial.h" -#include -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/private/registrykey_p.h b/include/FramelessHelper/Core/private/registrykey_p.h index 81cd51e..9ced2c2 100644 --- a/include/FramelessHelper/Core/private/registrykey_p.h +++ b/include/FramelessHelper/Core/private/registrykey_p.h @@ -25,9 +25,7 @@ #pragma once #include "framelesshelpercore_global.h" -#include #include -#include #ifndef REGISTRYKEY_FORCE_QSETTINGS # define REGISTRYKEY_FORCE_QSETTINGS (0) diff --git a/include/FramelessHelper/Core/private/sysapiloader_p.h b/include/FramelessHelper/Core/private/sysapiloader_p.h index 65b6314..b093255 100644 --- a/include/FramelessHelper/Core/private/sysapiloader_p.h +++ b/include/FramelessHelper/Core/private/sysapiloader_p.h @@ -25,12 +25,9 @@ #pragma once #include "framelesshelpercore_global.h" -#include #include #include -#include - FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_CORE_API SysApiLoader : public QObject diff --git a/include/FramelessHelper/Core/private/windowborderpainter_p.h b/include/FramelessHelper/Core/private/windowborderpainter_p.h new file mode 100644 index 0000000..e365eff --- /dev/null +++ b/include/FramelessHelper/Core/private/windowborderpainter_p.h @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include "framelesshelpercore_global.h" +#include "windowborderpainter.h" + +FRAMELESSHELPER_BEGIN_NAMESPACE + +class FRAMELESSHELPER_CORE_API WindowBorderPainterPrivate : public QObject +{ + Q_OBJECT + Q_DECLARE_PUBLIC(WindowBorderPainter) + Q_DISABLE_COPY_MOVE(WindowBorderPainterPrivate) + +public: + explicit WindowBorderPainterPrivate(WindowBorderPainter *q); + ~WindowBorderPainterPrivate() override; + + Q_NODISCARD static WindowBorderPainterPrivate *get(WindowBorderPainter *q); + Q_NODISCARD static const WindowBorderPainterPrivate *get(const WindowBorderPainter *q); + + Q_NODISCARD static int getNativeBorderThickness(); + Q_NODISCARD static QColor getNativeBorderColor(const bool active); + Q_NODISCARD static Global::WindowEdges getNativeBorderEdges(); + +public Q_SLOTS: + void paint(QPainter *painter, const QSize &size, const bool active) const; + +private: + void initialize(); + +private: + QPointer q_ptr = nullptr; + std::optional m_thickness = std::nullopt; + std::optional m_edges = std::nullopt; + std::optional m_activeColor = std::nullopt; + std::optional m_inactiveColor = std::nullopt; +}; + +FRAMELESSHELPER_END_NAMESPACE + +Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(WindowBorderPainterPrivate)) diff --git a/include/FramelessHelper/Core/utils.h b/include/FramelessHelper/Core/utils.h index 019be7b..42383c5 100644 --- a/include/FramelessHelper/Core/utils.h +++ b/include/FramelessHelper/Core/utils.h @@ -25,8 +25,6 @@ #pragma once #include "framelesshelpercore_global.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Core/windowborderpainter.h b/include/FramelessHelper/Core/windowborderpainter.h new file mode 100644 index 0000000..5b5e512 --- /dev/null +++ b/include/FramelessHelper/Core/windowborderpainter.h @@ -0,0 +1,86 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include "framelesshelpercore_global.h" + +FRAMELESSHELPER_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcWindowBorderPainter) + +class WindowBorderPainterPrivate; + +class FRAMELESSHELPER_CORE_API WindowBorderPainter : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(WindowBorderPainter) + Q_DECLARE_PRIVATE(WindowBorderPainter) + + Q_PROPERTY(int thickness READ thickness WRITE setThickness NOTIFY thicknessChanged FINAL) + Q_PROPERTY(Global::WindowEdges edges READ edges WRITE setEdges NOTIFY edgesChanged FINAL) + Q_PROPERTY(QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged FINAL) + Q_PROPERTY(QColor inactiveColor READ inactiveColor WRITE setInactiveColor NOTIFY inactiveColorChanged FINAL) + + Q_PROPERTY(int nativeThickness READ nativeThickness NOTIFY nativeBorderChanged FINAL) + Q_PROPERTY(Global::WindowEdges nativeEdges READ nativeEdges NOTIFY nativeBorderChanged FINAL) + Q_PROPERTY(QColor nativeActiveColor READ nativeActiveColor NOTIFY nativeBorderChanged FINAL) + Q_PROPERTY(QColor nativeInactiveColor READ nativeInactiveColor NOTIFY nativeBorderChanged FINAL) + +public: + explicit WindowBorderPainter(QObject *parent = nullptr); + ~WindowBorderPainter() override; + + Q_NODISCARD int thickness() const; + Q_NODISCARD Global::WindowEdges edges() const; + Q_NODISCARD QColor activeColor() const; + Q_NODISCARD QColor inactiveColor() const; + + Q_NODISCARD int nativeThickness() const; + Q_NODISCARD Global::WindowEdges nativeEdges() const; + Q_NODISCARD QColor nativeActiveColor() const; + Q_NODISCARD QColor nativeInactiveColor() const; + +public Q_SLOTS: + void paint(QPainter *painter, const QSize &size, const bool active) const; + void setThickness(const int value); + void setEdges(const Global::WindowEdges value); + void setActiveColor(const QColor &value); + void setInactiveColor(const QColor &value); + +Q_SIGNALS: + void thicknessChanged(); + void edgesChanged(); + void activeColorChanged(); + void inactiveColorChanged(); + void nativeBorderChanged(); + void shouldRepaint(); + +private: + QScopedPointer d_ptr; +}; + +FRAMELESSHELPER_END_NAMESPACE + +Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(WindowBorderPainter)) diff --git a/include/FramelessHelper/Quick/QuickWindowBorder b/include/FramelessHelper/Quick/QuickWindowBorder new file mode 100644 index 0000000..db95f69 --- /dev/null +++ b/include/FramelessHelper/Quick/QuickWindowBorder @@ -0,0 +1 @@ +#include diff --git a/include/FramelessHelper/Quick/framelesshelperquick_global.h b/include/FramelessHelper/Quick/framelesshelperquick_global.h index 0c8edff..26539ad 100644 --- a/include/FramelessHelper/Quick/framelesshelperquick_global.h +++ b/include/FramelessHelper/Quick/framelesshelperquick_global.h @@ -25,11 +25,9 @@ #pragma once #include -#include +#include #if __has_include() # include -#else -# include #endif #ifndef FRAMELESSHELPER_QUICK_API @@ -186,7 +184,20 @@ public: FRAMELESSHELPER_QUICK_ENUM_VALUE(BlurMode, Windows_Mica) }; Q_ENUM(BlurMode) + + enum class WindowEdge + { + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowEdge, Unspecified) + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowEdge, Left) + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowEdge, Top) + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowEdge, Right) + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowEdge, Bottom) + }; + Q_ENUM(WindowEdge) + Q_DECLARE_FLAGS(WindowEdges, WindowEdge) + Q_FLAG(WindowEdges) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QuickGlobal::WindowEdges) namespace FramelessHelper::Quick { diff --git a/include/FramelessHelper/Quick/framelessquickhelper.h b/include/FramelessHelper/Quick/framelessquickhelper.h index 4736021..7016767 100644 --- a/include/FramelessHelper/Quick/framelessquickhelper.h +++ b/include/FramelessHelper/Quick/framelessquickhelper.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperquick_global.h" -#include #include #include @@ -34,6 +33,8 @@ FRAMELESSHELPER_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcFramelessQuickHelper) class FramelessQuickHelperPrivate; +class QuickMicaMaterial; +class QuickWindowBorder; class FRAMELESSHELPER_QUICK_API FramelessQuickHelper : public QQuickItem { @@ -64,6 +65,9 @@ public: Q_NODISCARD bool isBlurBehindWindowEnabled() const; Q_NODISCARD bool isContentExtendedIntoTitleBar() const; + Q_NODISCARD QuickMicaMaterial *micaMaterial() const; + Q_NODISCARD QuickWindowBorder *windowBorder() const; + public Q_SLOTS: void extendsContentIntoTitleBar(const bool value = true); diff --git a/include/FramelessHelper/Quick/framelessquickmodule.h b/include/FramelessHelper/Quick/framelessquickmodule.h index 3bf22f6..07d517a 100644 --- a/include/FramelessHelper/Quick/framelessquickmodule.h +++ b/include/FramelessHelper/Quick/framelessquickmodule.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperquick_global.h" -#include QT_BEGIN_NAMESPACE class QQmlEngine; diff --git a/include/FramelessHelper/Quick/framelessquickutils.h b/include/FramelessHelper/Quick/framelessquickutils.h index 2e4222a..595942e 100644 --- a/include/FramelessHelper/Quick/framelessquickutils.h +++ b/include/FramelessHelper/Quick/framelessquickutils.h @@ -25,10 +25,6 @@ #pragma once #include "framelesshelperquick_global.h" -#include -#include -#include -#include #include QT_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h index 84bd411..5304672 100644 --- a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h @@ -26,9 +26,6 @@ #include "framelesshelperquick_global.h" #include "framelessquickhelper.h" -#include -#include -#include QT_BEGIN_NAMESPACE class QQuickItem; @@ -80,6 +77,9 @@ public: void setProperty(const QByteArray &name, const QVariant &value); Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {}); + Q_NODISCARD QuickMicaMaterial *findOrCreateMicaMaterial() const; + Q_NODISCARD QuickWindowBorder *findOrCreateWindowBorder() const; + protected: Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; diff --git a/include/FramelessHelper/Quick/private/framelessquickwindow_p.h b/include/FramelessHelper/Quick/private/framelessquickwindow_p.h index 261722c..2baf6b1 100644 --- a/include/FramelessHelper/Quick/private/framelessquickwindow_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickwindow_p.h @@ -25,12 +25,9 @@ #pragma once #include "framelesshelperquick_global.h" -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #include #include -Q_MOC_INCLUDE("framelessquickwindow_p_p.h") - FRAMELESSHELPER_BEGIN_NAMESPACE class FramelessQuickWindowPrivate; @@ -49,7 +46,6 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow, publ Q_PROPERTY(bool maximized READ isMaximized NOTIFY maximizedChanged FINAL) Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL) Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL) - Q_PRIVATE_PROPERTY(FramelessQuickWindow::d_func(), QQuickAnchorLine topBorderBottom READ getTopBorderBottom CONSTANT FINAL) public: explicit FramelessQuickWindow(QWindow *parent = nullptr); @@ -85,6 +81,5 @@ private: FRAMELESSHELPER_END_NAMESPACE -Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow)) +Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow)) QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow)) -#endif diff --git a/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h b/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h index df07e58..0b543c3 100644 --- a/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickwindow_p_p.h @@ -25,18 +25,12 @@ #pragma once #include "framelesshelperquick_global.h" -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #include "framelessquickwindow_p.h" -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QQuickRectangle; -QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE +class QuickWindowBorder; + class FRAMELESSHELPER_QUICK_API FramelessQuickWindowPrivate : public QObject { Q_OBJECT @@ -57,9 +51,6 @@ public: Q_INVOKABLE Q_NODISCARD bool isZoomed() const; Q_INVOKABLE Q_NODISCARD bool isFullScreen() const; - Q_INVOKABLE Q_NODISCARD QColor getFrameBorderColor() const; - Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderBottom() const; - public Q_SLOTS: void showMinimized2(); void toggleMaximized(); @@ -70,17 +61,14 @@ private: Q_NODISCARD bool shouldDrawFrameBorder() const; private Q_SLOTS: - void updateTopBorderColor(); - void updateTopBorderHeight(); + void updateWindowBorderVisibility(); private: QPointer q_ptr = nullptr; - QScopedPointer m_topBorderRectangle; - QScopedPointer m_topBorderAnchors; + QScopedPointer m_windowBorder; QQuickWindow::Visibility m_savedVisibility = QQuickWindow::Windowed; }; FRAMELESSHELPER_END_NAMESPACE -Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindowPrivate)) -#endif +Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindowPrivate)) diff --git a/include/FramelessHelper/Quick/private/quickimageitem_p.h b/include/FramelessHelper/Quick/private/quickimageitem_p.h index 2f14a5b..b898e67 100644 --- a/include/FramelessHelper/Quick/private/quickimageitem_p.h +++ b/include/FramelessHelper/Quick/private/quickimageitem_p.h @@ -26,8 +26,6 @@ #include "framelesshelperquick_global.h" #include "quickimageitem.h" -#include -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/quickmicamaterial_p.h b/include/FramelessHelper/Quick/private/quickmicamaterial_p.h index a62f48f..5aac1ed 100644 --- a/include/FramelessHelper/Quick/private/quickmicamaterial_p.h +++ b/include/FramelessHelper/Quick/private/quickmicamaterial_p.h @@ -26,8 +26,6 @@ #include "framelesshelperquick_global.h" #include "quickmicamaterial.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Quick/private/quickwindowborder_p.h b/include/FramelessHelper/Quick/private/quickwindowborder_p.h new file mode 100644 index 0000000..b713a61 --- /dev/null +++ b/include/FramelessHelper/Quick/private/quickwindowborder_p.h @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include "framelesshelperquick_global.h" +#include "quickwindowborder.h" + +FRAMELESSHELPER_BEGIN_NAMESPACE + +class WindowBorderPainter; + +class FRAMELESSHELPER_QUICK_API QuickWindowBorderPrivate : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(QuickWindowBorderPrivate) + Q_DECLARE_PUBLIC(QuickWindowBorder) + +public: + explicit QuickWindowBorderPrivate(QuickWindowBorder *q); + ~QuickWindowBorderPrivate() override; + + Q_NODISCARD static QuickWindowBorderPrivate *get(QuickWindowBorder *q); + Q_NODISCARD static const QuickWindowBorderPrivate *get(const QuickWindowBorder *q); + + void paint(QPainter *painter) const; + +private: + void initialize(); + +private: + QPointer q_ptr = nullptr; + QScopedPointer m_borderPainter; +}; + +FRAMELESSHELPER_END_NAMESPACE + +Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickWindowBorderPrivate)) diff --git a/include/FramelessHelper/Quick/quickchromepalette.h b/include/FramelessHelper/Quick/quickchromepalette.h index ee25419..2005fea 100644 --- a/include/FramelessHelper/Quick/quickchromepalette.h +++ b/include/FramelessHelper/Quick/quickchromepalette.h @@ -25,10 +25,8 @@ #pragma once #include "framelesshelperquick_global.h" -#include -#include -#include #include +#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Quick/quickimageitem.h b/include/FramelessHelper/Quick/quickimageitem.h index 21c8515..37cfa48 100644 --- a/include/FramelessHelper/Quick/quickimageitem.h +++ b/include/FramelessHelper/Quick/quickimageitem.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperquick_global.h" -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Quick/quickmicamaterial.h b/include/FramelessHelper/Quick/quickmicamaterial.h index 5aa06a1..d9d3665 100644 --- a/include/FramelessHelper/Quick/quickmicamaterial.h +++ b/include/FramelessHelper/Quick/quickmicamaterial.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperquick_global.h" -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Quick/quickwindowborder.h b/include/FramelessHelper/Quick/quickwindowborder.h new file mode 100644 index 0000000..1af0a0b --- /dev/null +++ b/include/FramelessHelper/Quick/quickwindowborder.h @@ -0,0 +1,95 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include "framelesshelperquick_global.h" +#include + +FRAMELESSHELPER_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcQuickWindowBorder) + +class QuickWindowBorderPrivate; + +class FRAMELESSHELPER_QUICK_API QuickWindowBorder : public QQuickPaintedItem +{ + Q_OBJECT +#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) + Q_PROPERTY(QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged FINAL) + Q_PROPERTY(QColor inactiveColor READ inactiveColor WRITE setInactiveColor NOTIFY inactiveColorChanged FINAL) + + Q_PROPERTY(qreal nativeThickness READ nativeThickness NOTIFY nativeBorderChanged FINAL) + Q_PROPERTY(QuickGlobal::WindowEdges nativeEdges READ nativeEdges NOTIFY nativeBorderChanged FINAL) + Q_PROPERTY(QColor nativeActiveColor READ nativeActiveColor NOTIFY nativeBorderChanged FINAL) + Q_PROPERTY(QColor nativeInactiveColor READ nativeInactiveColor NOTIFY nativeBorderChanged FINAL) + +public: + explicit QuickWindowBorder(QQuickItem *parent = nullptr); + ~QuickWindowBorder() override; + + void paint(QPainter *painter) override; + + Q_NODISCARD qreal thickness() const; + Q_NODISCARD QuickGlobal::WindowEdges edges() const; + Q_NODISCARD QColor activeColor() const; + Q_NODISCARD QColor inactiveColor() const; + + Q_NODISCARD qreal nativeThickness() const; + Q_NODISCARD QuickGlobal::WindowEdges nativeEdges() const; + Q_NODISCARD QColor nativeActiveColor() const; + Q_NODISCARD QColor nativeInactiveColor() const; + +public Q_SLOTS: + void setThickness(const qreal value); + void setEdges(const QuickGlobal::WindowEdges value); + void setActiveColor(const QColor &value); + void setInactiveColor(const QColor &value); + +protected: + void classBegin() override; + void componentComplete() override; + +Q_SIGNALS: + void thicknessChanged(); + void edgesChanged(); + void activeColorChanged(); + void inactiveColorChanged(); + void nativeBorderChanged(); + +private: + QScopedPointer d_ptr; +}; + +FRAMELESSHELPER_END_NAMESPACE + +Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickWindowBorder)) +QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickWindowBorder)) diff --git a/include/FramelessHelper/Widgets/framelessdialog.h b/include/FramelessHelper/Widgets/framelessdialog.h index 7cf138c..d350fcc 100644 --- a/include/FramelessHelper/Widgets/framelessdialog.h +++ b/include/FramelessHelper/Widgets/framelessdialog.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperwidgets_global.h" -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelesshelperwidgets_global.h b/include/FramelessHelper/Widgets/framelesshelperwidgets_global.h index df89c6a..4139430 100644 --- a/include/FramelessHelper/Widgets/framelesshelperwidgets_global.h +++ b/include/FramelessHelper/Widgets/framelesshelperwidgets_global.h @@ -25,7 +25,6 @@ #pragma once #include -#include #ifndef FRAMELESSHELPER_WIDGETS_API # ifdef FRAMELESSHELPER_WIDGETS_STATIC diff --git a/include/FramelessHelper/Widgets/framelessmainwindow.h b/include/FramelessHelper/Widgets/framelessmainwindow.h index f13b353..d1517fe 100644 --- a/include/FramelessHelper/Widgets/framelessmainwindow.h +++ b/include/FramelessHelper/Widgets/framelessmainwindow.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperwidgets_global.h" -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelesswidget.h b/include/FramelessHelper/Widgets/framelesswidget.h index de10af1..34171d6 100644 --- a/include/FramelessHelper/Widgets/framelesswidget.h +++ b/include/FramelessHelper/Widgets/framelesswidget.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperwidgets_global.h" -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelesswidgetshelper.h b/include/FramelessHelper/Widgets/framelesswidgetshelper.h index 40c6b9d..703ee1f 100644 --- a/include/FramelessHelper/Widgets/framelesswidgetshelper.h +++ b/include/FramelessHelper/Widgets/framelesswidgetshelper.h @@ -25,8 +25,6 @@ #pragma once #include "framelesshelperwidgets_global.h" -#include -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE @@ -34,6 +32,8 @@ FRAMELESSHELPER_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcFramelessWidgetsHelper) class FramelessWidgetsHelperPrivate; +class MicaMaterial; +class WindowBorderPainter; class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelper : public QObject { @@ -58,6 +58,9 @@ public: Q_NODISCARD QWidget *window() const; Q_NODISCARD bool isContentExtendedIntoTitleBar() const; + Q_NODISCARD MicaMaterial *micaMaterial() const; + Q_NODISCARD WindowBorderPainter *windowBorder() const; + public Q_SLOTS: void extendsContentIntoTitleBar(const bool value = true); diff --git a/include/FramelessHelper/Widgets/private/framelessdialog_p.h b/include/FramelessHelper/Widgets/private/framelessdialog_p.h index 0137c33..3e180bc 100644 --- a/include/FramelessHelper/Widgets/private/framelessdialog_p.h +++ b/include/FramelessHelper/Widgets/private/framelessdialog_p.h @@ -26,8 +26,6 @@ #include "framelesshelperwidgets_global.h" #include "framelessdialog.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h b/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h index 74ce3e2..f615abe 100644 --- a/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h +++ b/include/FramelessHelper/Widgets/private/framelessmainwindow_p.h @@ -26,8 +26,6 @@ #include "framelesshelperwidgets_global.h" #include "framelessmainwindow.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/framelesswidget_p.h b/include/FramelessHelper/Widgets/private/framelesswidget_p.h index 589cfb8..01b7691 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidget_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidget_p.h @@ -26,8 +26,6 @@ #include "framelesshelperwidgets_global.h" #include "framelesswidget.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h index f9ed797..9f9158b 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h @@ -26,8 +26,6 @@ #include "framelesshelperwidgets_global.h" #include "framelesswidgetshelper.h" -#include -#include FRAMELESSHELPER_BEGIN_NAMESPACE @@ -77,6 +75,9 @@ public: Q_NODISCARD QWidget *window() const; + Q_NODISCARD MicaMaterial *getMicaMaterialIfAny() const; + Q_NODISCARD WindowBorderPainter *getWindowBorderIfAny() const; + private: Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const; Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const; diff --git a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h index c8a6fb4..89b650c 100644 --- a/include/FramelessHelper/Widgets/private/standardsystembutton_p.h +++ b/include/FramelessHelper/Widgets/private/standardsystembutton_p.h @@ -26,9 +26,6 @@ #include "framelesshelperwidgets_global.h" #include "standardsystembutton.h" -#include -#include -#include QT_BEGIN_NAMESPACE class QEnterEvent; diff --git a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h index 35366c3..2649286 100644 --- a/include/FramelessHelper/Widgets/private/standardtitlebar_p.h +++ b/include/FramelessHelper/Widgets/private/standardtitlebar_p.h @@ -26,9 +26,6 @@ #include "framelesshelperwidgets_global.h" #include "standardtitlebar.h" -#include -#include -#include QT_BEGIN_NAMESPACE class QPaintEvent; diff --git a/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h b/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h index a458caa..5432fae 100644 --- a/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h +++ b/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h @@ -25,8 +25,6 @@ #pragma once #include "framelesshelperwidgets_global.h" -#include -#include #include QT_BEGIN_NAMESPACE @@ -36,6 +34,7 @@ QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE class MicaMaterial; +class WindowBorderPainter; class FRAMELESSHELPER_WIDGETS_API WidgetsSharedHelper : public QObject { @@ -52,6 +51,9 @@ public: Q_NODISCARD bool isMicaEnabled() const; void setMicaEnabled(const bool value); + Q_NODISCARD MicaMaterial *rawMicaMaterial() const; + Q_NODISCARD WindowBorderPainter *rawWindowBorder() const; + protected: Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; @@ -82,6 +84,9 @@ private: QMetaObject::Connection m_micaRedrawConnection = {}; qreal m_screenDpr = 0.0; QMetaObject::Connection m_screenDpiChangeConnection = {}; + QScopedPointer m_borderPainter; + QMetaObject::Connection m_borderRepaintConnection = {}; + QMetaObject::Connection m_screenChangeConnection = {}; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/standardsystembutton.h b/include/FramelessHelper/Widgets/standardsystembutton.h index aaa9ae7..e6c2f63 100644 --- a/include/FramelessHelper/Widgets/standardsystembutton.h +++ b/include/FramelessHelper/Widgets/standardsystembutton.h @@ -25,7 +25,6 @@ #pragma once #include "framelesshelperwidgets_global.h" -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/include/FramelessHelper/Widgets/standardtitlebar.h b/include/FramelessHelper/Widgets/standardtitlebar.h index 69dfa34..39d0961 100644 --- a/include/FramelessHelper/Widgets/standardtitlebar.h +++ b/include/FramelessHelper/Widgets/standardtitlebar.h @@ -27,7 +27,6 @@ #include "framelesshelperwidgets_global.h" #include "standardsystembutton.h" #include -#include #include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/qmake/core.pri b/qmake/core.pri index 08761c4..5dd5402 100644 --- a/qmake/core.pri +++ b/qmake/core.pri @@ -26,11 +26,13 @@ HEADERS += \ $$CORE_PUB_INC_DIR/framelessmanager.h \ $$CORE_PUB_INC_DIR/micamaterial.h \ $$CORE_PUB_INC_DIR/utils.h \ + $$CORE_PUB_INC_DIR/windowborderpainter.h \ $$CORE_PRIV_INC_DIR/chromepalette_p.h \ $$CORE_PRIV_INC_DIR/framelessconfig_p.h \ $$CORE_PRIV_INC_DIR/framelessmanager_p.h \ $$CORE_PRIV_INC_DIR/micamaterial_p.h \ - $$CORE_PRIV_INC_DIR/sysapiloader_p.h + $$CORE_PRIV_INC_DIR/sysapiloader_p.h \ + $$CORE_PRIV_INC_DIR/windowborderpainter_p.h SOURCES += \ $$CORE_SRC_DIR/chromepalette.cpp \ @@ -40,7 +42,8 @@ SOURCES += \ $$CORE_SRC_DIR/framelesshelpercore_global.cpp \ $$CORE_SRC_DIR/micamaterial.cpp \ $$CORE_SRC_DIR/sysapiloader.cpp \ - $$CORE_SRC_DIR/utils.cpp + $$CORE_SRC_DIR/utils.cpp \ + $$CORE_SRC_DIR/windowborderpainter.cpp RESOURCES += \ $$CORE_SRC_DIR/framelesshelpercore.qrc diff --git a/qmake/quick.pri b/qmake/quick.pri index ddcec78..76f24d5 100644 --- a/qmake/quick.pri +++ b/qmake/quick.pri @@ -26,13 +26,15 @@ HEADERS += \ $$QUICK_PUB_INC_DIR/quickchromepalette.h \ $$QUICK_PUB_INC_DIR/quickmicamaterial.h \ $$QUICK_PUB_INC_DIR/quickimageitem.h \ + $$QUICK_PUB_INC_DIR/quickwindowborder.h \ $$QUICK_PRIV_INC_DIR/quickstandardsystembutton_p.h \ $$QUICK_PRIV_INC_DIR/quickstandardtitlebar_p.h \ $$QUICK_PRIV_INC_DIR/framelessquickhelper_p.h \ $$QUICK_PRIV_INC_DIR/framelessquickwindow_p.h \ $$QUICK_PRIV_INC_DIR/framelessquickwindow_p_p.h \ $$QUICK_PRIV_INC_DIR/quickmicamaterial_p.h \ - $$QUICK_PRIV_INC_DIR/quickimageitem_p.h + $$QUICK_PRIV_INC_DIR/quickimageitem_p.h \ + $$QUICK_PRIV_INC_DIR/quickwindowborder_p.h SOURCES += \ $$QUICK_SRC_DIR/quickstandardsystembutton.cpp \ @@ -44,4 +46,5 @@ SOURCES += \ $$QUICK_SRC_DIR/quickchromepalette.cpp \ $$QUICK_SRC_DIR/framelesshelperquick_global.cpp \ $$QUICK_SRC_DIR/quickmicamaterial.cpp \ - $$QUICK_SRC_DIR/quickimageitem.cpp + $$QUICK_SRC_DIR/quickimageitem.cpp \ + $$QUICK_SRC_DIR/quickwindowborder.cpp diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 0a9444a..fe910e9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -45,6 +45,7 @@ set(PUBLIC_HEADERS ${INCLUDE_PREFIX}/utils.h ${INCLUDE_PREFIX}/chromepalette.h ${INCLUDE_PREFIX}/micamaterial.h + ${INCLUDE_PREFIX}/windowborderpainter.h ) set(PUBLIC_HEADERS_ALIAS @@ -54,6 +55,7 @@ set(PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/Utils ${INCLUDE_PREFIX}/ChromePalette ${INCLUDE_PREFIX}/MicaMaterial + ${INCLUDE_PREFIX}/WindowBorderPainter ) set(PRIVATE_HEADERS @@ -62,6 +64,7 @@ set(PRIVATE_HEADERS ${INCLUDE_PREFIX}/private/sysapiloader_p.h ${INCLUDE_PREFIX}/private/chromepalette_p.h ${INCLUDE_PREFIX}/private/micamaterial_p.h + ${INCLUDE_PREFIX}/private/windowborderpainter_p.h ) set(SOURCES @@ -73,6 +76,7 @@ set(SOURCES chromepalette.cpp framelesshelpercore_global.cpp micamaterial.cpp + windowborderpainter.cpp ) if(WIN32) diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index 5ea86e1..5114d6a 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -23,7 +23,6 @@ */ #include "framelesshelper_win.h" -#include #include #include #include @@ -35,7 +34,6 @@ #include "utils.h" #include "winverhelper_p.h" #include "framelesshelper_windows.h" -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/src/core/framelesshelpercore_global.cpp b/src/core/framelesshelpercore_global.cpp index c2e72c0..fcdb465 100644 --- a/src/core/framelesshelpercore_global.cpp +++ b/src/core/framelesshelpercore_global.cpp @@ -31,11 +31,13 @@ #include "framelesshelper_qt.h" #include "chromepalette.h" #include "micamaterial.h" +#include "windowborderpainter.h" #include "sysapiloader_p.h" #include "framelessmanager_p.h" #include "framelessconfig_p.h" #include "chromepalette_p.h" #include "micamaterial_p.h" +#include "windowborderpainter_p.h" #ifdef Q_OS_WINDOWS # include "registrykey_p.h" #endif @@ -166,6 +168,8 @@ void initialize() # ifdef Q_OS_WINDOWS qRegisterMetaType(); # endif + qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); @@ -182,6 +186,8 @@ void initialize() qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); # ifdef Q_OS_WINDOWS qRegisterMetaType(); # endif diff --git a/src/core/framelessmanager.cpp b/src/core/framelessmanager.cpp index 1c304e2..fdc7d50 100644 --- a/src/core/framelessmanager.cpp +++ b/src/core/framelessmanager.cpp @@ -23,7 +23,6 @@ */ #include "framelessmanager_p.h" -#include #include #include #include diff --git a/src/core/micamaterial.cpp b/src/core/micamaterial.cpp index 4611e83..fe7b53b 100644 --- a/src/core/micamaterial.cpp +++ b/src/core/micamaterial.cpp @@ -27,7 +27,6 @@ #include "framelessmanager.h" #include "utils.h" #include "framelessconfig_p.h" -#include #include #include #include diff --git a/src/core/registrykey.cpp b/src/core/registrykey.cpp index 115b76c..77bddaf 100644 --- a/src/core/registrykey.cpp +++ b/src/core/registrykey.cpp @@ -24,7 +24,6 @@ #include "registrykey_p.h" #include "framelesshelper_windows.h" -#include #if REGISTRYKEY_QWINREGISTRYKEY # include #else diff --git a/src/core/sysapiloader.cpp b/src/core/sysapiloader.cpp index 01fa9f6..513fef8 100644 --- a/src/core/sysapiloader.cpp +++ b/src/core/sysapiloader.cpp @@ -23,7 +23,6 @@ */ #include "sysapiloader_p.h" -#include #ifdef Q_OS_WINDOWS # include #else diff --git a/src/core/utils.cpp b/src/core/utils.cpp index 60bb04a..90d2b89 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -23,7 +23,6 @@ */ #include "utils.h" -#include #include #include #include diff --git a/src/core/utils_linux.cpp b/src/core/utils_linux.cpp index 625b1c8..726d2c3 100644 --- a/src/core/utils_linux.cpp +++ b/src/core/utils_linux.cpp @@ -26,7 +26,6 @@ #include "framelessconfig_p.h" #include "framelessmanager.h" #include "framelessmanager_p.h" -#include #include #include #include @@ -373,7 +372,8 @@ static inline void xcb_flush(connection); } -static inline void sendMouseReleaseEvent(QWindow *window, const QPoint &globalPos) +[[maybe_unused]] static inline void + sendMouseReleaseEvent(QWindow *window, const QPoint &globalPos) { Q_ASSERT(window); if (!window) { @@ -398,8 +398,10 @@ void Utils::startSystemMove(QWindow *window, const QPoint &globalPos) if (!window) { return; } +#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0)) // Before we start the dragging we need to tell Qt that the mouse is released. sendMouseReleaseEvent(window, globalPos); +#endif #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) window->startSystemMove(); #else @@ -417,8 +419,10 @@ void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoi if (edges == Qt::Edges{}) { return; } +#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0)) // Before we start the resizing we need to tell Qt that the mouse is released. sendMouseReleaseEvent(window, globalPos); +#endif #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) window->startSystemResize(edges); #else diff --git a/src/core/utils_mac.mm b/src/core/utils_mac.mm index 8919143..7e3bdc4 100644 --- a/src/core/utils_mac.mm +++ b/src/core/utils_mac.mm @@ -26,7 +26,6 @@ #include "framelessmanager.h" #include "framelessmanager_p.h" #include "framelessconfig_p.h" -#include #include #include #include diff --git a/src/core/utils_win.cpp b/src/core/utils_win.cpp index 0a93597..f75cfb3 100644 --- a/src/core/utils_win.cpp +++ b/src/core/utils_win.cpp @@ -23,7 +23,6 @@ */ #include "utils.h" -#include #include #include #include diff --git a/src/core/windowborderpainter.cpp b/src/core/windowborderpainter.cpp new file mode 100644 index 0000000..ca9e0dd --- /dev/null +++ b/src/core/windowborderpainter.cpp @@ -0,0 +1,290 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "windowborderpainter.h" +#include "windowborderpainter_p.h" +#include "utils.h" +#include "framelessmanager.h" +#ifdef Q_OS_WINDOWS +# include "winverhelper_p.h" +#endif +#include + +FRAMELESSHELPER_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcWindowBorderPainter, "wangwenx190.framelesshelper.core.windowborderpainter") +#define INFO qCInfo(lcWindowBorderPainter) +#define DEBUG qCDebug(lcWindowBorderPainter) +#define WARNING qCWarning(lcWindowBorderPainter) +#define CRITICAL qCCritical(lcWindowBorderPainter) + +using namespace Global; + +static constexpr const int kMaximumBorderThickness = 100; + +WindowBorderPainterPrivate::WindowBorderPainterPrivate(WindowBorderPainter *q) : QObject(q) +{ + Q_ASSERT(q); + if (!q) { + return; + } + q_ptr = q; + initialize(); +} + +WindowBorderPainterPrivate::~WindowBorderPainterPrivate() = default; + +WindowBorderPainterPrivate *WindowBorderPainterPrivate::get(WindowBorderPainter *q) +{ + Q_ASSERT(q); + if (!q) { + return nullptr; + } + return q->d_func(); +} + +const WindowBorderPainterPrivate *WindowBorderPainterPrivate::get(const WindowBorderPainter *q) +{ + Q_ASSERT(q); + if (!q) { + return nullptr; + } + return q->d_func(); +} + +int WindowBorderPainterPrivate::getNativeBorderThickness() +{ + return kDefaultWindowFrameBorderThickness; +} + +QColor WindowBorderPainterPrivate::getNativeBorderColor(const bool active) +{ +#ifdef Q_OS_WINDOWS + return Utils::getFrameBorderColor(active); +#elif defined(Q_OS_LINUX) + return (active ? Utils::getWmThemeColor() : kDefaultDarkGrayColor); +#elif defined(Q_OS_MACOS) + return (active ? Utils::getControlsAccentColor() : kDefaultDarkGrayColor); +#else + return (active ? kDefaultBlackColor : kDefaultDarkGrayColor); +#endif +} + +WindowEdges WindowBorderPainterPrivate::getNativeBorderEdges() +{ +#ifdef Q_OS_WINDOWS + return (WindowsVersionHelper::isWin10OrGreater() ? WindowEdges(WindowEdge::Top) : WindowEdges()); +#else + return {}; +#endif +} + +void WindowBorderPainterPrivate::paint(QPainter *painter, const QSize &size, const bool active) const +{ + Q_ASSERT(painter); + if (!painter) { + return; + } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QList lines = {}; +#else + QVector lines = {}; +#endif + const QPoint leftTop = {0, 0}; + // In fact, we should use "size.width() - 1" here in theory but we can't + // because Qt's drawing system has some rounding errors internally and if + // we minus one here we'll get a one pixel gap, so sad. But drawing a line + // with a little extra pixels won't hurt anyway. + const QPoint rightTop = {size.width(), 0}; + // Same here as above: we should use "size.height() - 1" ideally but we + // can't, sadly. + const QPoint rightBottom = {size.width(), size.height()}; + const QPoint leftBottom = {0, size.height()}; + const WindowEdges edges = m_edges.value_or(getNativeBorderEdges()); + if (edges & WindowEdge::Left) { + lines.append({leftBottom, leftTop}); + } + if (edges & WindowEdge::Top) { + lines.append({leftTop, rightTop}); + } + if (edges & WindowEdge::Right) { + lines.append({rightTop, rightBottom}); + } + if (edges & WindowEdge::Bottom) { + lines.append({rightBottom, leftBottom}); + } + if (lines.isEmpty()) { + return; + } + painter->save(); + painter->setRenderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); + // We can't enable antialiasing here, because the border is too thin and antialiasing + // will break it's painting. + painter->setRenderHint(QPainter::Antialiasing, false); + QPen pen = {}; + pen.setColor([active, this]() -> QColor { + QColor color = {}; + if (active) { + color = m_activeColor.value_or(getNativeBorderColor(true)); + } else { + color = m_inactiveColor.value_or(getNativeBorderColor(false)); + } + if (color.isValid()) { + return color; + } + return (active ? kDefaultBlackColor : kDefaultDarkGrayColor); + }()); + pen.setWidth(m_thickness.value_or(getNativeBorderThickness())); + painter->setPen(pen); + painter->drawLines(lines); + painter->restore(); +} + +void WindowBorderPainterPrivate::initialize() +{ + Q_Q(WindowBorderPainter); + connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, + q, &WindowBorderPainter::nativeBorderChanged); + connect(q, &WindowBorderPainter::nativeBorderChanged, q, &WindowBorderPainter::shouldRepaint); +} + +WindowBorderPainter::WindowBorderPainter(QObject *parent) + : QObject(parent), d_ptr(new WindowBorderPainterPrivate(this)) +{ +} + +WindowBorderPainter::~WindowBorderPainter() = default; + +int WindowBorderPainter::thickness() const +{ + Q_D(const WindowBorderPainter); + return d->m_thickness.value_or(d->getNativeBorderThickness()); +} + +WindowEdges WindowBorderPainter::edges() const +{ + Q_D(const WindowBorderPainter); + return d->m_edges.value_or(d->getNativeBorderEdges()); +} + +QColor WindowBorderPainter::activeColor() const +{ + Q_D(const WindowBorderPainter); + return d->m_activeColor.value_or(d->getNativeBorderColor(true)); +} + +QColor WindowBorderPainter::inactiveColor() const +{ + Q_D(const WindowBorderPainter); + return d->m_inactiveColor.value_or(d->getNativeBorderColor(false)); +} + +int WindowBorderPainter::nativeThickness() const +{ + Q_D(const WindowBorderPainter); + return d->getNativeBorderThickness(); +} + +WindowEdges WindowBorderPainter::nativeEdges() const +{ + Q_D(const WindowBorderPainter); + return d->getNativeBorderEdges(); +} + +QColor WindowBorderPainter::nativeActiveColor() const +{ + Q_D(const WindowBorderPainter); + return d->getNativeBorderColor(true); +} + +QColor WindowBorderPainter::nativeInactiveColor() const +{ + Q_D(const WindowBorderPainter); + return d->getNativeBorderColor(false); +} + +void WindowBorderPainter::paint(QPainter *painter, const QSize &size, const bool active) const +{ + Q_D(const WindowBorderPainter); + d->paint(painter, size, active); +} + +void WindowBorderPainter::setThickness(const int value) +{ + Q_ASSERT(value >= 0); + Q_ASSERT(value < kMaximumBorderThickness); + if ((value < 0) || (value >= kMaximumBorderThickness)) { + return; + } + if (thickness() == value) { + return; + } + Q_D(WindowBorderPainter); + d->m_thickness = value; + Q_EMIT thicknessChanged(); + Q_EMIT shouldRepaint(); +} + +void WindowBorderPainter::setEdges(const Global::WindowEdges value) +{ + if (edges() == value) { + return; + } + Q_D(WindowBorderPainter); + d->m_edges = value; + Q_EMIT edgesChanged(); + Q_EMIT shouldRepaint(); +} + +void WindowBorderPainter::setActiveColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + if (activeColor() == value) { + return; + } + Q_D(WindowBorderPainter); + d->m_activeColor = value; + Q_EMIT activeColorChanged(); + Q_EMIT shouldRepaint(); +} + +void WindowBorderPainter::setInactiveColor(const QColor &value) +{ + Q_ASSERT(value.isValid()); + if (!value.isValid()) { + return; + } + if (inactiveColor() == value) { + return; + } + Q_D(WindowBorderPainter); + d->m_inactiveColor = value; + Q_EMIT inactiveColorChanged(); + Q_EMIT shouldRepaint(); +} + +FRAMELESSHELPER_END_NAMESPACE diff --git a/src/core/windowborderpainter.h b/src/core/windowborderpainter.h new file mode 100644 index 0000000..060e9c7 --- /dev/null +++ b/src/core/windowborderpainter.h @@ -0,0 +1 @@ +#include "../../include/FramelessHelper/Core/windowborderpainter.h" diff --git a/src/core/windowborderpainter_p.h b/src/core/windowborderpainter_p.h new file mode 100644 index 0000000..3e0bdc7 --- /dev/null +++ b/src/core/windowborderpainter_p.h @@ -0,0 +1 @@ +#include "../../include/FramelessHelper/Core/private/windowborderpainter_p.h" diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt index c488f90..7cc9cd0 100644 --- a/src/quick/CMakeLists.txt +++ b/src/quick/CMakeLists.txt @@ -39,6 +39,7 @@ set(PUBLIC_HEADERS ${INCLUDE_PREFIX}/quickchromepalette.h ${INCLUDE_PREFIX}/quickmicamaterial.h ${INCLUDE_PREFIX}/quickimageitem.h + ${INCLUDE_PREFIX}/quickwindowborder.h ) set(PUBLIC_HEADERS_ALIAS @@ -49,6 +50,7 @@ set(PUBLIC_HEADERS_ALIAS ${INCLUDE_PREFIX}/QuickChromePalette ${INCLUDE_PREFIX}/QuickMicaMaterial ${INCLUDE_PREFIX}/QuickImageItem + ${INCLUDE_PREFIX}/QuickWindowBorder ) set(PRIVATE_HEADERS @@ -59,6 +61,7 @@ set(PRIVATE_HEADERS ${INCLUDE_PREFIX}/private/framelessquickwindow_p_p.h ${INCLUDE_PREFIX}/private/quickmicamaterial_p.h ${INCLUDE_PREFIX}/private/quickimageitem_p.h + ${INCLUDE_PREFIX}/private/quickwindowborder_p.h ) set(SOURCES @@ -72,6 +75,7 @@ set(SOURCES framelesshelperquick_global.cpp quickmicamaterial.cpp quickimageitem.cpp + quickwindowborder.cpp ) if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC) diff --git a/src/quick/framelesshelperquick_global.cpp b/src/quick/framelesshelperquick_global.cpp index d220c03..6a54f7d 100644 --- a/src/quick/framelesshelperquick_global.cpp +++ b/src/quick/framelesshelperquick_global.cpp @@ -36,6 +36,8 @@ # include "quickmicamaterial_p.h" # include "quickimageitem.h" # include "quickimageitem_p.h" +# include "quickwindowborder.h" +# include "quickwindowborder_p.h" #endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) FRAMELESSHELPER_BEGIN_NAMESPACE @@ -76,6 +78,8 @@ void initialize() #endif qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) qRegisterMetaType(); @@ -99,6 +103,9 @@ void initialize() qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); #endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) } diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index 16395c3..53913c4 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -25,9 +25,9 @@ #include "framelessquickhelper.h" #include "framelessquickhelper_p.h" #include "quickmicamaterial.h" +#include "quickwindowborder.h" #include #include -#include #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) # include // For QWINDOWSIZE_MAX #else @@ -75,7 +75,7 @@ struct QuickHelper Q_GLOBAL_STATIC(QuickHelper, g_quickHelper) -[[nodiscard]] static inline QuickMicaMaterial *findMicaMaterialItem(const QQuickWindow * const window) +[[nodiscard]] static inline QuickMicaMaterial *findOrCreateMicaMaterial(const QQuickWindow * const window) { Q_ASSERT(window); if (!window) { @@ -93,6 +93,24 @@ Q_GLOBAL_STATIC(QuickHelper, g_quickHelper) return item; } +[[nodiscard]] static inline QuickWindowBorder *findOrCreateWindowBorder(const QQuickWindow * const window) +{ + Q_ASSERT(window); + if (!window) { + return nullptr; + } + QQuickItem * const rootItem = window->contentItem(); + if (const auto item = rootItem->findChild()) { + return item; + } + const auto item = new QuickWindowBorder; + item->setParent(rootItem); + item->setParentItem(rootItem); + item->setZ(999); // Make sure it always stays on the top. + QQuickItemPrivate::get(item)->anchors()->setFill(rootItem); + return item; +} + FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q) : QObject(q) { Q_ASSERT(q); @@ -517,7 +535,7 @@ void FramelessQuickHelperPrivate::setBlurBehindWindowEnabled(const bool value, c } } else { m_blurBehindWindowEnabled = value; - findMicaMaterialItem(window)->setVisible(m_blurBehindWindowEnabled); + findOrCreateMicaMaterial()->setVisible(m_blurBehindWindowEnabled); emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("blurBehindWindowEnabledChanged")); } } @@ -552,6 +570,26 @@ QVariant FramelessQuickHelperPrivate::getProperty(const QByteArray &name, const return (value.isValid() ? value : defaultValue); } +QuickMicaMaterial *FramelessQuickHelperPrivate::findOrCreateMicaMaterial() const +{ + Q_Q(const FramelessQuickHelper); + const QQuickWindow * const window = q->window(); + if (!window) { + return nullptr; + } + return FRAMELESSHELPER_PREPEND_NAMESPACE(findOrCreateMicaMaterial)(window); +} + +QuickWindowBorder *FramelessQuickHelperPrivate::findOrCreateWindowBorder() const +{ + Q_Q(const FramelessQuickHelper); + const QQuickWindow * const window = q->window(); + if (!window) { + return nullptr; + } + return FRAMELESSHELPER_PREPEND_NAMESPACE(findOrCreateWindowBorder)(window); +} + bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event) { Q_ASSERT(object); @@ -909,6 +947,18 @@ bool FramelessQuickHelper::isContentExtendedIntoTitleBar() const return d->isContentExtendedIntoTitleBar(); } +QuickMicaMaterial *FramelessQuickHelper::micaMaterial() const +{ + Q_D(const FramelessQuickHelper); + return d->findOrCreateMicaMaterial(); +} + +QuickWindowBorder *FramelessQuickHelper::windowBorder() const +{ + Q_D(const FramelessQuickHelper); + return d->findOrCreateWindowBorder(); +} + void FramelessQuickHelper::extendsContentIntoTitleBar(const bool value) { Q_D(FramelessQuickHelper); diff --git a/src/quick/framelessquickmodule.cpp b/src/quick/framelessquickmodule.cpp index df20630..aa7c175 100644 --- a/src/quick/framelessquickmodule.cpp +++ b/src/quick/framelessquickmodule.cpp @@ -28,12 +28,11 @@ #include "quickchromepalette.h" #include "quickmicamaterial.h" #include "quickimageitem.h" +#include "quickwindowborder.h" +#include "framelessquickwindow_p.h" #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) # include "quickstandardsystembutton_p.h" # include "quickstandardtitlebar_p.h" -# include "framelessquickwindow_p.h" -#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) -# include #endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #ifndef QUICK_URI_SHORT @@ -86,20 +85,19 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine) qmlRegisterRevision(QUICK_URI_FULL); qmlRegisterType(QUICK_URI_EXPAND("FramelessHelper")); + qmlRegisterType(QUICK_URI_EXPAND("FramelessWindow")); qmlRegisterType(QUICK_URI_EXPAND("MicaMaterial")); qmlRegisterType(QUICK_URI_EXPAND("ImageItem")); + qmlRegisterType(QUICK_URI_EXPAND("WindowBorder")); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) qmlRegisterType(QUICK_URI_EXPAND("StandardSystemButton")); qmlRegisterType(QUICK_URI_EXPAND("StandardTitleBar")); - qmlRegisterType(QUICK_URI_EXPAND("FramelessWindow")); #else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardSystemButton"), FRAMELESSHELPER_STRING_LITERAL("StandardSystemButton is not available until Qt6.")); qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardTitleBar"), FRAMELESSHELPER_STRING_LITERAL("StandardTitleBar is not available until Qt6.")); - qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("FramelessWindow"), - FRAMELESSHELPER_STRING_LITERAL("FramelessWindow is not available until Qt6.")); #endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) qmlRegisterModule(QUICK_URI_FULL); diff --git a/src/quick/framelessquickwindow.cpp b/src/quick/framelessquickwindow.cpp index 2785e85..594a51d 100644 --- a/src/quick/framelessquickwindow.cpp +++ b/src/quick/framelessquickwindow.cpp @@ -23,17 +23,15 @@ */ #include "framelessquickwindow_p.h" -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #include "framelessquickwindow_p_p.h" #include "framelessquickhelper.h" +#include "quickwindowborder.h" #include -#include #include -#include #include #ifdef Q_OS_WINDOWS # include -#endif // Q_OS_WINDOWS +#endif FRAMELESSHELPER_BEGIN_NAMESPACE @@ -111,21 +109,6 @@ bool FramelessQuickWindowPrivate::isFullScreen() const return (q->visibility() == FramelessQuickWindow::FullScreen); } -QColor FramelessQuickWindowPrivate::getFrameBorderColor() const -{ -#ifdef Q_OS_WINDOWS - Q_Q(const FramelessQuickWindow); - return Utils::getFrameBorderColor(q->isActive()); -#else - return {}; -#endif -} - -QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderBottom() const -{ - return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::BottomAnchor); -} - void FramelessQuickWindowPrivate::showMinimized2() { Q_Q(FramelessQuickWindow); @@ -166,22 +149,13 @@ void FramelessQuickWindowPrivate::initialize() Q_Q(FramelessQuickWindow); QQuickItem * const rootItem = q->contentItem(); FramelessQuickHelper::get(rootItem)->extendsContentIntoTitleBar(); - m_topBorderRectangle.reset(new QQuickRectangle(rootItem)); - m_topBorderRectangle->setZ(999); // Make sure the frame border stays on top of eveything. - m_topBorderRectangle->setColor(kDefaultTransparentColor); - m_topBorderRectangle->setHeight(0.0); - QQuickPen * const b = m_topBorderRectangle->border(); - b->setWidth(0.0); - b->setColor(kDefaultTransparentColor); - updateTopBorderHeight(); - updateTopBorderColor(); - m_topBorderAnchors.reset(new QQuickAnchors(m_topBorderRectangle.data(), m_topBorderRectangle.data())); - const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem); - m_topBorderAnchors->setTop(rootItemPrivate->top()); - m_topBorderAnchors->setLeft(rootItemPrivate->left()); - m_topBorderAnchors->setRight(rootItemPrivate->right()); + m_windowBorder.reset(new QuickWindowBorder); + m_windowBorder->setParent(rootItem); + m_windowBorder->setParentItem(rootItem); + m_windowBorder->setZ(999); // Make sure it always stays on the top. + QQuickItemPrivate::get(m_windowBorder.data())->anchors()->setFill(rootItem); connect(q, &FramelessQuickWindow::visibilityChanged, this, [this, q](){ - updateTopBorderHeight(); + updateWindowBorderVisibility(); Q_EMIT q->hiddenChanged(); Q_EMIT q->normalChanged(); Q_EMIT q->minimizedChanged(); @@ -189,38 +163,27 @@ void FramelessQuickWindowPrivate::initialize() Q_EMIT q->zoomedChanged(); Q_EMIT q->fullScreenChanged(); }); - connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor); - connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor); + connect(q, &FramelessQuickWindow::activeChanged, + m_windowBorder.data(), [this](){ m_windowBorder->update(); }); + updateWindowBorderVisibility(); } bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const { #ifdef Q_OS_WINDOWS - return (Utils::isWindowFrameBorderVisible() && !WindowsVersionHelper::isWin11OrGreater()); + return (Utils::isWindowFrameBorderVisible() + && !WindowsVersionHelper::isWin11OrGreater() && isNormal()); #else return false; #endif } -void FramelessQuickWindowPrivate::updateTopBorderColor() +void FramelessQuickWindowPrivate::updateWindowBorderVisibility() { -#ifdef Q_OS_WINDOWS - if (!shouldDrawFrameBorder()) { + if (m_windowBorder.isNull()) { return; } - m_topBorderRectangle->setColor(getFrameBorderColor()); -#endif -} - -void FramelessQuickWindowPrivate::updateTopBorderHeight() -{ -#ifdef Q_OS_WINDOWS - if (!shouldDrawFrameBorder()) { - return; - } - const qreal newHeight = (isNormal() ? qreal(kDefaultWindowFrameBorderThickness) : 0.0); - m_topBorderRectangle->setHeight(newHeight); -#endif + m_windowBorder->setVisible(shouldDrawFrameBorder()); } FramelessQuickWindow::FramelessQuickWindow(QWindow *parent) @@ -293,4 +256,3 @@ void FramelessQuickWindow::componentComplete() } FRAMELESSHELPER_END_NAMESPACE -#endif diff --git a/src/quick/quickimageitem.cpp b/src/quick/quickimageitem.cpp index 5218aff..b6d47cb 100644 --- a/src/quick/quickimageitem.cpp +++ b/src/quick/quickimageitem.cpp @@ -24,7 +24,6 @@ #include "quickimageitem.h" #include "quickimageitem_p.h" -#include #include #include #include diff --git a/src/quick/quickmicamaterial.cpp b/src/quick/quickmicamaterial.cpp index b6aa854..b660bf8 100644 --- a/src/quick/quickmicamaterial.cpp +++ b/src/quick/quickmicamaterial.cpp @@ -25,7 +25,6 @@ #include "quickmicamaterial.h" #include "quickmicamaterial_p.h" #include -#include #include #include #include diff --git a/src/quick/quickwindowborder.cpp b/src/quick/quickwindowborder.cpp new file mode 100644 index 0000000..6bc22a1 --- /dev/null +++ b/src/quick/quickwindowborder.cpp @@ -0,0 +1,265 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "quickwindowborder.h" +#include "quickwindowborder_p.h" +#include +#include + +FRAMELESSHELPER_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcQuickWindowBorder, "wangwenx190.framelesshelper.quick.quickwindowborder") +#define INFO qCInfo(lcQuickWindowBorder) +#define DEBUG qCDebug(lcQuickWindowBorder) +#define WARNING qCWarning(lcQuickWindowBorder) +#define CRITICAL qCCritical(lcQuickWindowBorder) + +using namespace Global; + +[[nodiscard]] static inline QuickGlobal::WindowEdges edgesToQuickEdges(const WindowEdges edges) +{ + QuickGlobal::WindowEdges result = {}; + if (edges & WindowEdge::Left) { + result |= QuickGlobal::WindowEdge::Left; + } + if (edges & WindowEdge::Top) { + result |= QuickGlobal::WindowEdge::Top; + } + if (edges & WindowEdge::Right) { + result |= QuickGlobal::WindowEdge::Right; + } + if (edges & WindowEdge::Bottom) { + result |= QuickGlobal::WindowEdge::Bottom; + } + return result; +} + +[[nodiscard]] static inline WindowEdges quickEdgesToEdges(const QuickGlobal::WindowEdges edges) +{ + WindowEdges result = {}; + if (edges & QuickGlobal::WindowEdge::Left) { + result |= WindowEdge::Left; + } + if (edges & QuickGlobal::WindowEdge::Top) { + result |= WindowEdge::Top; + } + if (edges & QuickGlobal::WindowEdge::Right) { + result |= WindowEdge::Right; + } + if (edges & QuickGlobal::WindowEdge::Bottom) { + result |= WindowEdge::Bottom; + } + return result; +} + +QuickWindowBorderPrivate::QuickWindowBorderPrivate(QuickWindowBorder *q) : QObject(q) +{ + Q_ASSERT(q); + if (!q) { + return; + } + q_ptr = q; + initialize(); +} + +QuickWindowBorderPrivate::~QuickWindowBorderPrivate() = default; + +QuickWindowBorderPrivate *QuickWindowBorderPrivate::get(QuickWindowBorder *q) +{ + Q_ASSERT(q); + if (!q) { + return nullptr; + } + return q->d_func(); +} + +const QuickWindowBorderPrivate *QuickWindowBorderPrivate::get(const QuickWindowBorder *q) +{ + Q_ASSERT(q); + if (!q) { + return nullptr; + } + return q->d_func(); +} + +void QuickWindowBorderPrivate::paint(QPainter *painter) const +{ + Q_ASSERT(painter); + if (!painter || m_borderPainter.isNull()) { + return; + } + Q_Q(const QuickWindowBorder); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) + const QSize size = q->size().toSize(); +#else + const QSize size = QSizeF(q->width(), q->height()).toSize(); +#endif + m_borderPainter->paint(painter, size, (q->window() && q->window()->isActive())); +} + +void QuickWindowBorderPrivate::initialize() +{ + Q_Q(QuickWindowBorder); + q->setClip(true); + q->setSmooth(true); + // We can't enable antialising for this element due to we are drawing + // some very thin lines that are too fragile. + q->setAntialiasing(false); + + m_borderPainter.reset(new WindowBorderPainter); + connect(m_borderPainter.data(), &WindowBorderPainter::thicknessChanged, + q, &QuickWindowBorder::thicknessChanged); + connect(m_borderPainter.data(), &WindowBorderPainter::edgesChanged, + q, &QuickWindowBorder::edgesChanged); + connect(m_borderPainter.data(), &WindowBorderPainter::activeColorChanged, + q, &QuickWindowBorder::activeColorChanged); + connect(m_borderPainter.data(), &WindowBorderPainter::inactiveColorChanged, + q, &QuickWindowBorder::inactiveColorChanged); + connect(m_borderPainter.data(), &WindowBorderPainter::nativeBorderChanged, + q, &QuickWindowBorder::nativeBorderChanged); + connect(m_borderPainter.data(), &WindowBorderPainter::shouldRepaint, q, [q](){ q->update(); }); +} + +QuickWindowBorder::QuickWindowBorder(QQuickItem *parent) + : QQuickPaintedItem(parent), d_ptr(new QuickWindowBorderPrivate(this)) +{ +} + +QuickWindowBorder::~QuickWindowBorder() = default; + +void QuickWindowBorder::paint(QPainter *painter) +{ + Q_D(QuickWindowBorder); + d->paint(painter); +} + +qreal QuickWindowBorder::thickness() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? 0 : d->m_borderPainter->thickness()); +} + +QuickGlobal::WindowEdges QuickWindowBorder::edges() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? QuickGlobal::WindowEdges() + : edgesToQuickEdges(d->m_borderPainter->edges())); +} + +QColor QuickWindowBorder::activeColor() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? QColor() : d->m_borderPainter->activeColor()); +} + +QColor QuickWindowBorder::inactiveColor() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? QColor() : d->m_borderPainter->inactiveColor()); +} + +qreal QuickWindowBorder::nativeThickness() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? 0 : d->m_borderPainter->nativeThickness()); +} + +QuickGlobal::WindowEdges QuickWindowBorder::nativeEdges() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? QuickGlobal::WindowEdges() + : edgesToQuickEdges(d->m_borderPainter->nativeEdges())); +} + +QColor QuickWindowBorder::nativeActiveColor() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? QColor() : d->m_borderPainter->nativeActiveColor()); +} + +QColor QuickWindowBorder::nativeInactiveColor() const +{ + Q_D(const QuickWindowBorder); + return (d->m_borderPainter.isNull() ? QColor() : d->m_borderPainter->nativeInactiveColor()); +} + +void QuickWindowBorder::setThickness(const qreal value) +{ + Q_D(QuickWindowBorder); + if (d->m_borderPainter.isNull()) { + return; + } + if (qFuzzyCompare(thickness(), value)) { + return; + } + d->m_borderPainter->setThickness(qRound(value)); +} + +void QuickWindowBorder::setEdges(const QuickGlobal::WindowEdges value) +{ + Q_D(QuickWindowBorder); + if (d->m_borderPainter.isNull()) { + return; + } + if (edges() == value) { + return; + } + d->m_borderPainter->setEdges(quickEdgesToEdges(value)); +} + +void QuickWindowBorder::setActiveColor(const QColor &value) +{ + Q_D(QuickWindowBorder); + if (d->m_borderPainter.isNull()) { + return; + } + if (activeColor() == value) { + return; + } + d->m_borderPainter->setActiveColor(value); +} + +void QuickWindowBorder::setInactiveColor(const QColor &value) +{ + Q_D(QuickWindowBorder); + if (d->m_borderPainter.isNull()) { + return; + } + if (inactiveColor() == value) { + return; + } + d->m_borderPainter->setInactiveColor(value); +} + +void QuickWindowBorder::classBegin() +{ + QQuickPaintedItem::classBegin(); +} + +void QuickWindowBorder::componentComplete() +{ + QQuickPaintedItem::componentComplete(); +} + +FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/quickwindowborder.h b/src/quick/quickwindowborder.h new file mode 100644 index 0000000..2bdda89 --- /dev/null +++ b/src/quick/quickwindowborder.h @@ -0,0 +1 @@ +#include "../../include/FramelessHelper/Quick/quickwindowborder.h" diff --git a/src/quick/quickwindowborder_p.h b/src/quick/quickwindowborder_p.h new file mode 100644 index 0000000..fe33993 --- /dev/null +++ b/src/quick/quickwindowborder_p.h @@ -0,0 +1 @@ +#include "../../include/FramelessHelper/Quick/private/quickwindowborder_p.h" diff --git a/src/widgets/framelesswidgetshelper.cpp b/src/widgets/framelesswidgetshelper.cpp index 78b8694..cdb1890 100644 --- a/src/widgets/framelesswidgetshelper.cpp +++ b/src/widgets/framelesswidgetshelper.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -268,6 +267,28 @@ QWidget *FramelessWidgetsHelperPrivate::window() const return m_window; } +MicaMaterial *FramelessWidgetsHelperPrivate::getMicaMaterialIfAny() const +{ + if (!m_window) { + return nullptr; + } + if (const WidgetsSharedHelper * const helper = findWidgetsSharedHelper(m_window)) { + return helper->rawMicaMaterial(); + } + return nullptr; +} + +WindowBorderPainter *FramelessWidgetsHelperPrivate::getWindowBorderIfAny() const +{ + if (!m_window) { + return nullptr; + } + if (const WidgetsSharedHelper * const helper = findWidgetsSharedHelper(m_window)) { + return helper->rawWindowBorder(); + } + return nullptr; +} + bool FramelessWidgetsHelperPrivate::isContentExtendedIntoTitleBar() const { return getWindowData().ready; @@ -859,6 +880,18 @@ bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const return d->isContentExtendedIntoTitleBar(); } +MicaMaterial *FramelessWidgetsHelper::micaMaterial() const +{ + Q_D(const FramelessWidgetsHelper); + return d->getMicaMaterialIfAny(); +} + +WindowBorderPainter *FramelessWidgetsHelper::windowBorder() const +{ + Q_D(const FramelessWidgetsHelper); + return d->getWindowBorderIfAny(); +} + void FramelessWidgetsHelper::extendsContentIntoTitleBar(const bool value) { Q_D(FramelessWidgetsHelper); diff --git a/src/widgets/widgetssharedhelper.cpp b/src/widgets/widgetssharedhelper.cpp index 5ae49ea..5994226 100644 --- a/src/widgets/widgetssharedhelper.cpp +++ b/src/widgets/widgetssharedhelper.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef Q_OS_WINDOWS # include #endif // Q_OS_WINDOWS @@ -58,10 +59,21 @@ void WidgetsSharedHelper::setup(QWidget *widget) if (!widget) { return; } - if (m_targetWidget == widget) { + if (m_targetWidget && (m_targetWidget == widget)) { return; } m_targetWidget = widget; + m_borderPainter.reset(new WindowBorderPainter); + if (m_borderRepaintConnection) { + disconnect(m_borderRepaintConnection); + m_borderRepaintConnection = {}; + } + m_borderRepaintConnection = connect(m_borderPainter.data(), + &WindowBorderPainter::shouldRepaint, this, [this](){ + if (m_targetWidget) { + m_targetWidget->update(); + } + }); m_micaMaterial = MicaMaterial::attach(m_targetWidget); if (m_micaRedrawConnection) { disconnect(m_micaRedrawConnection); @@ -82,7 +94,12 @@ void WidgetsSharedHelper::setup(QWidget *widget) QScreen *screen = m_targetWidget->windowHandle()->screen(); #endif handleScreenChanged(screen); - connect(m_targetWidget->windowHandle(), &QWindow::screenChanged, this, &WidgetsSharedHelper::handleScreenChanged); + if (m_screenChangeConnection) { + disconnect(m_screenChangeConnection); + m_screenChangeConnection = {}; + } + m_screenChangeConnection = connect(m_targetWidget->windowHandle(), + &QWindow::screenChanged, this, &WidgetsSharedHelper::handleScreenChanged); } bool WidgetsSharedHelper::isMicaEnabled() const @@ -102,6 +119,16 @@ void WidgetsSharedHelper::setMicaEnabled(const bool value) Q_EMIT micaEnabledChanged(); } +MicaMaterial *WidgetsSharedHelper::rawMicaMaterial() const +{ + return (m_micaMaterial.isNull() ? nullptr : m_micaMaterial.data()); +} + +WindowBorderPainter *WidgetsSharedHelper::rawWindowBorder() const +{ + return (m_borderPainter.isNull() ? nullptr : m_borderPainter.data()); +} + bool WidgetsSharedHelper::eventFilter(QObject *object, QEvent *event) { Q_ASSERT(object); @@ -190,26 +217,10 @@ void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event) m_micaMaterial->paint(&painter, m_targetWidget->size(), m_targetWidget->mapToGlobal(QPoint(0, 0))); } -#ifdef Q_OS_WINDOWS - if (shouldDrawFrameBorder()) { + if (shouldDrawFrameBorder() && !m_borderPainter.isNull()) { QPainter painter(m_targetWidget); - painter.save(); - painter.setRenderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - // We can't enable antialiasing here, because the border is only 1px height, - // it's too thin and antialiasing will break it's painting. - painter.setRenderHint(QPainter::Antialiasing, false); - QPen pen = {}; - pen.setColor(Utils::getFrameBorderColor(m_targetWidget->isActiveWindow())); - pen.setWidth(kDefaultWindowFrameBorderThickness); - painter.setPen(pen); - // In fact, we should use "m_targetWidget->width() - 1" here but we can't - // because Qt's drawing system has some rounding errors internally and if - // we minus one here we'll get a one pixel gap, so sad. But drawing a line - // with a little extra pixels won't hurt anyway. - painter.drawLine(0, 0, m_targetWidget->width(), 0); - painter.restore(); + m_borderPainter->paint(&painter, m_targetWidget->size(), m_targetWidget->isActiveWindow()); } -#endif // Don't eat this event here, we need Qt to keep dispatching this paint event // otherwise the widget won't paint anything else from the user side. }