Zhao Yuhang
2023-12-21 430d245bb94c634047e7b65232eb3e50e2b6e49a
add more attrib
8个文件已修改
167 ■■■■ 已修改文件
examples/mainwindow/CMakeLists.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/dark-style.qss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/light-style.qss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.cpp 83 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/shared/qwkwindowsextra_p.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/stylesupport/styleagent_p.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/stylesupport/styleagent_win.cpp 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/CMakeLists.txt
@@ -5,7 +5,7 @@
qwk_add_example(${PROJECT_NAME}
    SOURCES ${_src} mainwindow.qrc ../shared/resources/shared.qrc
    QT_LINKS Core Gui Widgets
    LINKS QWKWidgets WidgetFrame
    LINKS QWKWidgets QWKStyleSupport WidgetFrame
)
set_target_properties(${PROJECT_NAME} PROPERTIES
examples/mainwindow/dark-style.qss
@@ -142,7 +142,11 @@
/* Window */
MainWindow {
MainWindow[custom-style=true] {
    background-color: transparent;
}
MainWindow[custom-style=false] {
    background-color: #1E1E1E;
}
examples/mainwindow/light-style.qss
@@ -140,7 +140,11 @@
/* Window */
MainWindow {
MainWindow[custom-style=true] {
    background-color: transparent;
}
MainWindow[custom-style=false] {
    background-color: #F3F3F3;
}
examples/mainwindow/mainwindow.cpp
@@ -4,11 +4,14 @@
#include <QtCore/QFile>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtGui/QPainter>
#include <QtGui/QActionGroup>
#include <QtWidgets/QApplication>
#include <QtWidgets/QStyle>
#include <QtWidgets/QPushButton>
#include <QWKWidgets/widgetwindowagent.h>
#include <QWKStyleSupport/styleagent.h>
#include <widgetframe/windowbar.h>
#include <widgetframe/windowbutton.h>
@@ -30,6 +33,8 @@
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    installWindowAgent();
    styleAgent = new QWK::StyleAgent(this);
    auto clockWidget = new ClockWidget();
    clockWidget->setObjectName(QStringLiteral("clock-widget"));
@@ -104,11 +109,11 @@
void MainWindow::installWindowAgent() {
    // 1. Setup window agent
    auto agent = new QWK::WidgetWindowAgent(this);
    agent->setup(this);
    windowAgent = new QWK::WidgetWindowAgent(this);
    windowAgent->setup(this);
    // 2. Construct your title bar
    auto menuBar = [this, agent]() {
    auto menuBar = [this]() {
        auto menuBar = new QMenuBar();
        // Virtual menu
@@ -122,7 +127,7 @@
        edit->addAction(new QAction(tr("Redo(&R)"), menuBar));
        // Theme action
        auto darkAction = new QAction(tr("Dark Theme"), menuBar);
        auto darkAction = new QAction(tr("Enable dark theme"), menuBar);
        darkAction->setCheckable(true);
        connect(darkAction, &QAction::triggered, this, [this](bool checked) {
            loadStyleSheet(checked ? Dark : Light); //
@@ -131,10 +136,60 @@
            darkAction->setChecked(currentTheme == Dark); //
        });
#ifdef Q_OS_WIN
        auto dwmBlurAction = new QAction(tr("Enable DWM blur"), menuBar);
        dwmBlurAction->setCheckable(true);
        connect(dwmBlurAction, &QAction::triggered, this, [this](bool checked){
            QWindow *w = windowHandle();
            styleAgent->setWindowAttribute(w, QStringLiteral("dwm-blur"), checked);
            setProperty("custom-style", checked);
            style()->polish(this);
        });
        auto acrylicAction = new QAction(tr("Enable acrylic material"), menuBar);
        acrylicAction->setCheckable(true);
        connect(acrylicAction, &QAction::triggered, this, [this](bool checked){
            QWindow *w = windowHandle();
            styleAgent->setWindowAttribute(w, QStringLiteral("acrylic-material"), QColor());
            setProperty("custom-style", checked);
            style()->polish(this);
        });
        auto micaAction = new QAction(tr("Enable mica"), menuBar);
        micaAction->setCheckable(true);
        connect(micaAction, &QAction::triggered, this, [this](bool checked){
            QWindow *w = windowHandle();
            styleAgent->setWindowAttribute(w, QStringLiteral("mica"), checked);
            setProperty("custom-style", checked);
            style()->polish(this);
        });
        auto micaAltAction = new QAction(tr("Enable mica alt"), menuBar);
        micaAltAction->setCheckable(true);
        connect(micaAltAction, &QAction::triggered, this, [this](bool checked){
            QWindow *w = windowHandle();
            styleAgent->setWindowAttribute(w, QStringLiteral("mica-alt"), checked);
            setProperty("custom-style", checked);
            style()->polish(this);
        });
        auto winStyleGroup = new QActionGroup(menuBar);
        winStyleGroup->addAction(dwmBlurAction);
        winStyleGroup->addAction(acrylicAction);
        winStyleGroup->addAction(micaAction);
        winStyleGroup->addAction(micaAltAction);
#endif
        // Real menu
        auto settings = new QMenu(tr("Settings(&S)"), menuBar);
        settings->addAction(darkAction);
#ifdef Q_OS_WIN
        settings->addSeparator();
        settings->addAction(dwmBlurAction);
        settings->addAction(acrylicAction);
        settings->addAction(micaAction);
        settings->addAction(micaAltAction);
#endif
        menuBar->addMenu(file);
        menuBar->addMenu(edit);
@@ -180,28 +235,28 @@
    windowBar->setTitleLabel(titleLabel);
    windowBar->setHostWidget(this);
    agent->setTitleBar(windowBar);
    windowAgent->setTitleBar(windowBar);
#ifndef Q_OS_MAC
    agent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
    agent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
    agent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
    agent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
#endif
    agent->setHitTestVisible(menuBar, true);
    windowAgent->setHitTestVisible(menuBar, true);
    setMenuWidget(windowBar);
    // 3. Adds simulated mouse events to the title bar buttons
#ifdef Q_OS_WINDOWS
    // Emulate Window system menu button behaviors
    connect(iconButton, &QAbstractButton::clicked, agent, [iconButton, agent] {
    connect(iconButton, &QAbstractButton::clicked, windowAgent, [this, iconButton] {
        iconButton->setProperty("double-click-close", false);
        // Pick a suitable time threshold
        QTimer::singleShot(75, agent, [iconButton, agent]() {
        QTimer::singleShot(75, windowAgent, [this, iconButton]() {
            if (iconButton->property("double-click-close").toBool())
                return;
            agent->showSystemMenu(iconButton->mapToGlobal(QPoint{0, iconButton->height()}));
            windowAgent->showSystemMenu(iconButton->mapToGlobal(QPoint{0, iconButton->height()}));
        });
    });
    connect(iconButton, &QWK::WindowButton::doubleClicked, this, [iconButton, this]() {
@@ -238,4 +293,4 @@
        setStyleSheet(QString::fromUtf8(qss.readAll()));
        Q_EMIT themeChanged();
    }
}
}
examples/mainwindow/mainwindow.h
@@ -3,6 +3,11 @@
#include <QtWidgets/QMainWindow>
namespace QWK {
    class WidgetWindowAgent;
    class StyleAgent;
}
class MainWindow : public QMainWindow {
    Q_OBJECT
public:
@@ -26,6 +31,9 @@
    void loadStyleSheet(Theme theme);
    Theme currentTheme{};
    QWK::WidgetWindowAgent *windowAgent;
    QWK::StyleAgent *styleAgent;
};
#endif // MAINWINDOW_H
src/core/shared/qwkwindowsextra_p.h
@@ -16,6 +16,9 @@
#include <QWKCore/qwindowkit_windows.h>
#include <QtGui/QStyleHints>
#include <QtGui/QPalette>
#include <QtCore/private/qsystemlibrary_p.h>
#include <QtCore/private/qwinregistry_p.h>
@@ -146,6 +149,7 @@
            DYNAMIC_API_DECLARE(DwmGetWindowAttribute);
            DYNAMIC_API_DECLARE(DwmSetWindowAttribute);
            DYNAMIC_API_DECLARE(DwmExtendFrameIntoClientArea);
            DYNAMIC_API_DECLARE(DwmEnableBlurBehindWindow);
            DYNAMIC_API_DECLARE(GetDpiForWindow);
            DYNAMIC_API_DECLARE(GetSystemMetricsForDpi);
            DYNAMIC_API_DECLARE(GetDpiForMonitor);
@@ -177,6 +181,7 @@
                DYNAMIC_API_RESOLVE(dwmapi, DwmGetWindowAttribute);
                DYNAMIC_API_RESOLVE(dwmapi, DwmSetWindowAttribute);
                DYNAMIC_API_RESOLVE(dwmapi, DwmExtendFrameIntoClientArea);
                DYNAMIC_API_RESOLVE(dwmapi, DwmEnableBlurBehindWindow);
                QSystemLibrary winmm(QStringLiteral("winmm"));
                DYNAMIC_API_RESOLVE(winmm, timeGetDevCaps);
src/stylesupport/styleagent_p.h
@@ -2,6 +2,7 @@
#define STYLEAGENTPRIVATE_H
#include <QWKStyleSupport/styleagent.h>
#include <QtCore/QHash>
namespace QWK {
src/stylesupport/styleagent_win.cpp
@@ -2,6 +2,7 @@
#include <QtCore/QSet>
#include <QtCore/QVariant>
#include <QtGui/QColor>
#include <QWKCore/private/qwkwindowsextra_p.h>
#include <QWKCore/private/nativeeventfilter_p.h>
@@ -88,13 +89,7 @@
        const auto hwnd = reinterpret_cast<HWND>(window->winId());
        const DynamicApis &apis = DynamicApis::instance();
        if (key == QStringLiteral("frame-shadow")) {
            if (attribute.toBool()) {
                // TODO: set off
            } else {
                // TODO: set on
            }
        } else if (key == QStringLiteral("mica")) {
        if (key == QStringLiteral("mica")) {
            if (!isWin11OrGreater()) {
                return false;
            }
@@ -151,7 +146,10 @@
            }
            return true;
        } else if (key == QStringLiteral("acrylic-material")) {
            if (attribute.type() == QVariant::Color) {
            if (!isWin10OrGreater()) {
                return false;
            }
            if (attribute.userType() == QMetaType::QColor) {
                // We need to extend the window frame into the whole client area to be able
                // to see the blurred window background.
                static constexpr const MARGINS margins = {-1, -1, -1, -1};
@@ -195,6 +193,48 @@
                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
            }
            return true;
        } else if (key == QStringLiteral("dwm-blur")) {
            if (attribute.toBool()) {
                // We need to extend the window frame into the whole client area to be able
                // to see the blurred window background.
                static constexpr const MARGINS margins = {-1, -1, -1, -1};
                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
                if (isWin8OrGreater()) {
                    ACCENT_POLICY policy{};
                    policy.dwAccentState = ACCENT_ENABLE_BLURBEHIND;
                    policy.dwAccentFlags = ACCENT_NONE;
                    WINDOWCOMPOSITIONATTRIBDATA wcad{};
                    wcad.Attrib = WCA_ACCENT_POLICY;
                    wcad.pvData = &policy;
                    wcad.cbData = sizeof(policy);
                    apis.pSetWindowCompositionAttribute(hwnd, &wcad);
                } else {
                    DWM_BLURBEHIND bb{};
                    bb.fEnable = TRUE;
                    bb.fTransitionOnMaximized = TRUE;
                    bb.dwFlags = DWM_BB_ENABLE | DWM_BB_TRANSITIONONMAXIMIZED;
                    apis.pDwmEnableBlurBehindWindow(hwnd, &bb);
                }
            } else {
                if (isWin8OrGreater()) {
                    ACCENT_POLICY policy{};
                    policy.dwAccentState = ACCENT_DISABLED;
                    policy.dwAccentFlags = ACCENT_NONE;
                    WINDOWCOMPOSITIONATTRIBDATA wcad{};
                    wcad.Attrib = WCA_ACCENT_POLICY;
                    wcad.pvData = &policy;
                    wcad.cbData = sizeof(policy);
                    apis.pSetWindowCompositionAttribute(hwnd, &wcad);
                } else {
                    DWM_BLURBEHIND bb{};
                    bb.fEnable = FALSE;
                    bb.dwFlags = DWM_BB_ENABLE;
                    apis.pDwmEnableBlurBehindWindow(hwnd, &bb);
                }
                static constexpr const MARGINS margins = {0, 0, 0, 0};
                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
            }
            return true;
        }
        return false;
    }