Sine Striker
2023-12-27 1571d7b43228a0ed4347f681a16b2b23defccda9
Add doxygen documentations
12个文件已修改
267 ■■■■ 已修改文件
README.md 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/CMakeLists.txt 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/style/styleagent.cpp 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/windowagentbase.cpp 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/windowagentbase.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/quick/CMakeLists.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/quick/quickwindowagent.cpp 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/CMakeLists.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent.cpp 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent_mac.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -5,21 +5,11 @@
This project inherited most of [wangwenx190 FramelessHelper](https://github.com/wangwenx190/framelesshelper)
implementation, with a complete refactoring and upgrading of the architecture.
Support as many system native features as possible without requiring additional dependencies.
Feature requests are welcome.
<!-- ## Why using QWindowKit?
## Join with Us :triangular_flag_on_post:
Here are why `QWindowKit` is better than `FramelessHelper`:
+ Full support of Windows 11 Snap Layout
+ Most of the redundant codes and architectural flaws are eliminated, and the binary size compiled by MSVC is about 1/9 of `FramelessHelper`
+ A critical issue that moving window forces the entire window to be repainted on Windows is fixed
+ Capable to cope with WinId mutation, and `QWebEngineView` is perfectly supported
+ Better workaround to handle Windows 10 top border issue
+ Simpler APIs, more detailed documentation and comments
+ A lot of bugs are fixed
Feature requests are welcome. -->
You can join our [Discord channel](https://discord.gg/grrM4Tmesy). You can share your findings, thoughts and ideas on improving / implementing FramelessHelper functionalities on more platforms and apps!
## Supported Platforms
@@ -27,12 +17,21 @@
+ Apple macOS (11+)
+ GNU/Linux
## Features
+ Full support of Windows 11 Snap Layout
+ Better workaround to handle Windows 10 top border issue
+ Support Mac system buttons geometry customization
+ Simpler APIs, more detailed documentations and comments
## Gallery
### Windows 11 (With Snap Layout)
![image](./docs/images/win11.png)
### Windows 10 (And 7, Vista)
![image](./docs/images/win10.png)
### macOS & Linux
@@ -130,7 +129,8 @@
}
```
If you don't want to derive a new widget class or change the constructor, you can initialize the agent after the window constructs.
If you don't want to derive a new widget class or change the constructor, you can initialize the agent after the window
constructs.
```c++
auto w = new MyWidget();
@@ -140,9 +140,11 @@
#### Construct Title bar
Then, construct your title bar widget, without which the window lacks the basic interaction feature, and it's better to put it into the window's layout.
Then, construct your title bar widget, without which the window lacks the basic interaction feature, and it's better to
put it into the window's layout.
You can use the [`WindowBar`](examples/shared/widgetframe/windowbar.h) provided by `WidgetFrame` in the examples as the container of your title bar components.
You can use the [`WindowBar`](examples/shared/widgetframe/windowbar.h) provided by `WidgetFrame` in the examples as the
container of your title bar components.
Let `WidgetWindowAgent` know which widget the title bar is.
@@ -150,7 +152,8 @@
agent->setTitleBar(myTitleBar);
```
Next, set system button hints to let `WidgetWindowAgent` know the role of the child widgets, which is important for the Snap Layout to work.
Next, set system button hints to let `WidgetWindowAgent` know the role of the child widgets, which is important for the
Snap Layout to work.
```c++
agent->setSystemButton(QWK::WindowAgentBase::WindowIcon, myTitleBar->iconButton());
@@ -158,11 +161,14 @@
agent->setSystemButton(QWK::WindowAgentBase::Maximize, myTitleBar->maxButton());
agent->setSystemButton(QWK::WindowAgentBase::Close, myTitleBar->closeButton());
```
Doing this does not mean that these buttons' click events are automatically associated with window actions, you still need to manually connect the signals and slots to emulate the native window behaviors.
Doing this does not mean that these buttons' click events are automatically associated with window actions, you still
need to manually connect the signals and slots to emulate the native window behaviors.
On macOS, this step can be skipped because it is better to use the buttons provided by the system.
Last but not least, set hit-test visible hint to let `WidgetWindowAgent` know other widgets that desire to receive mouse events.
Last but not least, set hit-test visible hint to let `WidgetWindowAgent` know other widgets that desire to receive mouse
events.
```c++
agent->setHitTestVisible(myTitleBar->menuBar(), true);
@@ -170,8 +176,7 @@
The rest region within the title bar will be regarded as the draggable area for the user to move the window.
#### Window Attributes (Experimental)
<!-- #### Window Attributes (Experimental)
On Windows 11, you can use this API to enable system effects.
@@ -179,7 +184,7 @@
agent->setWindowAttribute("mica", true);
```
Available keys: `mica`, `mica-alt`, `acrylic`, `dark-mode`.
Available keys: `mica`, `mica-alt`, `acrylic`, `dark-mode`. -->
### Qt Quick Application
@@ -224,23 +229,19 @@
You can omit the version number or use "auto" instead of "1.0" for the module URI if you are using Qt6.
#### Window Attributes (Experimental)
TODO
### Learn More
See [examples](examples) for more demo use cases. The examples have no High DPI support.
## Documentations
+ Examples (TODO)
+ Notes (TODO)
+ [FramelessHelper Related](docs/framelesshelper-related.md)
## TODO
+ Fix 5.15 window abnormal behavior
+ Support Mac style change notification
+ Support Mac system buttons customization for Quick
+ More documentations
+ When do we support Linux native features?
## Special Thanks
examples/mainwindow/mainwindow.cpp
@@ -292,6 +292,10 @@
void MainWindow::installStyleAgent() {
    styleAgent = new QWK::StyleAgent(this);
    connect(styleAgent, &QWK::StyleAgent::systemThemeChanged, this, [this]() {
        qDebug() << "System style changed:" << styleAgent->systemTheme(); //
    });
}
void MainWindow::loadStyleSheet(Theme theme) {
src/CMakeLists.txt
@@ -136,6 +136,43 @@
endif()
# ----------------------------------
# Documentation
# ----------------------------------
if(QWINDOWKIT_BUILD_DOCUMENTATIONS)
    if(NOT DOXYGEN_EXECUTABLE)
        find_package(Doxygen REQUIRED)
    endif()
    set(_install_options)
    if(QWINDOWKIT_INSTALL)
        set(_install_options INSTALL_DIR share/doc/${QWINDOWKIT_INSTALL_NAME})
    endif()
    set(_doc_targets ${QWINDOWKIT_ENABLED_TARGETS})
    set(QWINDOWKIT_DOXYGEN_TAGFILE
        ${CMAKE_BUILD_SHARE_DIR}/doc/${QWINDOWKIT_INSTALL_NAME}/${QWINDOWKIT_INSTALL_NAME}_tagfile.xml
        CACHE FILEPATH "QWindowKit doxygen tag file path" FORCE
    )
    qm_import(Doxygen)
    qm_setup_doxygen(QWindowKit_RunDoxygen
        NAME "QWindowKit"
        DESCRIPTION "${QWINDOWKIT_PROJECT_DESCRIPTION}"
        MDFILE ../README.md
        OUTPUT_DIR ${CMAKE_BUILD_SHARE_DIR}/doc/${QWINDOWKIT_INSTALL_NAME}
        INPUT ${QWINDOWKIT_ENABLED_SUBDIRECTORIES}
        TARGETS ${_doc_targets}
        DEPENDS ${_doc_targets}
        NO_EXPAND_MACROS Q_OBJECT Q_GADGET Q_DECLARE_TR_FUNCTIONS
        COMPILE_DEFINITIONS Q_SIGNALS=Q_SIGNALS Q_SLOTS=Q_SLOTS
        GENERATE_TAGFILE "${QWINDOWKIT_DOXYGEN_TAGFILE}"
        ${_install_options}
    )
endif()
# ----------------------------------
# Install
# ----------------------------------
if(QWINDOWKIT_INSTALL)
src/core/style/styleagent.cpp
@@ -5,6 +5,11 @@
namespace QWK {
    /*!
        \class StyleAgent
        \brief StyleAgent provides some features related to system theme.
    */
    StyleAgentPrivate::StyleAgentPrivate() {
    }
@@ -25,21 +30,40 @@
        Q_EMIT q->systemThemeChanged();
    }
    /*!
        Constructor. Since it is not related to a concrete window instance, it is better to be used
        as a singleton.
    */
    StyleAgent::StyleAgent(QObject *parent) : StyleAgent(*new StyleAgentPrivate(), parent) {
    }
    /*!
        Destructor.
    */
    StyleAgent::~StyleAgent() {
    }
    /*!
        Returns the system theme.
    */
    StyleAgent::SystemTheme StyleAgent::systemTheme() const {
        Q_D(const StyleAgent);
        return d->systemTheme;
    }
    /*!
        \internal
    */
    StyleAgent::StyleAgent(StyleAgentPrivate &d, QObject *parent) : QObject(parent), d_ptr(&d) {
        d.q_ptr = this;
        d.init();
    }
    /*!
        \fn void StyleAgent::systemThemeChanged()
        This signal is emitted when the system theme changes.
    */
}
src/core/windowagentbase.cpp
@@ -17,6 +17,20 @@
namespace QWK {
    /*!
        \namespace QWK
        \brief QWindowKit namespace
    */
    /*!
        \class WindowAgentBase
        \brief WindowAgentBase is the base class of the specifiy window agent for QtWidgets and
        QtQuick.
        It processes some system events and the implements of frameless logic, and provides some
        common methods for derived classes to call.
    */
    WindowAgentBasePrivate::WindowContextFactoryMethod
        WindowAgentBasePrivate::windowContextFactoryMethod = nullptr;
@@ -48,33 +62,74 @@
        context.reset(ctx);
    }
    /*!
        Destructor.
    */
    WindowAgentBase::~WindowAgentBase() = default;
    /*!
        Returns the window attribute value.
        \sa setWindowAttribute()
    */
    QVariant WindowAgentBase::windowAttribute(const QString &key) const {
        Q_D(const WindowAgentBase);
        return d->context->windowAttribute(key);
    }
    /*!
        Sets the platform-related attribute for the window.
        Available attributes:
        On Windows,
            \li \c acrylic-material: Specify a boolean value to enable or disable acrylic material,
                    this attribute is only available on Windows 11.
            \li \c mica: Specify a boolean value to enable or disable mica material,
                    this attribute is only available on Windows 11.
            \li \c mica-alt: Specify a boolean value to enable or disable mica-alt material,
                    this attribute is only available on Windows 11.
            \li \c dark-mode: Specify a boolean value to enable or disable the dark mode, it is
                    enabled by default on Windows 10 if the system borders config is enabled.
            \li \c extra-margins: Specify a margin value to change the \c dwm extended area
                    geometry, you shouldn't change this attribute because it may break the
                    internal state.
        On macOS,
            \li \c no-system-buttons: Specify a boolean value to set the system buttons' visibility.
    */
    bool WindowAgentBase::setWindowAttribute(const QString &key, const QVariant &attribute) {
        Q_D(WindowAgentBase);
        return d->context->setWindowAttribute(key, attribute);
    }
    /*!
        Shows the system menu, it's only implemented on Windows.
    */
    void WindowAgentBase::showSystemMenu(const QPoint &pos) {
        Q_D(WindowAgentBase);
        d->context->showSystemMenu(pos);
    }
    /*!
        Makes the window show in center of the current screen.
    */
    void WindowAgentBase::centralize() {
        Q_D(WindowAgentBase);
        d->context->virtual_hook(AbstractWindowContext::CentralizeHook, nullptr);
    }
    /*!
        Brings the window to top.
    */
    void WindowAgentBase::raise() {
        Q_D(WindowAgentBase);
        d->context->virtual_hook(AbstractWindowContext::RaiseWindowHook, nullptr);
    }
    /*!
        \internal
    */
    WindowAgentBase::WindowAgentBase(WindowAgentBasePrivate &d, QObject *parent)
        : QObject(parent), d_ptr(&d) {
        d.q_ptr = this;
src/core/windowagentbase.h
@@ -30,9 +30,6 @@
        QVariant windowAttribute(const QString &key) const;
        Q_INVOKABLE bool setWindowAttribute(const QString &key, const QVariant &attribute);
    Q_SIGNALS:
        void systemThemeChanged();
    public Q_SLOTS:
        void showSystemMenu(const QPoint &pos); // Only available on Windows now
        void centralize();
src/quick/CMakeLists.txt
@@ -22,7 +22,7 @@
    LINKS QWKCore
    QT_LINKS Core Gui Quick
    QT_INCLUDE_PRIVATE Core Gui Quick
    INCLUDE_PRIVATE contexts
    INCLUDE_PRIVATE
    PREFIX QWK_QUICK
)
src/quick/quickwindowagent.cpp
@@ -8,6 +8,14 @@
namespace QWK {
    /*!
        \class QuickWindowAgent
        \brief QuickWindowAgent is the window agent for QtQuick.
        It provides interfaces for QtQuick and processes some Qt events related to the QQuickItem
        instance. The usage of all APIs is consistent with the \a Widgets module.
    */
    QuickWindowAgentPrivate::QuickWindowAgentPrivate() = default;
    QuickWindowAgentPrivate::~QuickWindowAgentPrivate() = default;
@@ -77,6 +85,9 @@
        d->context->setHitTestVisible(item, visible);
    }
    /*!
        \internal
    */
    QuickWindowAgent::QuickWindowAgent(QuickWindowAgentPrivate &d, QObject *parent)
        : WindowAgentBase(d, parent) {
        d.init();
src/widgets/CMakeLists.txt
@@ -23,7 +23,7 @@
    LINKS QWKCore
    QT_LINKS Core Gui Widgets
    QT_INCLUDE_PRIVATE Core Gui Widgets
    INCLUDE_PRIVATE contexts
    INCLUDE_PRIVATE
    PREFIX QWK_WIDGETS
)
src/widgets/widgetwindowagent.cpp
@@ -9,6 +9,14 @@
namespace QWK {
    /*!
        \class WidgetWindowAgent
        \brief WindowAgentBase is the window agent for QtWidgets.
        It provides interfaces for QtWidgets and processes some Qt events related to the QWidget
        instance.
    */
    WidgetWindowAgentPrivate::WidgetWindowAgentPrivate() = default;
    WidgetWindowAgentPrivate::~WidgetWindowAgentPrivate() = default;
@@ -16,12 +24,22 @@
    void WidgetWindowAgentPrivate::init() {
    }
    /*!
        Constructs a widget agent, it's better to set the widget to setup as \a parent.
    */
    WidgetWindowAgent::WidgetWindowAgent(QObject *parent)
        : WidgetWindowAgent(*new WidgetWindowAgentPrivate(), parent) {
    }
    /*!
        Destructor.
    */
    WidgetWindowAgent::~WidgetWindowAgent() = default;
    /*!
        Installs the window agent on the widget. The window agent will take over some of the window
        events, making the window look frameless.
    */
    bool WidgetWindowAgent::setup(QWidget *w) {
        Q_ASSERT(w);
        if (!w) {
@@ -45,24 +63,38 @@
        return true;
    }
    /*!
        Returns the title bar widget.
    */
    QWidget *WidgetWindowAgent::titleBar() const {
        Q_D(const WidgetWindowAgent);
        return static_cast<QWidget *>(d->context->titleBar());
    }
    /*!
        Sets the title bar widget, all system button and hit-test visible widget references that
        have been set will be removed.
    */
    void WidgetWindowAgent::setTitleBar(QWidget *w) {
        Q_D(WidgetWindowAgent);
        if (!d->context->setTitleBar(w)) {
            return;
        }
        Q_EMIT titleBarWidgetChanged(w);
        Q_EMIT titleBarChanged(w);
    }
    /*!
        Returns the system button of the given type.
    */
    QWidget *WidgetWindowAgent::systemButton(SystemButton button) const {
        Q_D(const WidgetWindowAgent);
        return static_cast<QWidget *>(d->context->systemButton(button));
    }
    /*!
        Sets the system button of the given type, the system buttons always receive mouse events so
        you don't need to call \c setHitTestVisible for them.
    */
    void WidgetWindowAgent::setSystemButton(SystemButton button, QWidget *w) {
        Q_D(WidgetWindowAgent);
        if (!d->context->setSystemButton(button, w)) {
@@ -71,18 +103,42 @@
        Q_EMIT systemButtonChanged(button, w);
    }
    /*!
        Returns \a true if the widget can receive mouse events on title bar.
    */
    bool WidgetWindowAgent::isHitTestVisible(const QWidget *w) const {
        Q_D(const WidgetWindowAgent);
        return d->context->isHitTestVisible(w);
    }
    /*!
        Makes the widget able to receive mouse events on title bar if \a visible is \c true.
        You're supposed to make sure that the specified widget \a w is a child or descendant
        of the title bar widget.
    */
    void WidgetWindowAgent::setHitTestVisible(const QWidget *w, bool visible) {
        Q_D(WidgetWindowAgent);
        d->context->setHitTestVisible(w, visible);
    }
    /*!
        \internal
    */
    WidgetWindowAgent::WidgetWindowAgent(WidgetWindowAgentPrivate &d, QObject *parent)
        : WindowAgentBase(d, parent) {
        d.init();
    }
    /*!
        \fn void WidgetWindowAgent::titleBarChanged(const QWidget *w)
        This signal is emitted when the title bar widget is replaced.
    */
    /*!
        \fn void WidgetWindowAgent::systemButtonChanged(SystemButton button, const QWidget *w)
        This signal is emitted when a system button is replaced.
    */
}
src/widgets/widgetwindowagent.h
@@ -26,7 +26,6 @@
        QWidget *systemButton(SystemButton button) const;
        void setSystemButton(SystemButton button, QWidget *w);
        // Not implement, don't use now
#ifdef Q_OS_MAC
        QWidget *systemButtonArea() const;
        void setSystemButtonArea(QWidget *widget);
@@ -36,7 +35,7 @@
        void setHitTestVisible(const QWidget *w, bool visible = true);
    Q_SIGNALS:
        void titleBarWidgetChanged(const QWidget *w);
        void titleBarChanged(const QWidget *w);
        void systemButtonChanged(SystemButton button, const QWidget *w);
    protected:
src/widgets/widgetwindowagent_mac.cpp
@@ -35,11 +35,18 @@
        AbstractWindowContext *ctx;
    };
    /*!
        Returns the widget that acts as the system button area.
    */
    QWidget *WidgetWindowAgent::systemButtonArea() const {
        Q_D(const WidgetWindowAgent);
        return d->systemButtonAreaWidget;
    }
    /*!
        Sets the widget that acts as the system button area. The system button will be centered in
        its area, it is recommended to place the widget in a layout and set a fixed size policy.
    */
    void WidgetWindowAgent::setSystemButtonArea(QWidget *widget) {
        Q_D(WidgetWindowAgent);
        auto ctx = d->context.get();