From e18723d66cf470720c29a9d2848150ea1cbe5450 Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 周四, 14 12月 2023 04:49:35 +0800
Subject: [PATCH] Add example resources

---
 examples/shared/widgetframe/CMakeLists.txt          |    5 
 src/core/contexts/abstractwindowcontext.cpp         |    1 
 src/widgets/widgetwindowagent_win.cpp               |    2 
 examples/mainwindow/CMakeLists.txt                  |    9 
 examples/mainwindow/main.cpp                        |   10 
 examples/shared/resources/window-bar/more-line.svg  |    5 
 examples/shared/widgetframe/windowbutton.h          |   48 ++++
 examples/shared/resources/window-bar.qrc            |   11 +
 examples/mainwindow/mainwindow.h                    |    6 
 examples/shared/resources/window-bar/icon.svg       |   18 +
 examples/shared/widgetframe/windowbutton.cpp        |   92 ++++++++
 examples/shared/resources/window-bar/fullscreen.svg |   11 +
 src/core/contexts/win32windowcontext.cpp            |    1 
 examples/qml/CMakeLists.txt                         |    7 
 examples/shared/resources/window-bar/maximize.svg   |   12 +
 examples/shared/widgetframe/windowbutton_p.h        |   27 ++
 examples/mainwindow/dark-style.qss                  |  153 +++++++++++++
 examples/shared/resources/window-bar/minimize.svg   |   11 +
 examples/shared/resources/window-bar/restore.svg    |   16 +
 examples/mainwindow/mainwindow.qrc                  |    5 
 examples/mainwindow/mainwindow.cpp                  |  170 +++++++++++---
 examples/shared/resources/window-bar/close.svg      |   15 +
 examples/CMakeLists.txt                             |    8 
 23 files changed, 597 insertions(+), 46 deletions(-)

diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 9c7ff52..4b35d4e 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -13,6 +13,10 @@
 
 add_subdirectory(shared)
 
-add_subdirectory(mainwindow)
+if(QWINDOWKIT_BUILD_WIDGETS)
+    add_subdirectory(mainwindow)
+endif()
 
