From 81e736570f80f29fe22cac917367cded7de09355 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Tue, 3 May 2022 19:02:39 +0800 Subject: [PATCH] refactor widgets interface Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- README.md | 21 +- examples/mainwindow/CMakeLists.txt | 5 +- examples/mainwindow/TitleBar.ui | 276 ------ examples/mainwindow/mainwindow.cpp | 82 +- examples/mainwindow/mainwindow.h | 19 +- examples/openglwidget/CMakeLists.txt | 2 - examples/openglwidget/mainwindow.cpp | 58 +- examples/openglwidget/mainwindow.h | 22 +- examples/widget/widget.cpp | 45 +- examples/widget/widget.h | 7 +- .../FramelessHelper/Core/framelesshelper_qt.h | 2 +- .../Core/framelesshelper_win.h | 2 +- .../Core/framelesshelpercore_global.h | 51 +- .../Core/framelesswindowsmanager.h | 2 +- include/FramelessHelper/Core/utils.h | 4 - .../Quick/framelesshelperquick_global.h | 32 - .../Quick/framelessquickhelper.h | 4 +- .../Quick/framelessquickwindow.h | 5 +- .../Widgets/FramelessWidgetsHelper | 1 + .../FramelessHelper/Widgets/StandardTitleBar | 1 + .../Widgets/framelessmainwindow.h | 25 +- .../FramelessHelper/Widgets/framelesswidget.h | 30 +- .../Widgets/framelesswidgetshelper.h | 72 ++ .../Widgets/standardtitlebar.h | 44 +- src/core/CMakeLists.txt | 2 - src/core/framelesshelper_qt.cpp | 13 +- src/core/framelesshelper_win.cpp | 60 +- src/core/framelesswindowsmanager.cpp | 74 +- src/core/framelesswindowsmanager_p.h | 5 +- src/core/qwinregistry.cpp | 119 --- src/core/qwinregistry_p.h | 95 -- src/core/utils_win.cpp | 69 +- src/quick/framelessquickhelper.cpp | 109 ++- src/quick/framelessquickhelper_p.h | 5 +- src/quick/framelessquickmodule.cpp | 1 - src/quick/framelessquickwindow.cpp | 27 +- src/quick/framelessquickwindow_p.h | 4 +- src/widgets/CMakeLists.txt | 6 + src/widgets/framelessmainwindow.cpp | 82 +- src/widgets/framelesswidget.cpp | 92 +- src/widgets/framelesswidgetshelper.cpp | 862 ++++++++---------- .../widgets/framelesswidgetshelper.h | 17 +- src/widgets/framelesswidgetshelper_p.h | 89 +- src/widgets/standardsystembutton.cpp | 2 +- src/widgets/standardsystembutton_p.h | 2 +- src/widgets/standardtitlebar.cpp | 235 +++++ .../widgets/standardtitlebar.h | 17 +- src/widgets/standardtitlebar_p.h | 72 ++ src/widgets/widgetssharedhelper.cpp | 144 +++ .../widgets/widgetssharedhelper_p.h | 48 +- 50 files changed, 1281 insertions(+), 1782 deletions(-) delete mode 100644 examples/mainwindow/TitleBar.ui create mode 100644 include/FramelessHelper/Widgets/FramelessWidgetsHelper create mode 100644 include/FramelessHelper/Widgets/StandardTitleBar create mode 100644 include/FramelessHelper/Widgets/framelesswidgetshelper.h rename examples/openglwidget/systembutton.cpp => include/FramelessHelper/Widgets/standardtitlebar.h (52%) delete mode 100644 src/core/qwinregistry.cpp delete mode 100644 src/core/qwinregistry_p.h rename examples/openglwidget/systembutton.h => src/widgets/framelesswidgetshelper.h (79%) create mode 100644 src/widgets/standardtitlebar.cpp rename examples/mainwindow/systembutton.h => src/widgets/standardtitlebar.h (79%) create mode 100644 src/widgets/standardtitlebar_p.h create mode 100644 src/widgets/widgetssharedhelper.cpp rename examples/mainwindow/systembutton.cpp => src/widgets/widgetssharedhelper_p.h (57%) diff --git a/README.md b/README.md index 34343ce..83261d0 100644 --- a/README.md +++ b/README.md @@ -44,19 +44,6 @@ ![Dark](./doc/mac_dark.png) -## Roadmap - -- 2.1 - - [ ] All: Add cross-platform system menu for both Qt Widgets and Qt Quick. Support both light and dark theme. Can be triggered by right-clicking on the title bar area or pressing the system menu shortcut (ALT + SPACE). - - [ ] All: Add QtWebEngine demo applications for both Qt Widgets and Qt Quick. - - [ ] All: Make more settings and options configurable through environment variables and configuration files. - - [ ] Windows: Snap layout feature introduced in Windows 11. -- Future versions - - [ ] Linux: Support runtime theme switching. - - [ ] Linux: Move window resize area outside of the client area. - - [ ] macOS: Move window resize area outside of the client area. - - [ ] More feature requests are welcome! - ## Requiredments - Compiler: a modern compiler which supports C++17 at least. @@ -74,7 +61,7 @@ cmake -DCMAKE_PREFIX_PATH= -DCMAKE_BUILD_TYPE=Release -GNi cmake --build . --config Release --target all --parallel ``` -**Note**: On Linux you need to install the GTK3 and X11 development packages first. +**Note**: On Linux you need to install the _GTK3_ and _X11_ development packages first. ## Use @@ -97,6 +84,12 @@ Please refer to the demo applications to see more detailed usages: [examples](./ - Force your application use pure software rendering instead of rendering through OpenGL. - Or just don't use OpenGL at all, try to use Direct3D/Vulkan/Metal instead. - Due to there are many sub-versions of Windows 10, it's highly recommended to use the latest version of Windows 10, at least no older than Windows 10 1809. If you try to use this framework on some very old Windows 10 versions such as 1507 or 1607, there may be some compatibility issues. Using this framework on Windows 7 is also supported but not recommended. To get the most stable behavior and the best appearance, you should use it on the latest version of Windows 10 or Windows 11. +- To make the snap layout work as expected, there are some additional requirements for your homemade system buttons to follow: + - Make sure there are two public invokable functions (slot functions are always invokable): `void setHovered(bool)` and `void setPressed(bool)`. These two functions will be invoked by FramelessHelper when the button is being hovered or pressed. You should change the button's visual state inside these functions. + - Make sure there's a public signal: `void clicked()`. When the button is being clicked, that signal will be triggered by FramelessHelper. You should connect your event handler to that signal. + - Don't forget to call `setSystemButton()` for each button to let FramelessHelper know which is the minimize/maximize/close button. + - System buttons will not be able to receive any actual mouse events so there's no need to handle any mouse events inside these buttons. That's also why we need to set the button's visual state manually. + - I know this is making everything complicated but unfortunately we can't avoid this mess if we need to support the snap layout feature. Snap layout is really only designed for the original standard window frame, so if we want to forcely support it without a standard window frame, many black magic will be needed. ### Linux diff --git a/examples/mainwindow/CMakeLists.txt b/examples/mainwindow/CMakeLists.txt index c7519e7..d081feb 100644 --- a/examples/mainwindow/CMakeLists.txt +++ b/examples/mainwindow/CMakeLists.txt @@ -23,13 +23,10 @@ ]] set(SOURCES - TitleBar.ui - MainWindow.ui + mainwindow.ui mainwindow.h mainwindow.cpp main.cpp - systembutton.h - systembutton.cpp ) if(WIN32) diff --git a/examples/mainwindow/TitleBar.ui b/examples/mainwindow/TitleBar.ui deleted file mode 100644 index 886ec9b..0000000 --- a/examples/mainwindow/TitleBar.ui +++ /dev/null @@ -1,276 +0,0 @@ - - - TitleBar - - - - 0 - 0 - 552 - 30 - - - - - 0 - 0 - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - QMenuBar { - background-color: transparent; - height: 23px; -} - -#iconButton, #minimizeButton, #maximizeButton, #closeButton { - border-style: none; - background-color: transparent; -} - -#minimizeButton:hover, #maximizeButton:hover { - background-color: #c7c7c7; -} - -#minimizeButton:pressed, #maximizeButton:pressed { - background-color: #808080; -} - -#closeButton:hover { - background-color: #e81123; -} - -#closeButton:pressed { - background-color: #8c0a15; -} - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 30 - 30 - - - - - 30 - 30 - - - - Qt::NoFocus - - - - 24 - 24 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - Segoe UI - 9 - - - - Hello, World! - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 45 - 30 - - - - - 45 - 30 - - - - Qt::NoFocus - - - Qt::NoContextMenu - - - Minimize - - - - 16 - 16 - - - - - - - - - 0 - 0 - - - - - 45 - 30 - - - - - 45 - 30 - - - - Qt::NoFocus - - - Qt::NoContextMenu - - - Maximize - - - - 16 - 16 - - - - - - - - - 0 - 0 - - - - - 45 - 30 - - - - - 45 - 30 - - - - Qt::NoFocus - - - Qt::NoContextMenu - - - Close - - - - 16 - 16 - - - - - - - - - - SystemButton - QPushButton -
systembutton.h
-
-
- - -
diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp index 8ef4041..98e3882 100644 --- a/examples/mainwindow/mainwindow.cpp +++ b/examples/mainwindow/mainwindow.cpp @@ -23,9 +23,12 @@ */ #include "mainwindow.h" -#include "ui_MainWindow.h" -#include "ui_TitleBar.h" +#include "ui_mainwindow.h" +#include #include +#include +#include +#include FRAMELESSHELPER_USE_NAMESPACE @@ -33,62 +36,31 @@ using namespace Global; MainWindow::MainWindow(QWidget *parent, const Qt::WindowFlags flags) : FramelessMainWindow(parent, flags) { - setupUi(); + initialize(); } MainWindow::~MainWindow() = default; -void MainWindow::changeEvent(QEvent *event) +void MainWindow::initialize() { - FramelessMainWindow::changeEvent(event); - if (event->type() == QEvent::WindowStateChange) { - Q_EMIT windowStateChanged(); - } -} - -void MainWindow::setupUi() -{ - mainWindow.reset(new Ui::MainWindow); - mainWindow->setupUi(this); - - const auto titleBarWidget = new QWidget(this); - titleBar.reset(new Ui::TitleBar); - titleBar->setupUi(titleBarWidget); - - const SystemTheme theme = SystemTheme::Light; - const ResourceType resource = ResourceType::Icon; - titleBar->minimizeButton->setIcon(qvariant_cast(Utils::getSystemButtonIconResource(SystemButtonType::Minimize, theme, resource))); - titleBar->maximizeButton->setIcon(qvariant_cast(Utils::getSystemButtonIconResource(SystemButtonType::Maximize, theme, resource))); - titleBar->closeButton->setIcon(qvariant_cast(Utils::getSystemButtonIconResource(SystemButtonType::Close, theme, resource))); - - QMenuBar *mb = menuBar(); - titleBar->horizontalLayout->insertWidget(1, mb); - - // This call to the setMenuWidget() function is only needed by this example - // application to achieve some special effects, don't use it in your own - // code if you don't know what's it for! - setMenuWidget(titleBarWidget); - - setTitleBarWidget(titleBarWidget); - - setHitTestVisible(mb); // IMPORTANT! - setSystemButton(titleBar->minimizeButton, SystemButtonType::Minimize); - setSystemButton(titleBar->maximizeButton, SystemButtonType::Maximize); - setSystemButton(titleBar->closeButton, SystemButtonType::Close); - - connect(titleBar->minimizeButton, &QPushButton::clicked, this, &MainWindow::showMinimized); - connect(titleBar->maximizeButton, &QPushButton::clicked, this, &MainWindow::toggleMaximized); - connect(titleBar->closeButton, &QPushButton::clicked, this, &MainWindow::close); - connect(this, &MainWindow::windowIconChanged, titleBar->iconButton, &QPushButton::setIcon); - connect(this, &MainWindow::windowTitleChanged, titleBar->titleLabel, &QLabel::setText); - connect(this, &MainWindow::windowStateChanged, this, [this](){ - const bool zoomed = isZoomed(); - const SystemTheme theme = SystemTheme::Light; - const SystemButtonType button = (zoomed ? SystemButtonType::Restore : SystemButtonType::Maximize); - const ResourceType resource = ResourceType::Icon; - titleBar->maximizeButton->setIcon(qvariant_cast(Utils::getSystemButtonIconResource(button, theme, resource))); - titleBar->maximizeButton->setToolTip(zoomed ? tr("Restore") : tr("Maximize")); - }); - - setWindowTitle(tr("Hello, World! - Qt MainWindow")); + m_titleBar.reset(new StandardTitleBar(this)); + m_mainWindow.reset(new Ui::MainWindow); + m_mainWindow->setupUi(this); + + QMenuBar * const mb = menuBar(); + const auto titleBarLayout = static_cast(m_titleBar->layout()); + titleBarLayout->insertWidget(0, mb); + + // "setMenuWidget()" will insert the menu widget on the window's top, just below + // system's title bar (if it's still there). + setMenuWidget(m_titleBar.data()); + + FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); + helper->setTitleBarWidget(m_titleBar.data()); + helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize); + helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize); + helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close); + helper->setHitTestVisible(mb); // IMPORTANT! + + setWindowTitle(tr("FramelessHelper demo application - Qt MainWindow")); } diff --git a/examples/mainwindow/mainwindow.h b/examples/mainwindow/mainwindow.h index 1aba778..22e377a 100644 --- a/examples/mainwindow/mainwindow.h +++ b/examples/mainwindow/mainwindow.h @@ -26,9 +26,12 @@ #include +FRAMELESSHELPER_BEGIN_NAMESPACE +class StandardTitleBar; +FRAMELESSHELPER_END_NAMESPACE + namespace Ui { -class TitleBar; class MainWindow; } @@ -41,16 +44,10 @@ public: explicit MainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {}); ~MainWindow() override; -protected: - void changeEvent(QEvent *event) override; +private: + void initialize(); private: - void setupUi(); - -Q_SIGNALS: - void windowStateChanged(); - -private: - QScopedPointer titleBar; - QScopedPointer mainWindow; + QScopedPointer m_titleBar; + QScopedPointer m_mainWindow; }; diff --git a/examples/openglwidget/CMakeLists.txt b/examples/openglwidget/CMakeLists.txt index 84014a4..e917d23 100644 --- a/examples/openglwidget/CMakeLists.txt +++ b/examples/openglwidget/CMakeLists.txt @@ -39,8 +39,6 @@ set(SOURCES mainwindow.h mainwindow.cpp main.cpp - systembutton.h - systembutton.cpp ) if(WIN32) diff --git a/examples/openglwidget/mainwindow.cpp b/examples/openglwidget/mainwindow.cpp index 8e488e3..907621d 100644 --- a/examples/openglwidget/mainwindow.cpp +++ b/examples/openglwidget/mainwindow.cpp @@ -24,9 +24,10 @@ #include "mainwindow.h" #include "glwidget.h" -#include "systembutton.h" #include -#include +#include +#include +#include FRAMELESSHELPER_USE_NAMESPACE @@ -34,58 +35,27 @@ using namespace Global; MainWindow::MainWindow(QWidget *parent) : FramelessWidget(parent) { - setupUi(); + initialize(); } MainWindow::~MainWindow() = default; -void MainWindow::updateMaximizeButton() +void MainWindow::initialize() { - m_maxBtn->setText(isZoomed() ? tr("RESTORE") : tr("MAXIMIZE")); -} - -void MainWindow::setupUi() -{ - m_titleLabel = new QLabel(this); - QFont f = font(); - f.setPointSize(kDefaultTitleBarFontPointSize); - m_titleLabel->setFont(f); - connect(this, &MainWindow::windowTitleChanged, m_titleLabel, &QLabel::setText); - m_minBtn = new SystemButton(this); - m_minBtn->setText(tr("MINIMIZE")); - connect(m_minBtn, &SystemButton::clicked, this, &MainWindow::showMinimized); - m_maxBtn = new SystemButton(this); - updateMaximizeButton(); - connect(m_maxBtn, &SystemButton::clicked, this, &MainWindow::toggleMaximized); - connect(this, &MainWindow::zoomedChanged, this, &MainWindow::updateMaximizeButton); - m_closeBtn = new SystemButton(this); - m_closeBtn->setText(tr("CLOSE")); - connect(m_closeBtn, &SystemButton::clicked, this, &MainWindow::close); - m_titleBarWidget = new QWidget(this); - m_titleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_titleBarWidget->setFixedHeight(kDefaultTitleBarHeight); - const auto titleBarLayout = new QHBoxLayout(m_titleBarWidget); - titleBarLayout->setSpacing(0); - titleBarLayout->setContentsMargins(0, 0, 0, 0); - titleBarLayout->addSpacerItem(new QSpacerItem(kDefaultTitleBarTitleLabelMargin, kDefaultTitleBarTitleLabelMargin)); - titleBarLayout->addWidget(m_titleLabel); - titleBarLayout->addStretch(); - titleBarLayout->addWidget(m_minBtn); - titleBarLayout->addWidget(m_maxBtn); - titleBarLayout->addWidget(m_closeBtn); - m_titleBarWidget->setLayout(titleBarLayout); + resize(800, 600); + setWindowTitle(tr("FramelessHelper demo application - QOpenGLWidget")); + m_titleBar = new StandardTitleBar(this); m_glWidget = new GLWidget(this); const auto mainLayout = new QVBoxLayout(this); mainLayout->setSpacing(0); mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addWidget(m_titleBarWidget); + mainLayout->addWidget(m_titleBar); mainLayout->addWidget(m_glWidget); setLayout(mainLayout); - setTitleBarWidget(m_titleBarWidget); - resize(800, 600); - setWindowTitle(tr("QOpenGLWidget demo")); - setSystemButton(m_minBtn, SystemButtonType::Minimize); - setSystemButton(m_maxBtn, SystemButtonType::Maximize); - setSystemButton(m_closeBtn, SystemButtonType::Close); + FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); + helper->setTitleBarWidget(m_titleBar); + helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize); + helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize); + helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close); } diff --git a/examples/openglwidget/mainwindow.h b/examples/openglwidget/mainwindow.h index 17f8cf4..cdbabe6 100644 --- a/examples/openglwidget/mainwindow.h +++ b/examples/openglwidget/mainwindow.h @@ -24,14 +24,13 @@ #pragma once -#include +#include -QT_BEGIN_NAMESPACE -class QLabel; -QT_END_NAMESPACE +FRAMELESSHELPER_BEGIN_NAMESPACE +class StandardTitleBar; +FRAMELESSHELPER_END_NAMESPACE class GLWidget; -class SystemButton; class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget) { @@ -42,17 +41,10 @@ public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow() override; -public Q_SLOTS: - void updateMaximizeButton(); +private: + void initialize(); private: - void setupUi(); - -private: - QLabel *m_titleLabel = nullptr; - SystemButton *m_minBtn = nullptr; - SystemButton *m_maxBtn = nullptr; - SystemButton *m_closeBtn = nullptr; - QWidget *m_titleBarWidget = nullptr; + FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *m_titleBar = nullptr; GLWidget *m_glWidget = nullptr; }; diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp index 4e6d344..b7e7515 100644 --- a/examples/widget/widget.cpp +++ b/examples/widget/widget.cpp @@ -26,29 +26,21 @@ #include #include #include +#include #include +#include +#include +#include FRAMELESSHELPER_USE_NAMESPACE using namespace Global; -static const UserSettings settings = +Widget::Widget(QWidget *parent) : FramelessWidget(parent) { - /* startupPosition */ QPoint(), - /* startupSize */ QSize(), - /* startupState */ Qt::WindowNoState, - /* options */ { Option::CreateStandardWindowLayout }, // Only needed by this demo application, you most probably don't need this option. - /* systemMenuOffset */ QPoint(), - /* minimizeButton */ nullptr, - /* maximizeButton */ nullptr, - /* closeButton */ nullptr -}; - -Widget::Widget(QWidget *parent) : FramelessWidget(parent, settings) -{ - setupUi(); + initialize(); startTimer(500); - connect(this, &Widget::systemThemeChanged, this, &Widget::updateStyleSheet); + connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &Widget::updateStyleSheet); } Widget::~Widget() = default; @@ -62,27 +54,36 @@ void Widget::timerEvent(QTimerEvent *event) m_clockLabel->setText(QTime::currentTime().toString(FRAMELESSHELPER_STRING_LITERAL("hh:mm:ss"))); } -void Widget::setupUi() +void Widget::initialize() { - setWindowTitle(tr("Hello, World! - Qt Widgets")); + setWindowTitle(tr("FramelessHelper demo application - Qt Widgets")); resize(800, 600); + m_titleBar.reset(new StandardTitleBar(this)); m_clockLabel.reset(new QLabel(this)); m_clockLabel->setFrameShape(QFrame::NoFrame); QFont clockFont = font(); clockFont.setBold(true); clockFont.setPointSize(70); m_clockLabel->setFont(clockFont); - const auto widget = new QWidget(this); - widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - const auto contentLayout = new QHBoxLayout(widget); + const auto contentLayout = new QHBoxLayout; contentLayout->setContentsMargins(0, 0, 0, 0); contentLayout->setSpacing(0); contentLayout->addStretch(); contentLayout->addWidget(m_clockLabel.data()); contentLayout->addStretch(); - widget->setLayout(contentLayout); - setContentWidget(widget); + const auto mainLayout = new QVBoxLayout(this); + mainLayout->setSpacing(0); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addWidget(m_titleBar.data()); + mainLayout->addLayout(contentLayout); + setLayout(mainLayout); updateStyleSheet(); + + FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); + helper->setTitleBarWidget(m_titleBar.data()); + helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize); + helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize); + helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close); } void Widget::updateStyleSheet() diff --git a/examples/widget/widget.h b/examples/widget/widget.h index 0a2ca0a..4002a7e 100644 --- a/examples/widget/widget.h +++ b/examples/widget/widget.h @@ -30,6 +30,10 @@ QT_BEGIN_NAMESPACE class QLabel; QT_END_NAMESPACE +FRAMELESSHELPER_BEGIN_NAMESPACE +class StandardTitleBar; +FRAMELESSHELPER_END_NAMESPACE + class Widget : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget) { Q_OBJECT @@ -43,11 +47,12 @@ protected: void timerEvent(QTimerEvent *event) override; private: - void setupUi(); + void initialize(); private Q_SLOTS: void updateStyleSheet(); private: QScopedPointer m_clockLabel; + QScopedPointer m_titleBar; }; diff --git a/include/FramelessHelper/Core/framelesshelper_qt.h b/include/FramelessHelper/Core/framelesshelper_qt.h index fbff00e..e892bf5 100644 --- a/include/FramelessHelper/Core/framelesshelper_qt.h +++ b/include/FramelessHelper/Core/framelesshelper_qt.h @@ -38,7 +38,7 @@ public: explicit FramelessHelperQt(QObject *parent = nullptr); ~FramelessHelperQt() override; - static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms); + static void addWindow(const Global::SystemParameters ¶ms); protected: Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; diff --git a/include/FramelessHelper/Core/framelesshelper_win.h b/include/FramelessHelper/Core/framelesshelper_win.h index 3b938fe..75afe71 100644 --- a/include/FramelessHelper/Core/framelesshelper_win.h +++ b/include/FramelessHelper/Core/framelesshelper_win.h @@ -37,7 +37,7 @@ public: explicit FramelessHelperWin(); ~FramelessHelperWin() override; - static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms); + static void addWindow(const Global::SystemParameters ¶ms); Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override; }; diff --git a/include/FramelessHelper/Core/framelesshelpercore_global.h b/include/FramelessHelper/Core/framelesshelpercore_global.h index 2040dbd..39d0f8e 100644 --- a/include/FramelessHelper/Core/framelesshelpercore_global.h +++ b/include/FramelessHelper/Core/framelesshelpercore_global.h @@ -25,10 +25,9 @@ #pragma once #include -#include #include #include -#include +#include #include #include #include @@ -192,37 +191,6 @@ FRAMELESSHELPER_STRING_CONSTANT2(UsePureQtImplKeyPath, "Options/UsePureQtImpleme FRAMELESSHELPER_STRING_CONSTANT2(ForceHideFrameBorderKeyPath, "Options/ForceHideFrameBorder") FRAMELESSHELPER_STRING_CONSTANT2(ForceShowFrameBorderKeyPath, "Options/ForceShowFrameBorder") -enum class Option -{ - ForceHideWindowFrameBorder = 0x00000001, // Windows only, force hide the window frame border even on Windows 10 and onwards. - ForceShowWindowFrameBorder = 0x00000002, // Windows only, force show the window frame border even on Windows 7 (~ 8.1). - DontDrawTopWindowFrameBorder = 0x00000004, // Windows only, don't draw the top window frame border even if the window frame border is visible. - DontForceSquareWindowCorners = 0x00000008, // Windows only, don't force the window corners to be square if the default corner style is not square. - TransparentWindowBackground = 0x00000010, // Make the window's background become transparent. - DisableWindowsSnapLayout = 0x00000020, // Windows only, don't enable the snap layout feature (available since Windows 11) unconditionally. - CreateStandardWindowLayout = 0x00000040, // Using this option will cause FramelessHelper create a homemade titlebar and a window layout to contain it. If your window has a layout already, the newly created layout will mess up your own layout. - BeCompatibleWithQtFramelessWindowHint = 0x00000080, // Windows only, make the code compatible with Qt::FramelessWindowHint. Don't use this option unless you really need that flag. - DontTouchQtInternals = 0x00000100, // Windows only, don't modify Qt's internal data. - DontTouchWindowFrameBorderColor = 0x00000200, // Windows only, don't change the window frame border color. - DontInstallSystemMenuHook = 0x00000400, // Windows only, don't install the system menu hook. - DisableSystemMenu = 0x00000800, // Windows only, don't open the system menu when right clicks the titlebar. - NoDoubleClickMaximizeToggle = 0x00001000, // Don't toggle the maximized state when user double clicks the titlebar. - DisableResizing = 0x00002000, // Disable resizing of the window. - DisableDragging = 0x00004000, // Disable dragging through the titlebar of the window. - DontTouchCursorShape = 0x00008000, // Don't change the cursor shape while the mouse is hovering above the window. - DontMoveWindowToDesktopCenter = 0x00010000, // Don't move the window to the desktop center before it's first shown. - DontTreatFullScreenAsZoomed = 0x00020000, // Don't treat fullscreen as zoomed (maximized). - DontTouchHighDpiScalingPolicy = 0x00040000, // Don't change Qt's default high DPI scaling policy. Qt5 default: disabled, Qt6 default: enabled. - DontTouchScaleFactorRoundingPolicy = 0x00080000, // Don't change Qt's default scale factor rounding policy. Qt5 default: round, Qt6 default: pass through. - DontTouchProcessDpiAwarenessLevel = 0x00100000, // Windows only, don't change the current process's DPI awareness level. - DontEnsureNonNativeWidgetSiblings = 0x00200000, // Don't ensure that siblings of native widgets stay non-native. - SyncNativeControlsThemeWithSystem = 0x00400000 // Windows only, sync the native Win32 controls' theme with system theme. -}; -Q_ENUM_NS(Option) -Q_DECLARE_FLAGS(Options, Option) -Q_FLAG_NS(Options) -Q_DECLARE_OPERATORS_FOR_FLAGS(Options) - enum class SystemTheme { Unknown = -1, @@ -409,20 +377,6 @@ using ShouldIgnoreMouseEventsCallback = std::function; using ShowSystemMenuCallback = std::function; -struct UserSettings -{ - QPoint startupPosition = {}; - QSize startupSize = {}; - Qt::WindowState startupState = Qt::WindowNoState; - Options options = {}; - QPoint systemMenuOffset = {}; - QPointer windowIconButton = nullptr; - QPointer contextHelpButton = nullptr; - QPointer minimizeButton = nullptr; - QPointer maximizeButton = nullptr; - QPointer closeButton = nullptr; -}; - struct SystemParameters { GetWindowFlagsCallback getWindowFlags = nullptr; @@ -528,11 +482,10 @@ static_assert((sizeof(WindowsVersions) / sizeof(WindowsVersions[0])) == (static_ namespace FramelessHelper::Core { -FRAMELESSHELPER_CORE_API void initialize(const Global::Options options = {}); +FRAMELESSHELPER_CORE_API void initialize(); } // namespace FramelessHelper::Core FRAMELESSHELPER_END_NAMESPACE Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber) -Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::UserSettings) Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::SystemParameters) diff --git a/include/FramelessHelper/Core/framelesswindowsmanager.h b/include/FramelessHelper/Core/framelesswindowsmanager.h index eb9e22a..bca11e8 100644 --- a/include/FramelessHelper/Core/framelesswindowsmanager.h +++ b/include/FramelessHelper/Core/framelesswindowsmanager.h @@ -51,7 +51,7 @@ public: Q_NODISCARD QColor systemAccentColor() const; public Q_SLOTS: - void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms); + void addWindow(const Global::SystemParameters ¶ms); Q_SIGNALS: void systemThemeChanged(); diff --git a/include/FramelessHelper/Core/utils.h b/include/FramelessHelper/Core/utils.h index ac9fed0..0f40c2d 100644 --- a/include/FramelessHelper/Core/utils.h +++ b/include/FramelessHelper/Core/utils.h @@ -70,9 +70,7 @@ FRAMELESSHELPER_CORE_API void syncWmPaintWithDwm(); FRAMELESSHELPER_CORE_API void showSystemMenu( const WId windowId, const QPoint &pos, - const QPoint &offset, const bool selectFirstEntry, - const Global::Options options, const Global::IsWindowFixedSizeCallback &isWindowFixedSize); [[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmColorizationColor(); [[nodiscard]] FRAMELESSHELPER_CORE_API Global::DwmColorizationArea getDwmColorizationArea(); @@ -93,8 +91,6 @@ FRAMELESSHELPER_CORE_API void fixupQtInternals(const WId windowId); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized(); FRAMELESSHELPER_CORE_API void installSystemMenuHook( const WId windowId, - const Global::Options options, - const QPoint &offset, const Global::IsWindowFixedSizeCallback &isWindowFixedSize, const Global::IsInsideTitleBarDraggableAreaCallback &isInTitleBarArea, const Global::GetWindowDevicePixelRatioCallback &getDevicePixelRatio); diff --git a/include/FramelessHelper/Quick/framelesshelperquick_global.h b/include/FramelessHelper/Quick/framelesshelperquick_global.h index 72f7ce0..5b70e91 100644 --- a/include/FramelessHelper/Quick/framelesshelperquick_global.h +++ b/include/FramelessHelper/Quick/framelesshelperquick_global.h @@ -76,36 +76,6 @@ FRAMELESSHELPER_BEGIN_NAMESPACE struct FRAMELESSHELPER_QUICK_API QuickGlobal { - enum class Option - { - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, ForceHideWindowFrameBorder) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, ForceShowWindowFrameBorder) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontDrawTopWindowFrameBorder) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontForceSquareWindowCorners) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, TransparentWindowBackground) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableWindowsSnapLayout) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, CreateStandardWindowLayout) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, BeCompatibleWithQtFramelessWindowHint) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchQtInternals) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchWindowFrameBorderColor) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontInstallSystemMenuHook) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableSystemMenu) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, NoDoubleClickMaximizeToggle) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableResizing) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableDragging) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchCursorShape) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontMoveWindowToDesktopCenter) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTreatFullScreenAsZoomed) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchHighDpiScalingPolicy) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchScaleFactorRoundingPolicy) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchProcessDpiAwarenessLevel) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontEnsureNonNativeWidgetSiblings) - FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, SyncNativeControlsThemeWithSystem) - }; - Q_ENUM(Option) - Q_DECLARE_FLAGS(Options, Option) - Q_FLAG(Options) - enum class SystemTheme { FRAMELESSHELPER_QUICK_ENUM_VALUE(SystemTheme, Unknown) @@ -175,6 +145,4 @@ private: #endif }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QuickGlobal::Options) - FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/framelessquickhelper.h b/include/FramelessHelper/Quick/framelessquickhelper.h index a9a504c..fa0e33d 100644 --- a/include/FramelessHelper/Quick/framelessquickhelper.h +++ b/include/FramelessHelper/Quick/framelessquickhelper.h @@ -42,7 +42,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickHelper : public QQuickItem Q_PROPERTY(QQuickItem* titleBarItem READ titleBarItem WRITE setTitleBarItem NOTIFY titleBarItemChanged FINAL) public: - explicit FramelessQuickHelper(QQuickItem *parent = nullptr, const Global::UserSettings &settings = {}); + explicit FramelessQuickHelper(QQuickItem *parent = nullptr); ~FramelessQuickHelper() override; Q_NODISCARD static FramelessQuickHelper *qmlAttachedProperties(QObject *parentObject); @@ -61,7 +61,7 @@ public Q_SLOTS: void moveWindowToDesktopCenter(); void bringWindowToFront(); - void setWindowFixedSize(const bool value, const bool force = false); + void setWindowFixedSize(const bool value); protected: void itemChange(const ItemChange change, const ItemChangeData &data) override; diff --git a/include/FramelessHelper/Quick/framelessquickwindow.h b/include/FramelessHelper/Quick/framelessquickwindow.h index e43a764..3752b87 100644 --- a/include/FramelessHelper/Quick/framelessquickwindow.h +++ b/include/FramelessHelper/Quick/framelessquickwindow.h @@ -44,10 +44,9 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL) Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL) Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL) - Q_PROPERTY(QColor frameBorderColor READ frameBorderColor NOTIFY frameBorderColorChanged FINAL) public: - explicit FramelessQuickWindow(QWindow *parent = nullptr, const Global::UserSettings &settings = {}); + explicit FramelessQuickWindow(QWindow *parent = nullptr); ~FramelessQuickWindow() override; Q_NODISCARD bool isHidden() const; @@ -55,7 +54,6 @@ public: Q_NODISCARD bool isMinimized() const; Q_NODISCARD bool isZoomed() const; Q_NODISCARD bool isFullScreen() const; - Q_NODISCARD QColor frameBorderColor() const; public Q_SLOTS: void showMinimized2(); @@ -69,7 +67,6 @@ Q_SIGNALS: void minimizedChanged(); void zoomedChanged(); void fullScreenChanged(); - void frameBorderColorChanged(); private: QScopedPointer d_ptr; diff --git a/include/FramelessHelper/Widgets/FramelessWidgetsHelper b/include/FramelessHelper/Widgets/FramelessWidgetsHelper new file mode 100644 index 0000000..51467e8 --- /dev/null +++ b/include/FramelessHelper/Widgets/FramelessWidgetsHelper @@ -0,0 +1 @@ +#include diff --git a/include/FramelessHelper/Widgets/StandardTitleBar b/include/FramelessHelper/Widgets/StandardTitleBar new file mode 100644 index 0000000..4b8ff1e --- /dev/null +++ b/include/FramelessHelper/Widgets/StandardTitleBar @@ -0,0 +1 @@ +#include diff --git a/include/FramelessHelper/Widgets/framelessmainwindow.h b/include/FramelessHelper/Widgets/framelessmainwindow.h index 4e7e5ec..5e16ebc 100644 --- a/include/FramelessHelper/Widgets/framelessmainwindow.h +++ b/include/FramelessHelper/Widgets/framelessmainwindow.h @@ -29,7 +29,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -class FramelessWidgetsHelper; +class WidgetsSharedHelper; class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow { @@ -38,43 +38,26 @@ class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow 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) - Q_PROPERTY(bool fixedSize READ isFixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL) - Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL) public: - explicit FramelessMainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {}, const Global::UserSettings &settings = {}); + explicit FramelessMainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {}); ~FramelessMainWindow() override; Q_NODISCARD bool isNormal() const; Q_NODISCARD bool isZoomed() const; - Q_NODISCARD bool isFixedSize() const; - void setFixedSize(const bool value); - - void setTitleBarWidget(QWidget *widget); - Q_NODISCARD QWidget *titleBarWidget() const; - public Q_SLOTS: - void setHitTestVisible(QWidget *widget); void toggleMaximized(); void toggleFullScreen(); - void moveToDesktopCenter(); - void bringToFront(); - void showSystemMenu(const QPoint &pos); - void startSystemMove2(const QPoint &pos); - void startSystemResize2(const Qt::Edges edges, const QPoint &pos); - void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType); Q_SIGNALS: void hiddenChanged(); void normalChanged(); void zoomedChanged(); - void fixedSizeChanged(); - void titleBarWidgetChanged(); - void systemThemeChanged(); private: - QScopedPointer d_ptr; + QScopedPointer m_helper; + Qt::WindowState m_savedWindowState = Qt::WindowNoState; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelesswidget.h b/include/FramelessHelper/Widgets/framelesswidget.h index 2bd132e..e6d64e1 100644 --- a/include/FramelessHelper/Widgets/framelesswidget.h +++ b/include/FramelessHelper/Widgets/framelesswidget.h @@ -29,7 +29,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -class FramelessWidgetsHelper; +class WidgetsSharedHelper; class FRAMELESSHELPER_WIDGETS_API FramelessWidget : public QWidget { @@ -38,48 +38,26 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidget : public QWidget 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) - Q_PROPERTY(bool fixedSize READ isFixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL) - Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL) - Q_PROPERTY(QWidget* contentWidget READ contentWidget WRITE setContentWidget NOTIFY contentWidgetChanged FINAL) public: - explicit FramelessWidget(QWidget *parent = nullptr, const Global::UserSettings &settings = {}); + explicit FramelessWidget(QWidget *parent = nullptr); ~FramelessWidget() override; Q_NODISCARD bool isNormal() const; Q_NODISCARD bool isZoomed() const; - Q_NODISCARD bool isFixedSize() const; - void setFixedSize(const bool value); - - void setTitleBarWidget(QWidget *widget); - Q_NODISCARD QWidget *titleBarWidget() const; - - void setContentWidget(QWidget *widget); - Q_NODISCARD QWidget *contentWidget() const; - public Q_SLOTS: - void setHitTestVisible(QWidget *widget); void toggleMaximized(); void toggleFullScreen(); - void moveToDesktopCenter(); - void bringToFront(); - void showSystemMenu(const QPoint &pos); - void startSystemMove2(const QPoint &pos); - void startSystemResize2(const Qt::Edges edges, const QPoint &pos); - void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType); Q_SIGNALS: void hiddenChanged(); void normalChanged(); void zoomedChanged(); - void fixedSizeChanged(); - void titleBarWidgetChanged(); - void contentWidgetChanged(); - void systemThemeChanged(); private: - QScopedPointer d_ptr; + QScopedPointer m_helper; + Qt::WindowState m_savedWindowState = Qt::WindowNoState; }; FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Widgets/framelesswidgetshelper.h b/include/FramelessHelper/Widgets/framelesswidgetshelper.h new file mode 100644 index 0000000..80189e7 --- /dev/null +++ b/include/FramelessHelper/Widgets/framelesswidgetshelper.h @@ -0,0 +1,72 @@ +/* + * 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 "framelesshelperwidgets_global.h" +#include + +FRAMELESSHELPER_BEGIN_NAMESPACE + +class FramelessWidgetsHelperPrivate; + +class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelper : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(FramelessWidgetsHelper) + Q_DISABLE_COPY_MOVE(FramelessWidgetsHelper) + Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL) + +public: + explicit FramelessWidgetsHelper(QObject *parent = nullptr); + ~FramelessWidgetsHelper() override; + + Q_NODISCARD static FramelessWidgetsHelper *get(QObject *object); + + Q_NODISCARD QWidget *titleBarWidget() const; + Q_NODISCARD bool isWindowFixedSize() const; + +public Q_SLOTS: + void attach(); + + void setTitleBarWidget(QWidget *widget); + void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType); + void setHitTestVisible(QWidget *widget); + + void showSystemMenu(const QPoint &pos); + void windowStartSystemMove2(const QPoint &pos); + void windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos); + + void moveWindowToDesktopCenter(); + void bringWindowToFront(); + void setWindowFixedSize(const bool value); + +Q_SIGNALS: + void titleBarWidgetChanged(); + +private: + QScopedPointer d_ptr; +}; + +FRAMELESSHELPER_END_NAMESPACE diff --git a/examples/openglwidget/systembutton.cpp b/include/FramelessHelper/Widgets/standardtitlebar.h similarity index 52% rename from examples/openglwidget/systembutton.cpp rename to include/FramelessHelper/Widgets/standardtitlebar.h index 12725b3..9d923a4 100644 --- a/examples/openglwidget/systembutton.cpp +++ b/include/FramelessHelper/Widgets/standardtitlebar.h @@ -22,22 +22,38 @@ * SOFTWARE. */ -#include "systembutton.h" +#pragma once -SystemButton::SystemButton(QWidget *parent) : QPushButton(parent) +#include "framelesshelperwidgets_global.h" +#include + +FRAMELESSHELPER_BEGIN_NAMESPACE + +class StandardTitleBarPrivate; +class StandardSystemButton; + +class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget { -} + Q_OBJECT + Q_DECLARE_PRIVATE(StandardTitleBar) + Q_DISABLE_COPY_MOVE(StandardTitleBar) + Q_PROPERTY(StandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL) + Q_PROPERTY(StandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL) + Q_PROPERTY(StandardSystemButton* closeButton READ closeButton CONSTANT FINAL) -SystemButton::~SystemButton() = default; +public: + explicit StandardTitleBar(QWidget *parent = nullptr); + ~StandardTitleBar() override; -void SystemButton::setHovered(const bool value) -{ - Q_UNUSED(value); - Q_UNIMPLEMENTED(); -} + Q_NODISCARD StandardSystemButton *minimizeButton() const; + Q_NODISCARD StandardSystemButton *maximizeButton() const; + Q_NODISCARD StandardSystemButton *closeButton() const; -void SystemButton::setPressed(const bool value) -{ - Q_UNUSED(value); - Q_UNIMPLEMENTED(); -} +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QScopedPointer d_ptr; +}; + +FRAMELESSHELPER_END_NAMESPACE diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ed822b2..ec1c299 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -48,8 +48,6 @@ if(WIN32) list(APPEND SOURCES ${INCLUDE_PREFIX}/framelesshelper_windows.h ${INCLUDE_PREFIX}/framelesshelper_win.h - qwinregistry_p.h - qwinregistry.cpp utils_win.cpp framelesshelper_win.cpp ) diff --git a/src/core/framelesshelper_qt.cpp b/src/core/framelesshelper_qt.cpp index e2d245b..878f689 100644 --- a/src/core/framelesshelper_qt.cpp +++ b/src/core/framelesshelper_qt.cpp @@ -36,7 +36,6 @@ using namespace Global; struct QtHelperData { - UserSettings settings = {}; SystemParameters params = {}; FramelessHelperQt *eventFilter = nullptr; bool cursorShapeChanged = false; @@ -55,7 +54,7 @@ FramelessHelperQt::FramelessHelperQt(QObject *parent) : QObject(parent) {} FramelessHelperQt::~FramelessHelperQt() = default; -void FramelessHelperQt::addWindow(const UserSettings &settings, const SystemParameters ¶ms) +void FramelessHelperQt::addWindow(const SystemParameters ¶ms) { Q_ASSERT(params.isValid()); if (!params.isValid()) { @@ -68,7 +67,6 @@ void FramelessHelperQt::addWindow(const UserSettings &settings, const SystemPara return; } QtHelperData data = {}; - data.settings = settings; data.params = params; QWindow *window = params.getWindowHandle(); // Give it a parent so that it can be deleted even if we forget to do so. @@ -148,7 +146,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) QMutexLocker locker(&g_qtHelper()->mutex); g_qtHelper()->data[windowId].leftButtonPressed = false; } - if ((button == Qt::RightButton) && !(data.settings.options & Option::DisableSystemMenu)) { + if (button == Qt::RightButton) { if (!ignoreThisEvent && insideTitleBar) { data.params.showSystemMenu(scenePos); return true; @@ -156,8 +154,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) } } break; case QEvent::MouseButtonDblClick: { - if ((button == Qt::LeftButton) && !windowFixedSize && !ignoreThisEvent - && insideTitleBar && !(data.settings.options & Option::NoDoubleClickMaximizeToggle)) { + if ((button == Qt::LeftButton) && !windowFixedSize && !ignoreThisEvent && insideTitleBar) { Qt::WindowState newWindowState = Qt::WindowNoState; if (data.params.getWindowState() != Qt::WindowMaximized) { newWindowState = Qt::WindowMaximized; @@ -166,7 +163,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) } } break; case QEvent::MouseMove: { - if (!windowFixedSize && !(data.settings.options & Option::DontTouchCursorShape)) { + if (!windowFixedSize) { const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos); if (cs == Qt::ArrowCursor) { if (data.cursorShapeChanged) { @@ -180,7 +177,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event) g_qtHelper()->data[windowId].cursorShapeChanged = true; } } - if (data.leftButtonPressed && !(data.settings.options & Option::DisableDragging)) { + if (data.leftButtonPressed) { if (!ignoreThisEvent && insideTitleBar) { Utils::startSystemMove(window, globalPos); return true; diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index 2905841..14b0fa6 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -41,7 +41,6 @@ using namespace Global; struct Win32HelperData { - UserSettings settings = {}; SystemParameters params = {}; bool trackingMouse = false; WId dragBarWindowId = 0; @@ -353,9 +352,8 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent) if (!parentWindowId) { return false; } - if (!Utils::isWindowsVersionOrGreater(WindowsVersion::_8)) { - qWarning() << "Our drag bar window needs the WS_EX_LAYERED style, however, " - "it's not supported for child windows until Windows 8."; + if (!Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507)) { + qWarning() << "The drag bar window is only supported on Windows 10 and onwards."; return false; } const auto parentWindowHandle = reinterpret_cast(parentWindowId); @@ -415,7 +413,7 @@ FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {} FramelessHelperWin::~FramelessHelperWin() = default; -void FramelessHelperWin::addWindow(const UserSettings &settings, const SystemParameters ¶ms) +void FramelessHelperWin::addWindow(const SystemParameters ¶ms) { Q_ASSERT(params.isValid()); if (!params.isValid()) { @@ -428,44 +426,27 @@ void FramelessHelperWin::addWindow(const UserSettings &settings, const SystemPar return; } Win32HelperData data = {}; - data.settings = settings; data.params = params; - if ((settings.options & Option::ForceHideWindowFrameBorder) - && (settings.options & Option::ForceShowWindowFrameBorder)) { - data.settings.options &= ~(Option::ForceHideWindowFrameBorder | Option::ForceShowWindowFrameBorder); - qWarning() << "You can't use both \"Option::ForceHideWindowFrameBorder\" and " - "\"Option::ForceShowWindowFrameBorder\" at the same time."; - } g_win32Helper()->data.insert(windowId, data); if (g_win32Helper()->nativeEventFilter.isNull()) { g_win32Helper()->nativeEventFilter.reset(new FramelessHelperWin); qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data()); } g_win32Helper()->mutex.unlock(); - if (!(settings.options & Option::DontTouchQtInternals)) { - Utils::fixupQtInternals(windowId); - } + Utils::fixupQtInternals(windowId); Utils::updateInternalWindowFrameMargins(params.getWindowHandle(), true); Utils::updateWindowFrameMargins(windowId, false); - if (Utils::isWindowsVersionOrGreater(WindowsVersion::_8)) { - if (!(settings.options & Option::DisableWindowsSnapLayout)) { - if (!createDragBarWindow(windowId)) { - qWarning() << "Failed to create the drag bar window."; - } + if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507)) { + if (!createDragBarWindow(windowId)) { + qWarning() << "Failed to create the drag bar window."; } if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607)) { const bool dark = Utils::shouldAppsUseDarkMode(); - if (!(settings.options & Option::DontTouchWindowFrameBorderColor)) { - Utils::updateWindowFrameBorderColor(windowId, dark); - } + Utils::updateWindowFrameBorderColor(windowId, dark); if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) { - if (settings.options & Option::SyncNativeControlsThemeWithSystem) { - Utils::updateGlobalWin32ControlsTheme(windowId, dark); - } + //Utils::updateGlobalWin32ControlsTheme(windowId, dark); // Causes some QtWidgets paint incorrectly. if (Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)) { - if (!(settings.options & Option::DontForceSquareWindowCorners)) { - Utils::forceSquareCornersForWindow(windowId, true); - } + Utils::forceSquareCornersForWindow(windowId, true); } } } @@ -499,15 +480,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } const Win32HelperData data = g_win32Helper()->data.value(windowId); g_win32Helper()->mutex.unlock(); - const bool frameBorderVisible = [&data]() -> bool { - if (data.settings.options & Option::ForceShowWindowFrameBorder) { - return true; - } - if (data.settings.options & Option::ForceHideWindowFrameBorder) { - return false; - } - return Utils::isWindowFrameBorderVisible(); - }(); + const bool frameBorderVisible = Utils::isWindowFrameBorderVisible(); const UINT uMsg = msg->message; const WPARAM wParam = msg->wParam; const LPARAM lParam = msg->lParam; @@ -832,8 +805,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me const bool buttonSwapped = (GetSystemMetrics(SM_SWAPBUTTON) != FALSE); const bool leftButtonPressed = (buttonSwapped ? (GetAsyncKeyState(VK_RBUTTON) < 0) : (GetAsyncKeyState(VK_LBUTTON) < 0)); - const bool isTitleBar = (data.params.isInsideTitleBarDraggableArea(qtScenePos) && - leftButtonPressed && !(data.settings.options & Option::DisableDragging)); + const bool isTitleBar = (data.params.isInsideTitleBarDraggableArea(qtScenePos) && leftButtonPressed); if (frameBorderVisible) { // This will handle the left, right and bottom parts of the frame // because we didn't change them. @@ -1040,13 +1012,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me .compare(qThemeSettingChangeEventName, Qt::CaseInsensitive) == 0)) { systemThemeChanged = true; const bool dark = Utils::shouldAppsUseDarkMode(); - if (!(data.settings.options & Option::DontTouchWindowFrameBorderColor)) { - Utils::updateWindowFrameBorderColor(windowId, dark); - } + Utils::updateWindowFrameBorderColor(windowId, dark); if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) { - if (data.settings.options & Option::SyncNativeControlsThemeWithSystem) { - Utils::updateGlobalWin32ControlsTheme(windowId, dark); - } + //Utils::updateGlobalWin32ControlsTheme(windowId, dark); } } } diff --git a/src/core/framelesswindowsmanager.cpp b/src/core/framelesswindowsmanager.cpp index c75b42c..bbb2a3a 100644 --- a/src/core/framelesswindowsmanager.cpp +++ b/src/core/framelesswindowsmanager.cpp @@ -117,7 +117,7 @@ QColor FramelessWindowsManagerPrivate::systemAccentColor() const return m_accentColor; } -void FramelessWindowsManagerPrivate::addWindow(const UserSettings &settings, const SystemParameters ¶ms) +void FramelessWindowsManagerPrivate::addWindow(const SystemParameters ¶ms) { Q_ASSERT(params.isValid()); if (!params.isValid()) { @@ -151,16 +151,14 @@ void FramelessWindowsManagerPrivate::addWindow(const UserSettings &settings, con } #endif if (pureQt) { - FramelessHelperQt::addWindow(settings, params); + FramelessHelperQt::addWindow(params); } #ifdef Q_OS_WINDOWS if (!pureQt) { - FramelessHelperWin::addWindow(settings, params); - } - if (!(settings.options & Option::DontInstallSystemMenuHook)) { - Utils::installSystemMenuHook(windowId, settings.options, settings.systemMenuOffset, - params.isWindowFixedSize, params.isInsideTitleBarDraggableArea, params.getWindowDevicePixelRatio); + FramelessHelperWin::addWindow(params); } + Utils::installSystemMenuHook(windowId, params.isWindowFixedSize, + params.isInsideTitleBarDraggableArea, params.getWindowDevicePixelRatio); #endif } @@ -242,13 +240,13 @@ QColor FramelessWindowsManager::systemAccentColor() const return d->systemAccentColor(); } -void FramelessWindowsManager::addWindow(const UserSettings &settings, const SystemParameters ¶ms) +void FramelessWindowsManager::addWindow(const SystemParameters ¶ms) { Q_D(FramelessWindowsManager); - d->addWindow(settings, params); + d->addWindow(params); } -void FramelessHelper::Core::initialize(const Options options) +void FramelessHelper::Core::initialize() { static bool inited = false; if (inited) { @@ -256,7 +254,7 @@ void FramelessHelper::Core::initialize(const Options options) } inited = true; #ifdef Q_OS_LINUX - // Qt's Wayland experience is not good, so we force the X11 backend here. + // Qt's Wayland experience is not good, so we force the XCB backend here. // TODO: Remove this hack once Qt's Wayland implementation is good enough. // We are setting the preferred QPA backend, so we have to set it early // enough, that is, before the construction of any Q(Gui)Application @@ -269,42 +267,33 @@ void FramelessHelper::Core::initialize(const Options options) qputenv(MAC_LAYER_ENV_VAR, kValueOne); #endif #ifdef Q_OS_WINDOWS - if (!(options & Option::DontTouchProcessDpiAwarenessLevel)) { - // This is equivalent to set the "dpiAware" and "dpiAwareness" field in - // your manifest file. It works through out Windows Vista to Windows 11. - // It's highly recommended to enable the highest DPI awareness level - // (currently it's PerMonitor Version 2, or PMv2 for short) for any GUI - // applications, to allow your user interface scale to an appropriate - // size and still stay sharp, though you will have to do the calculation - // and resize by yourself. - Utils::tryToEnableHighestDpiAwarenessLevel(); - } + // This is equivalent to set the "dpiAware" and "dpiAwareness" field in + // your manifest file. It works through out Windows Vista to Windows 11. + // It's highly recommended to enable the highest DPI awareness level + // (currently it's PerMonitor Version 2, or PMv2 for short) for any GUI + // applications, to allow your user interface scale to an appropriate + // size and still stay sharp, though you will have to do the calculation + // and resize by yourself. + Utils::tryToEnableHighestDpiAwarenessLevel(); #endif - if (!(options & Option::DontEnsureNonNativeWidgetSiblings)) { - // This attribute is known to be __NOT__ compatible with QGLWidget. - // Please consider migrating to the recommended QOpenGLWidget instead. - QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); - } + // This attribute is known to be __NOT__ compatible with QGLWidget. + // Please consider migrating to the recommended QOpenGLWidget instead. + QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) - if (!(options & Option::DontTouchHighDpiScalingPolicy)) { - // Enable high DPI scaling by default, but only for Qt5 applications, - // because this has become the default setting since Qt6 and it can't - // be changed from outside anymore (except for internal testing purposes). - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - } + // Enable high DPI scaling by default, but only for Qt5 applications, + // because this has become the default setting since Qt6 and it can't + // be changed from outside anymore (except for internal testing purposes). + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - if (!(options & Option::DontTouchScaleFactorRoundingPolicy)) { - // Non-integer scale factors will cause Qt have some painting defects - // for both Qt Widgets and Qt Quick applications, and it's still not - // totally fixed till now (Qt 6.4), so we round the scale factors to - // get a better looking. Non-integer scale factors will also cause - // flicker and jitter during window resizing. - QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); - } + // Non-integer scale factors will cause Qt have some painting defects + // for both Qt Widgets and Qt Quick applications, and it's still not + // totally fixed till now (Qt 6.4), so we round the scale factors to + // get a better looking. Non-integer scale factors will also cause + // flicker and jitter during window resizing. + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); #endif - qRegisterMetaType