From 573488a6fec17a9fc71e4d8b0a4741c107ab4ef8 Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 周一, 11 12月 2023 16:35:29 +0800
Subject: [PATCH] Add virtual hook

---
 src/quick/quickwindowagent.h                |   16 +++--
 src/core/contexts/abstractwindowcontext.cpp |    9 ++-
 src/widgets/widgetwindowagent.cpp           |   54 ++++++++++++++++--
 src/core/contexts/abstractwindowcontext_p.h |   18 +++--
 src/widgets/widgetwindowagent.h             |    8 +-
 src/widgets/widgetwindowagent_p.h           |    2 
 src/core/contexts/win32windowcontext.cpp    |   19 ++++++
 src/quick/quickwindowagent.cpp              |   13 ++--
 8 files changed, 105 insertions(+), 34 deletions(-)

diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp
index d60a6c7..e1187fa 100644
--- a/src/core/contexts/abstractwindowcontext.cpp
+++ b/src/core/contexts/abstractwindowcontext.cpp
@@ -61,7 +61,7 @@
     }
 
     bool AbstractWindowContext::setSystemButton(WindowAgentBase::SystemButton button,
-                                                const QObject *obj) {
+                                                QObject *obj) {
         Q_ASSERT(obj);
         Q_ASSERT(button != WindowAgentBase::Unknown);
         if (!obj || (button == WindowAgentBase::Unknown)) {
@@ -75,7 +75,7 @@
         return true;
     }
 
-    bool AbstractWindowContext::setTitleBar(const QObject *item) {
+    bool AbstractWindowContext::setTitleBar(QObject *item) {
         Q_ASSERT(item);
         if (!item) {
             return false;
@@ -170,8 +170,11 @@
 
     void AbstractWindowContext::virtual_hook(int id, void *data) {
         switch (id) {
-            case CentralizeHook:
+            case NeedsDrawBordersHook: {
+                auto &result = *reinterpret_cast<bool *>(data);
+                result = false;
                 break;
+            }
             default:
                 break;
         }
diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h
index fde76b0..a7b6767 100644
--- a/src/core/contexts/abstractwindowcontext_p.h
+++ b/src/core/contexts/abstractwindowcontext_p.h
@@ -29,11 +29,11 @@
         bool setHitTestVisible(const QObject *obj, bool visible);
         bool setHitTestVisible(const QRect &rect, bool visible);
 
-        inline const QObject *systemButton(WindowAgentBase::SystemButton button) const;
-        bool setSystemButton(WindowAgentBase::SystemButton button, const QObject *obj);
+        inline QObject *systemButton(WindowAgentBase::SystemButton button) const;
+        bool setSystemButton(WindowAgentBase::SystemButton button, QObject *obj);
 
-        inline const QObject *titleBar() const;
-        bool setTitleBar(const QObject *obj);
+        inline QObject *titleBar() const;
+        bool setTitleBar(QObject *obj);
 
         void showSystemMenu(const QPoint &pos);
 
@@ -46,6 +46,8 @@
         enum WindowContextHook {
             CentralizeHook = 1,
             ShowSystemMenuHook,
+            NeedsDrawBordersHook,
+            DrawBordersHook,
         };
         virtual void virtual_hook(int id, void *data);
 
@@ -60,8 +62,8 @@
         QSet<const QObject *> m_hitTestVisibleItems;
         QList<QRect> m_hitTestVisibleRects;
 
-        const QObject *m_titleBar{};
-        std::array<const QObject *, WindowAgentBase::NumSystemButton> m_systemButtons{};
+        QObject *m_titleBar{};
+        std::array<QObject *, WindowAgentBase::NumSystemButton> m_systemButtons{};
 
         // Cached shape
         mutable bool hitTestVisibleShapeDirty{};
@@ -80,12 +82,12 @@
         return m_hitTestVisibleItems.contains(obj);
     }
 
-    inline const QObject *
+    inline QObject *
         AbstractWindowContext::systemButton(WindowAgentBase::SystemButton button) const {
         return m_systemButtons[button];
     }
 
-    inline const QObject *AbstractWindowContext::titleBar() const {
+    inline QObject *AbstractWindowContext::titleBar() const {
         return m_titleBar;
     }
 
diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index c1f3dbd..2168e44 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -5,6 +5,7 @@
 #include <QtCore/QHash>
 #include <QtCore/QScopeGuard>
 #include <QtGui/QGuiApplication>
+#include <QtGui/QPainter>
 
 #include <QtCore/private/qsystemlibrary_p.h>
 #include <QtGui/private/qhighdpiscaling_p.h>
@@ -683,6 +684,24 @@
                                 m_delegate->isHostSizeFixed(m_host));
                 return;
             }
+            case NeedsDrawBordersHook: {
+                auto &result = *reinterpret_cast<bool *>(data);
+                result = isWin10OrGreater() && !isWin11OrGreater();
+                return;
+            }
+            case DrawBordersHook: {
+                auto a = reinterpret_cast<void **>(data);
+                auto &painter = *reinterpret_cast<QPainter *>(a[0]);
+                auto &rect = *reinterpret_cast<const QRect *>(a[1]);
+                auto &region = *reinterpret_cast<const QRegion *>(a[2]);
+
+                qDebug() << "paint" << &painter << rect << region;
+
+                // TODO: Draw border
+                // ...
+
+                break;
+            }
             default:
                 break;
         }
diff --git a/src/quick/quickwindowagent.cpp b/src/quick/quickwindowagent.cpp
index 9cee1b5..77ccc9e 100644
--- a/src/quick/quickwindowagent.cpp
+++ b/src/quick/quickwindowagent.cpp
@@ -41,12 +41,12 @@
         return true;
     }
 
-    const QQuickItem *QuickWindowAgent::titleBar() const {
+    QQuickItem *QuickWindowAgent::titleBar() const {
         Q_D(const QuickWindowAgent);
-        return static_cast<const QQuickItem *>(d->context->titleBar());
+        return static_cast<QQuickItem *>(d->context->titleBar());
     }
 
-    void QuickWindowAgent::setTitleBar(const QQuickItem *item) {
+    void QuickWindowAgent::setTitleBar(QQuickItem *item) {
         Q_D(QuickWindowAgent);
         if (!d->context->setTitleBar(item)) {
             return;
@@ -54,12 +54,12 @@
         Q_EMIT titleBarWidgetChanged(item);
     }
 
-    const QQuickItem *QuickWindowAgent::systemButton(SystemButton button) const {
+    QQuickItem *QuickWindowAgent::systemButton(SystemButton button) const {
         Q_D(const QuickWindowAgent);
-        return static_cast<const QQuickItem *>(d->context->systemButton(button));
+        return static_cast<QQuickItem *>(d->context->systemButton(button));
     }
 
-    void QuickWindowAgent::setSystemButton(SystemButton button, const QQuickItem *item) {
+    void QuickWindowAgent::setSystemButton(SystemButton button, QQuickItem *item) {
         Q_D(QuickWindowAgent);
         if (!d->context->setSystemButton(button, item)) {
             return;
@@ -86,4 +86,5 @@
         : WindowAgentBase(d, parent) {
         d.init();
     }
+
 }
diff --git a/src/quick/quickwindowagent.h b/src/quick/quickwindowagent.h
index e2460d4..0d60a7a 100644
--- a/src/quick/quickwindowagent.h
+++ b/src/quick/quickwindowagent.h
@@ -21,16 +21,14 @@
     public:
         Q_INVOKABLE bool setup(QQuickWindow *window);
 
-        Q_INVOKABLE const QQuickItem *titleBar() const;
-        Q_INVOKABLE void setTitleBar(const QQuickItem *item);
+        Q_INVOKABLE QQuickItem *titleBar() const;
+        Q_INVOKABLE void setTitleBar(QQuickItem *item);
 
-        Q_INVOKABLE const QQuickItem *systemButton(SystemButton button) const;
-        Q_INVOKABLE void setSystemButton(SystemButton button, const QQuickItem *item);
+        Q_INVOKABLE QQuickItem *systemButton(SystemButton button) const;
+        Q_INVOKABLE void setSystemButton(SystemButton button, QQuickItem *item);
 
         Q_INVOKABLE bool isHitTestVisible(const QQuickItem *item) const;
-        Q_INVOKABLE inline void setHitTestVisible(const QQuickItem *item, bool visible = true) {
-            setHitTestVisible_item(item, visible);
-        }
+        Q_INVOKABLE inline void setHitTestVisible(const QQuickItem *item, bool visible = true);
         Q_INVOKABLE void setHitTestVisible_item(const QQuickItem *item, bool visible = true);
         Q_INVOKABLE void setHitTestVisible_rect(const QRect &rect, bool visible = true);
 
@@ -42,6 +40,10 @@
         QuickWindowAgent(QuickWindowAgentPrivate &d, QObject *parent = nullptr);
     };
 
+    inline void QuickWindowAgent::setHitTestVisible(const QQuickItem *item, bool visible) {
+        setHitTestVisible_item(item, visible);
+    }
+
 }
 
 #endif // QUICKWINDOWAGENT_H
\ No newline at end of file
diff --git a/src/widgets/widgetwindowagent.cpp b/src/widgets/widgetwindowagent.cpp
index f7d016e..c85f14e 100644
--- a/src/widgets/widgetwindowagent.cpp
+++ b/src/widgets/widgetwindowagent.cpp
@@ -1,9 +1,44 @@
 #include "widgetwindowagent.h"
 #include "widgetwindowagent_p.h"
 
+#include <QtGui/QtEvents>
+#include <QtGui/QPainter>
+
 #include "widgetitemdelegate_p.h"
 
 namespace QWK {
+
+    class WidgetPaintFilter : public QObject {
+    public:
+        WidgetPaintFilter(QWidget *widget, AbstractWindowContext *ctx) : widget(widget), ctx(ctx) {
+            widget->installEventFilter(this);
+        }
+
+    protected:
+        bool eventFilter(QObject *obj, QEvent *event) override {
+            switch (event->type()) {
+                case QEvent::Paint: {
+                    auto e = static_cast<QPaintEvent *>(event);
+                    QPainter painter(widget);
+                    QRect rect = e->rect();
+                    QRegion region = e->region();
+                    void *a[3] = {
+                        &painter,
+                        &rect,
+                        &region,
+                    };
+                    ctx->virtual_hook(AbstractWindowContext::DrawBordersHook, a);
+                    return true;
+                }
+                default:
+                    break;
+            }
+            return false;
+        }
+
+        QWidget *widget;
+        AbstractWindowContext *ctx;
+    };
 
     WidgetWindowAgentPrivate::WidgetWindowAgentPrivate() {
     }
@@ -39,15 +74,22 @@
             return false;
         }
         d->hostWidget = w;
+
+        // Install painting hook
+        if (bool needPaintBorder = false;
+            d->context->virtual_hook(AbstractWindowContext::NeedsDrawBordersHook, &needPaintBorder),
+            needPaintBorder) {
+            d->paintFilter = std::make_unique<WidgetPaintFilter>(w, d->context.get());
+        }
         return true;
     }
 
-    const QWidget *WidgetWindowAgent::titleBar() const {
+    QWidget *WidgetWindowAgent::titleBar() const {
         Q_D(const WidgetWindowAgent);
-        return static_cast<const QWidget *>(d->context->titleBar());
+        return static_cast<QWidget *>(d->context->titleBar());
     }
 
-    void WidgetWindowAgent::setTitleBar(const QWidget *w) {
+    void WidgetWindowAgent::setTitleBar(QWidget *w) {
         Q_D(WidgetWindowAgent);
         if (!d->context->setTitleBar(w)) {
             return;
@@ -55,12 +97,12 @@
         Q_EMIT titleBarWidgetChanged(w);
     }
 
-    const QWidget *WidgetWindowAgent::systemButton(SystemButton button) const {
+    QWidget *WidgetWindowAgent::systemButton(SystemButton button) const {
         Q_D(const WidgetWindowAgent);
-        return static_cast<const QWidget *>(d->context->systemButton(button));
+        return static_cast<QWidget *>(d->context->systemButton(button));
     }
 
-    void WidgetWindowAgent::setSystemButton(SystemButton button, const QWidget *w) {
+    void WidgetWindowAgent::setSystemButton(SystemButton button, QWidget *w) {
         Q_D(WidgetWindowAgent);
         if (!d->context->setSystemButton(button, w)) {
             return;
diff --git a/src/widgets/widgetwindowagent.h b/src/widgets/widgetwindowagent.h
index d13d628..bc092d2 100644
--- a/src/widgets/widgetwindowagent.h
+++ b/src/widgets/widgetwindowagent.h
@@ -20,11 +20,11 @@
     public:
         bool setup(QWidget *w);
 
-        const QWidget *titleBar() const;
-        void setTitleBar(const QWidget *w);
+        QWidget *titleBar() const;
+        void setTitleBar(QWidget *w);
 
-        const QWidget *systemButton(SystemButton button) const;
-        void setSystemButton(SystemButton button, const QWidget *w);
+        QWidget *systemButton(SystemButton button) const;
+        void setSystemButton(SystemButton button, QWidget *w);
 
         bool isHitTestVisible(const QWidget *w) const;
         void setHitTestVisible(const QWidget *w, bool visible = true);
diff --git a/src/widgets/widgetwindowagent_p.h b/src/widgets/widgetwindowagent_p.h
index d433064..758250e 100644
--- a/src/widgets/widgetwindowagent_p.h
+++ b/src/widgets/widgetwindowagent_p.h
@@ -16,6 +16,8 @@
 
         // Host
         QWidget *hostWidget{};
+
+        std::unique_ptr<QObject> paintFilter;
     };
 
 }

--
Gitblit v1.9.1