-add_subdirectory(qml)
\ No newline at end of file
+if(QWINDOWKIT_BUILD_QUICK)
+    add_subdirectory(qml)
+endif()
\ No newline at end of file
diff --git a/examples/mainwindow/CMakeLists.txt b/examples/mainwindow/CMakeLists.txt
index 6137ab3..62845fa 100644
--- a/examples/mainwindow/CMakeLists.txt
+++ b/examples/mainwindow/CMakeLists.txt
@@ -3,7 +3,12 @@
 file(GLOB _src *.h *.cpp)
 
 qwk_add_example(${PROJECT_NAME}
-    SOURCES ${_src}
+    SOURCES ${_src} mainwindow.qrc ../shared/resources/window-bar.qrc
     QT_LINKS Core Gui Widgets
     LINKS QWKWidgets WidgetFrame
-)
\ No newline at end of file
+)
+
+set_target_properties(${PROJECT_NAME} PROPERTIES
+    CXX_STANDARD 17
+    CXX_STANDARD_REQUIRED TRUE
+)
diff --git a/examples/mainwindow/dark-style.qss b/examples/mainwindow/dark-style.qss
new file mode 100644
index 0000000..43ea3ee
--- /dev/null
+++ b/examples/mainwindow/dark-style.qss
@@ -0,0 +1,153 @@
+/* Window bar */
+
+QWK--WindowBar[bar-active=true] {
+    background-color: #3C3C3C;
+}
+
+QWK--WindowBar[bar-active=false] {
+    background-color: #505050;
+}
+
+
+/* Title label */
+
+QWK--WindowBar>QLabel#win-title-label {
+    padding: 0;
+    border: none;
+    color: #ECECEC;
+    background-color: transparent;
+}
+
+
+/* System buttons */
+
+QWK--WindowBar>QAbstractButton[system-button=true] {
+    qproperty-iconSize: 12px 12px;
+    min-width: 50px;
+    border: none;
+    padding: 0;
+    background-color: transparent;
+}
+
+QWK--WindowBar>QAbstractButton#min-button {
+    qproperty-iconNormal: url(":/window-bar/minimize.svg");
+    qproperty-iconSize: 12px 12px;
+}
+
+QWK--WindowBar>QAbstractButton#min-button:hover,
+QWK--WindowBar>QAbstractButton#min-button:pressed {
+    background-color: rgba(0, 0, 0, 15%);
+}
+
+QWK--WindowBar>QAbstractButton#max-button {
+    qproperty-iconNormal: url(":/window-bar/maximize.svg");
+    qproperty-iconChecked: url(":/window-bar/restore.svg");
+}
+
+QWK--WindowBar>QAbstractButton#max-button:hover,
+QWK--WindowBar>QAbstractButton#max-button:pressed {
+    background-color: rgba(0, 0, 0, 15%);
+}
+
+QWK--WindowBar>QAbstractButton#close-button {
+    qproperty-iconNormal: url(":/window-bar/close.svg");
+}
+
+QWK--WindowBar>QAbstractButton#close-button:hover,
+QWK--WindowBar>QAbstractButton#close-button:pressed {
+    background-color: #e81123;
+}
+
+
+/* Icon button */
+
+QWK--WindowBar>QAbstractButton#icon-button {
+    qproperty-iconNormal: url(":/window-bar/icon.svg");
+    qproperty-iconSize: 20px 20px;
+    min-width: 40px;
+    border: none;
+    padding: 0;
+    background-color: transparent;
+}
+
+
+/* Menu Bar */
+
+QMenuBar {
+    background-color: transparent;
+    border: none;
+}
+
+QMenuBar>QToolButton#qt_menubar_ext_button {
+    qproperty-icon: url(":/window-bar/more-line.svg");
+}
+
+QMenuBar>QToolButton#qt_menubar_ext_button:hover,
+QMenuBar>QToolButton#qt_menubar_ext_button:pressed {
+    background-color: rgba(255, 255, 255, 10%);
+}
+
+QMenuBar::item {
+    color: #CCCCCC;
+    border: none;
+    padding: 8px 12px;
+}
+
+QMenuBar::item:selected {
+    background-color: rgba(255, 255, 255, 10%);
+}
+
+
+/* Menu */
+
+QMenu {
+    padding: 4px;
+    background: #303030;
+    border: 1.25px solid transparent;
+}
+
+QMenu::indicator {
+    left: 6px;
+    width: 20px;
+    height: 20px;
+}
+
+QMenu::icon {
+    left: 6px;
+}
+
+QMenu::item {
+    background: transparent;
+    color: #CCCCCC;
+    padding: 6px 24px;
+}
+
+QMenu::item:selected {
+    color: white;
+    background-color: #0060C0;
+}
+
+QMenu::item:disabled {
+    color: #666666;
+    background-color: transparent;
+}
+
+QMenu::separator {
+    height: 2px;
+    background-color: #5B5B5B;
+    margin: 6px 0;
+}
+
+
+/* Window */
+
+MainWindow {
+    background-color: #1E1E1E;
+}
+
+QWidget#clock-widget {
+    font-size: 75px;
+    color: #FEFEFE;
+    font-weight: bold;
+    background-color: transparent;
+}
\ No newline at end of file
diff --git a/examples/mainwindow/main.cpp b/examples/mainwindow/main.cpp
index 66f6bee..8813a60 100644
--- a/examples/mainwindow/main.cpp
+++ b/examples/mainwindow/main.cpp
@@ -1,4 +1,5 @@
 #include <QtWidgets/QApplication>
+#include <QtGui/QFont>
 #include <QtCore/QDebug>
 
 #include "mainwindow.h"
@@ -17,6 +18,15 @@
     QGuiApplication::setHighDpiScaleFactorRoundingPolicy(
         Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
     QApplication a(argc, argv);
+
+#ifdef Q_OS_WINDOWS
+    a.setFont([]() {
+        QFont f("Microsoft YaHei");
+        f.setPixelSize(15);
+        return f;
+    }());
+#endif
+
     MainWindow w;
     w.show();
     return a.exec();
diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp
index c18fe5d..882dc9b 100644
--- a/examples/mainwindow/mainwindow.cpp
+++ b/examples/mainwindow/mainwindow.cpp
@@ -1,17 +1,23 @@
 #include "mainwindow.h"
 
 #include <QtCore/QDebug>
+#include <QtCore/QFile>
 #include <QtCore/QTime>
+#include <QtCore/QTimer>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QStyle>
 #include <QtWidgets/QPushButton>
 
 #include <QWKWidgets/widgetwindowagent.h>
 
 #include <widgetframe/windowbar.h>
+#include <widgetframe/windowbutton.h>
 
-class ClockWidget : public QPushButton {
+class ClockWidget : public QLabel {
 public:
-    explicit ClockWidget(QWidget *parent = nullptr) : QPushButton(parent) {
+    explicit ClockWidget(QWidget *parent = nullptr) : QLabel(parent) {
         startTimer(100);
+        setAlignment(Qt::AlignCenter);
     }
 
     ~ClockWidget() override = default;
@@ -24,9 +30,79 @@
 
 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
     installWindowAgent();
+
+    auto clockWidget = new ClockWidget();
+    clockWidget->setObjectName("clock-widget");
+    clockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+    setCentralWidget(clockWidget);
+
+    if (QFile qss(":/dark-style.qss"); qss.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        setStyleSheet(QString::fromUtf8(qss.readAll()));
+    }
+
+    setWindowTitle("Example MainWindow");
+    resize(640, 480);
+}
+
+static inline void emulateLeaveEvent(QWidget *widget) {
+    Q_ASSERT(widget);
+    if (!widget) {
+        return;
+    }
+    QTimer::singleShot(0, widget, [widget]() {
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+        const QScreen *screen = widget->screen();
+#else
+        const QScreen *screen = widget->windowHandle()->screen();
+#endif
+        const QPoint globalPos = QCursor::pos(screen);
+        if (!QRect(widget->mapToGlobal(QPoint{0, 0}), widget->size()).contains(globalPos)) {
+            QCoreApplication::postEvent(widget, new QEvent(QEvent::Leave));
+            if (widget->testAttribute(Qt::WA_Hover)) {
+                const QPoint localPos = widget->mapFromGlobal(globalPos);
+                const QPoint scenePos = widget->window()->mapFromGlobal(globalPos);
+                static constexpr const auto oldPos = QPoint{};
+                const Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
+                const auto event =
+                    new QHoverEvent(QEvent::HoverLeave, scenePos, globalPos, oldPos, modifiers);
+                Q_UNUSED(localPos);
+#elif (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
+                const auto event =  new QHoverEvent(QEvent::HoverLeave, localPos, globalPos, oldPos, modifiers);
+                Q_UNUSED(scenePos);
+#else
+                const auto event =  new QHoverEvent(QEvent::HoverLeave, localPos, oldPos, modifiers);
+                Q_UNUSED(scenePos);
+#endif
+                QCoreApplication::postEvent(widget, event);
+            }
+        }
+    });
 }
 
 MainWindow::~MainWindow() {
+}
+
+bool MainWindow::event(QEvent *event) {
+    switch (event->type()) {
+        case QEvent::WindowActivate: {
+            auto menu = menuWidget();
+            menu->setProperty("bar-active", true);
+            style()->polish(menu);
+            break;
+        }
+
+        case QEvent::WindowDeactivate: {
+            auto menu = menuWidget();
+            menu->setProperty("bar-active", false);
+            style()->polish(menu);
+            break;
+        }
+
+        default:
+            break;
+    }
+    return QMainWindow::event(event);
 }
 
 void MainWindow::installWindowAgent() {
@@ -35,37 +111,45 @@
         qFatal("Frameless handle failed to initialize.");
     }
 
-    auto titleLabel = new QLabel();
-    titleLabel->setAlignment(Qt::AlignCenter);
-
     auto menuBar = []() {
         auto menuBar = new QMenuBar();
-        auto file = new QMenu("File(&F)");
-        file->addAction(new QAction("New(&N)"));
-        file->addAction(new QAction("Open(&O)"));
+        auto file = new QMenu("File(&F)", menuBar);
+        file->addAction(new QAction("New(&N)", menuBar));
+        file->addAction(new QAction("Open(&O)", menuBar));
 
-        auto edit = new QMenu("Edit(&E)");
-        edit->addAction(new QAction("Undo(&U)"));
-        edit->addAction(new QAction("Redo(&R)"));
+        auto edit = new QMenu("Edit(&E)", menuBar);
+        edit->addAction(new QAction("Undo(&U)", menuBar));
+        edit->addAction(new QAction("Redo(&R)", menuBar));
 
         menuBar->addMenu(file);
         menuBar->addMenu(edit);
         return menuBar;
     }();
+    menuBar->setObjectName("win-menu-bar");
 
-    auto iconButton = new QPushButton("I");
-    iconButton->setAttribute(Qt::WA_Hover);
-    iconButton->setMouseTracking(true);
-    auto minButton = new QPushButton("鈥�");
-    minButton->setAttribute(Qt::WA_Hover);
-    minButton->setMouseTracking(true);
-    auto maxButton = new QPushButton("馃棖");
+    auto titleLabel = new QLabel();
+    titleLabel->setAlignment(Qt::AlignCenter);
+    titleLabel->setObjectName("win-title-label");
+
+    auto iconButton = new QWK::WindowButton();
+    iconButton->setObjectName("icon-button");
+    iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+    auto minButton = new QWK::WindowButton();
+    minButton->setObjectName("min-button");
+    minButton->setProperty("system-button", true);
+    minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+    auto maxButton = new QWK::WindowButton();
     maxButton->setCheckable(true);
-    maxButton->setAttribute(Qt::WA_Hover);
-    maxButton->setMouseTracking(true);
-    auto closeButton = new QPushButton("鉁�");
-    closeButton->setAttribute(Qt::WA_Hover);
-    closeButton->setMouseTracking(true);
+    maxButton->setObjectName("max-button");
+    maxButton->setProperty("system-button", true);
+    maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+    auto closeButton = new QWK::WindowButton();
+    closeButton->setObjectName("close-button");
+    closeButton->setProperty("system-button", true);
+    closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
 
     auto windowBar = new QWK::WindowBar();
     windowBar->setIconButton(iconButton);
@@ -83,29 +167,37 @@
     agent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
     agent->setHitTestVisible(menuBar, true);
 
+#ifdef Q_OS_WINDOWS
+    // Emulate Window system menu button behaviors
+    connect(iconButton, &QAbstractButton::clicked, agent, [this, iconButton, agent] {
+        setProperty("double-click-close", false);
+
+        // Pick a suitable time threshold
+        QTimer::singleShot(75, this, [this, iconButton, agent]() {
+            if (property("double-click-close").toBool())
+                return;
+            agent->showSystemMenu(iconButton->mapToGlobal({0, iconButton->height()}));
+        });
+    });
+    connect(iconButton, &QWK::WindowButton::doubleClicked, this, [this]() {
+        setProperty("double-click-close", true);
+        close();
+    });
+#endif
+
     connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
-    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this](bool max) {
+    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this, maxButton](bool max) {
         if (max) {
             showMaximized();
         } else {
             showNormal();
         }
+
+        // It's a Qt issue that if a QAbstractButton::clicked triggers a window's maximization,
+        // the button remains to be hovered until the mouse move. As a result, we need to
+        // manully send leave events to the button.
+        emulateLeaveEvent(maxButton);
     });
     connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
-
-    auto clockWidget = new ClockWidget();
-    clockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-    connect(clockWidget, &QAbstractButton::clicked, this, [this]() {
-        if (!isMaximized()) {
-            showMaximized();
-        } else {
-            showNormal();
-        }
-    });
-
     setMenuWidget(windowBar);
-    setCentralWidget(clockWidget);
-    setWindowTitle("Example MainWindow");
-    // setContentsMargins({0, 1, 0, 0});
-    resize(640, 480);
 }
diff --git a/examples/mainwindow/mainwindow.h b/examples/mainwindow/mainwindow.h
index 46f23d3..cfed3a6 100644
--- a/examples/mainwindow/mainwindow.h
+++ b/examples/mainwindow/mainwindow.h
@@ -4,11 +4,15 @@
 #include <QtWidgets/QMainWindow>
 
 class MainWindow : public QMainWindow {
+    Q_OBJECT
 public:
     explicit MainWindow(QWidget *parent = nullptr);
-    ~MainWindow();
+    ~MainWindow() override;
 
 protected:
+    bool event(QEvent *event) override;
+
+private:
     void installWindowAgent();
 };
 
diff --git a/examples/mainwindow/mainwindow.qrc b/examples/mainwindow/mainwindow.qrc
new file mode 100644
index 0000000..03d122b
--- /dev/null
+++ b/examples/mainwindow/mainwindow.qrc
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>dark-style.qss</file>
+    </qresource>
+</RCC>
\ No newline at end of file
diff --git a/examples/qml/CMakeLists.txt b/examples/qml/CMakeLists.txt
index ed78439..871f04f 100644
--- a/examples/qml/CMakeLists.txt
+++ b/examples/qml/CMakeLists.txt
@@ -6,4 +6,9 @@
     SOURCES ${_src}
     QT_LINKS Core Gui Qml Quick
     LINKS QWKQuick
-)
\ No newline at end of file
+)
+
+set_target_properties(${PROJECT_NAME} PROPERTIES
+    CXX_STANDARD 17
+    CXX_STANDARD_REQUIRED TRUE
+)
diff --git a/examples/shared/resources/window-bar.qrc b/examples/shared/resources/window-bar.qrc
new file mode 100644
index 0000000..894de7f
--- /dev/null
+++ b/examples/shared/resources/window-bar.qrc
@@ -0,0 +1,11 @@
+<RCC>
+    <qresource prefix="/">
+        <file>window-bar/close.svg</file>
+        <file>window-bar/fullscreen.svg</file>
+        <file>window-bar/icon.svg</file>
+        <file>window-bar/maximize.svg</file>
+        <file>window-bar/minimize.svg</file>
+        <file>window-bar/restore.svg</file>
+        <file>window-bar/more-line.svg</file>
+    </qresource>
+</RCC>
diff --git a/examples/shared/resources/window-bar/close.svg b/examples/shared/resources/window-bar/close.svg
new file mode 100644
index 0000000..103d04e
--- /dev/null
+++ b/examples/shared/resources/window-bar/close.svg
@@ -0,0 +1,15 @@
+<svg id="鍥惧眰_1" data-name="鍥惧眰 1" xmlns="http://www.w3.org/2000/svg" width="10.88" height="10.88"
+  viewBox="0 0 10.88 10.88">
+  <defs>
+    <style>
+      .cls-1 {
+        fill: none;
+        stroke: white;
+        stroke-miterlimit: 10;
+        stroke-width: 1.25px;
+      }
+    </style>
+  </defs>
+  <line class="cls-1" x1="0.44" y1="0.44" x2="10.44" y2="10.44" />
+  <line class="cls-1" x1="0.44" y1="10.44" x2="10.44" y2="0.44" />
+</svg>
\ No newline at end of file
diff --git a/examples/shared/resources/window-bar/fullscreen.svg b/examples/shared/resources/window-bar/fullscreen.svg
new file mode 100644
index 0000000..fff0898
--- /dev/null
+++ b/examples/shared/resources/window-bar/fullscreen.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1594017175519"
+    class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1933"
+    xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
+    <defs>
+        <style type="text/css"></style>
+    </defs>
+    <path
+        d="M874.666667 128h-170.666667a21.333333 21.333333 0 0 0 0 42.666667h119.168l-176.917333 176.917333a21.333333 21.333333 0 1 0 30.165333 30.165333L853.333333 200.832V320a21.333333 21.333333 0 0 0 42.666667 0V149.333333a21.333333 21.333333 0 0 0-21.333333-21.333333zM347.584 646.250667L170.666667 823.168V704a21.333333 21.333333 0 0 0-42.666667 0v170.666667a21.333333 21.333333 0 0 0 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 0-42.666667H200.832l176.917333-176.917333a21.333333 21.333333 0 0 0-30.165333-30.165333zM874.666667 682.666667a21.333333 21.333333 0 0 0-21.333334 21.333333v119.168l-176.917333-176.917333a21.333333 21.333333 0 0 0-30.165333 30.165333L823.168 853.333333H704a21.333333 21.333333 0 0 0 0 42.666667h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333zM200.832 170.666667H320a21.333333 21.333333 0 0 0 0-42.666667H149.333333a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667a21.333333 21.333333 0 0 0 42.666667 0V200.832l176.917333 176.917333a21.333333 21.333333 0 0 0 30.165333-30.165333z"
+        fill="#ffffff" p-id="1934"></path>
+</svg>
\ No newline at end of file
diff --git a/examples/shared/resources/window-bar/icon.svg b/examples/shared/resources/window-bar/icon.svg
new file mode 100644
index 0000000..d56bf51
--- /dev/null
+++ b/examples/shared/resources/window-bar/icon.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1597412561411"
+    class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="780"
+    xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
+    <defs>
+        <style type="text/css"></style>
+    </defs>
+    <path d="M512 384m-170.666667 0a170.666667 170.666667 0 1 0 341.333334 0 170.666667 170.666667 0 1 0-341.333334 0Z"
+        fill="#009688" p-id="781"></path>
+    <path d="M341.333333 384h341.333334v128H341.333333z" fill="#E89419" p-id="782"></path>
+    <path
+        d="M661.333333 106.666667v85.333333h-46.933333c-51.2 0-25.6-21.333333-102.4-21.333333V85.333333c76.8 0 51.2 21.333333 102.4 21.333334H661.333333z"
+        fill="#2196F3" p-id="783"></path>
+    <path d="M85.333333 512h853.333334v362.666667H85.333333z" fill="#FFB74D" p-id="784"></path>
+    <path
+        d="M661.333333 725.333333h85.333334v106.666667h-85.333334zM533.333333 725.333333h85.333334v106.666667h-85.333334zM405.333333 725.333333h85.333334v106.666667h-85.333334zM789.333333 725.333333h85.333334v106.666667h-85.333334zM277.333333 725.333333h85.333334v106.666667h-85.333334zM149.333333 725.333333h85.333334v106.666667H149.333333zM661.333333 576h85.333334v106.666667h-85.333334zM533.333333 576h85.333334v106.666667h-85.333334zM405.333333 576h85.333334v106.666667h-85.333334zM618.666667 512h-85.333334v-64c0-23.466667 19.2-42.666667 42.666667-42.666667s42.666667 19.2 42.666667 42.666667v64zM490.666667 512h-85.333334v-64c0-23.466667 19.2-42.666667 42.666667-42.666667s42.666667 19.2 42.666667 42.666667v64zM789.333333 576h85.333334v106.666667h-85.333334zM277.333333 576h85.333334v106.666667h-85.333334zM149.333333 576h85.333334v106.666667H149.333333z"
+        fill="#B07424" p-id="785"></path>
+</svg>
\ No newline at end of file
diff --git a/examples/shared/resources/window-bar/maximize.svg b/examples/shared/resources/window-bar/maximize.svg
new file mode 100644
index 0000000..a50c909
--- /dev/null
+++ b/examples/shared/resources/window-bar/maximize.svg
@@ -0,0 +1,12 @@
+<svg id="鍥惧眰_1" data-name="鍥惧眰 1" xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10">
+  <defs>
+    <style>
+      .cls-1 {
+        fill: none;
+        stroke: white;
+        stroke-miterlimit: 10;
+      }
+    </style>
+  </defs>
+  <rect class="cls-1" x="0.5" y="0.5" width="9" height="9" />
+</svg>
\ No newline at end of file
diff --git a/examples/shared/resources/window-bar/minimize.svg b/examples/shared/resources/window-bar/minimize.svg
new file mode 100644
index 0000000..e4e4bfd
--- /dev/null
+++ b/examples/shared/resources/window-bar/minimize.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="鍥惧眰_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
+	y="0px" viewBox="0 0 10 10" style="enable-background:new 0 0 10 10;" xml:space="preserve">
+	<style type="text/css">
+		.st0 {
+			fill: white;
+		}
+	</style>
+	<rect y="4.5" class="st0" width="10" height="1" />
+</svg>
\ No newline at end of file
diff --git a/examples/shared/resources/window-bar/more-line.svg b/examples/shared/resources/window-bar/more-line.svg
new file mode 100644
index 0000000..246247f
--- /dev/null
+++ b/examples/shared/resources/window-bar/more-line.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
+    <path fill="none" d="M0 0h24v24H0z" />
+    <path fill="white"
+        d="M4.5 10.5c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S6 12.825 6 12s-.675-1.5-1.5-1.5zm15 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S21 12.825 21 12s-.675-1.5-1.5-1.5zm-7.5 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5 1.5-.675 1.5-1.5-.675-1.5-1.5-1.5z" />
+</svg>
\ No newline at end of file
diff --git a/examples/shared/resources/window-bar/restore.svg b/examples/shared/resources/window-bar/restore.svg
new file mode 100644
index 0000000..bb6e245
--- /dev/null
+++ b/examples/shared/resources/window-bar/restore.svg
@@ -0,0 +1,16 @@
+<svg id="鍥惧眰_1" data-name="鍥惧眰 1" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+  <defs>
+    <style>
+      .cls-1 {
+        fill: none;
+        stroke: white;
+        stroke-miterlimit: 10;
+      }
+    </style>
+  </defs>
+  <rect class="cls-1" x="0.5" y="2.5" width="9" height="9" />
+  <line class="cls-1" x1="2.5" y1="2.5" x2="2.5" y2="0.5" />
+  <line class="cls-1" x1="12" y1="0.5" x2="2" y2="0.5" />
+  <line class="cls-1" x1="11.5" y1="10" x2="11.5" />
+  <line class="cls-1" x1="10" y1="9.5" x2="12" y2="9.5" />
+</svg>
\ No newline at end of file
diff --git a/examples/shared/widgetframe/CMakeLists.txt b/examples/shared/widgetframe/CMakeLists.txt
index ccd7aa6..05ac949 100644
--- a/examples/shared/widgetframe/CMakeLists.txt
+++ b/examples/shared/widgetframe/CMakeLists.txt
@@ -13,4 +13,9 @@
     QT_LINKS Core Gui Widgets
 )
 
+set_target_properties(${PROJECT_NAME} PROPERTIES
+    CXX_STANDARD 17
+    CXX_STANDARD_REQUIRED TRUE
+)
+
 target_include_directories(${PROJECT_NAME} PUBLIC . ..)
\ No newline at end of file
diff --git a/examples/shared/widgetframe/windowbutton.cpp b/examples/shared/widgetframe/windowbutton.cpp
new file mode 100644
index 0000000..7d21cb2
--- /dev/null
+++ b/examples/shared/widgetframe/windowbutton.cpp
@@ -0,0 +1,92 @@
+#include "windowbutton.h"
+#include "windowbutton_p.h"
+
+#include <QtCore/QDebug>
+#include <QtGui/QtEvents>
+
+namespace QWK {
+
+    WindowButtonPrivate::WindowButtonPrivate() {
+    }
+
+    WindowButtonPrivate::~WindowButtonPrivate() {
+    }
+
+    void WindowButtonPrivate::init() {
+    }
+
+    void WindowButtonPrivate::reloadIcon() {
+        Q_Q(WindowButton);
+
+        if (!q->isEnabled() && !iconDisabled.isNull()) {
+            q->setIcon(iconDisabled);
+            return;
+        }
+
+        if (q->isChecked() && !iconChecked.isNull()) {
+            q->setIcon(iconChecked);
+            return;
+        }
+
+        if (!iconNormal.isNull()) {
+            q->setIcon(iconNormal);
+        }
+    }
+
+    WindowButton::WindowButton(QWidget *parent) : WindowButton(*new WindowButtonPrivate(), parent) {
+    }
+
+    WindowButton::~WindowButton() = default;
+
+    QIcon WindowButton::iconNormal() const {
+        Q_D(const WindowButton);
+        return d->iconNormal;
+    }
+
+    void WindowButton::setIconNormal(const QIcon &icon) {
+        Q_D(WindowButton);
+        d->iconNormal = icon;
+        d->reloadIcon();
+    }
+
+    QIcon WindowButton::iconChecked() const {
+        Q_D(const WindowButton);
+        return d->iconChecked;
+    }
+
+    void WindowButton::setIconChecked(const QIcon &icon) {
+        Q_D(WindowButton);
+        d->iconChecked = icon;
+        d->reloadIcon();
+    }
+
+    QIcon WindowButton::iconDisabled() const {
+        Q_D(const WindowButton);
+        return d->iconDisabled;
+    }
+
+    void WindowButton::setIconDisabled(const QIcon &icon) {
+        Q_D(WindowButton);
+        d->iconDisabled = icon;
+        d->reloadIcon();
+    }
+
+    void WindowButton::checkStateSet() {
+        Q_D(WindowButton);
+        d->reloadIcon();
+    }
+
+    void WindowButton::mouseDoubleClickEvent(QMouseEvent *event) {
+        if (event->button() == Qt::LeftButton) {
+            Q_EMIT doubleClicked();
+        }
+    }
+
+    WindowButton::WindowButton(WindowButtonPrivate &d, QWidget *parent)
+        : QPushButton(parent), d_ptr(&d) {
+        d.q_ptr = this;
+
+        d.init();
+    }
+
+}
diff --git a/examples/shared/widgetframe/windowbutton.h b/examples/shared/widgetframe/windowbutton.h
new file mode 100644
index 0000000..eb42194
--- /dev/null
+++ b/examples/shared/widgetframe/windowbutton.h
@@ -0,0 +1,48 @@
+#ifndef WINDOWBUTTON_H
+#define WINDOWBUTTON_H
+
+#include "QPushButton.h"
+
+#include <QtGlobal>
+
+namespace QWK {
+
+    class WindowButtonPrivate;
+
+    class WindowButton : public QPushButton {
+        Q_OBJECT
+        Q_DECLARE_PRIVATE(WindowButton)
+        Q_PROPERTY(QIcon iconNormal READ iconNormal WRITE setIconNormal FINAL)
+        Q_PROPERTY(QIcon iconChecked READ iconChecked WRITE setIconChecked FINAL)
+        Q_PROPERTY(QIcon iconDisabled READ iconDisabled WRITE setIconDisabled FINAL)
+    public:
+        explicit WindowButton(QWidget *parent = nullptr);
+        ~WindowButton();
+
+    public:
+        QIcon iconNormal() const;
+        void setIconNormal(const QIcon &icon);
+
+        QIcon iconChecked() const;
+        void setIconChecked(const QIcon &icon);
+
+        QIcon iconDisabled() const;
+        void setIconDisabled(const QIcon &icon);
+
+    Q_SIGNALS:
+        void doubleClicked();
+
+    protected:
+        void checkStateSet() override;
+
+        void mouseDoubleClickEvent(QMouseEvent *event) override;
+
+    protected:
+        WindowButton(WindowButtonPrivate &d, QWidget *parent = nullptr);
+
+        QScopedPointer<WindowButtonPrivate> d_ptr;
+    };
+
+}
+
+#endif // WINDOWBUTTON_H
\ No newline at end of file
diff --git a/examples/shared/widgetframe/windowbutton_p.h b/examples/shared/widgetframe/windowbutton_p.h
new file mode 100644
index 0000000..75c5976
--- /dev/null
+++ b/examples/shared/widgetframe/windowbutton_p.h
@@ -0,0 +1,27 @@
+#ifndef WINDOWBUTTONPRIVATE_H
+#define WINDOWBUTTONPRIVATE_H
+
+#include "windowbutton.h"
+
+namespace QWK {
+
+    class WindowButtonPrivate {
+        Q_DECLARE_PUBLIC(WindowButton)
+    public:
+        WindowButtonPrivate();
+        virtual ~WindowButtonPrivate();
+
+        void init();
+
+        WindowButton *q_ptr;
+
+        QIcon iconNormal;
+        QIcon iconChecked;
+        QIcon iconDisabled;
+
+        void reloadIcon();
+    };
+
+}
+
+#endif // WINDOWBUTTONPRIVATE_H
\ No newline at end of file
diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp
index 2a68081..155f0af 100644
--- a/src/core/contexts/abstractwindowcontext.cpp
+++ b/src/core/contexts/abstractwindowcontext.cpp
@@ -195,6 +195,7 @@
                 map.insert(QStringLiteral("inactiveDark"), kSampleColorSet.inactiveDark);
                 return;
             }
+            
             default:
                 break;
         }
diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 86ec6bd..a2340ac 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -849,6 +849,7 @@
                     QPoint{m_windowHandle->width(), 0}
                 });
                 painter.restore();
+                return;
             }
 
             default: {
diff --git a/src/widgets/widgetwindowagent_win.cpp b/src/widgets/widgetwindowagent_win.cpp
index 2a67ebb..ccac368 100644
--- a/src/widgets/widgetwindowagent_win.cpp
+++ b/src/widgets/widgetwindowagent_win.cpp
@@ -81,7 +81,7 @@
                         &region,
                     };
                     ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook, args);
-                    return true;
+                    break;
                 }
 
                 case QEvent::WindowStateChange: {

--
Gitblit v1.9.1