From 44c08f3cc456155b960ca5a115df93109d2202ce Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 周三, 13 12月 2023 23:22:25 +0800
Subject: [PATCH] Remove event observer

---
 /dev/null                                   |   47 -------
 src/core/contexts/win32windowcontext_p.h    |    3 
 src/widgets/widgetwindowagent_win.cpp       |   38 ++++--
 src/core/kernel/nativeeventfilter.cpp       |  112 ++++++++++++------
 src/core/kernel/nativeeventfilter_p.h       |   34 +++++
 src/core/contexts/abstractwindowcontext_p.h |    6 
 src/core/CMakeLists.txt                     |    2 
 src/quick/quickwindowagent_win.cpp          |   29 +++-
 src/core/contexts/win32windowcontext.cpp    |   62 ++--------
 9 files changed, 171 insertions(+), 162 deletions(-)

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2123a05..718d862 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -12,8 +12,6 @@
     windowagentbase.cpp
     windowitemdelegate_p.h
     windowitemdelegate.cpp
-    kernel/eventobserver_p.h
-    kernel/eventobserver.cpp
     kernel/nativeeventfilter_p.h
     kernel/nativeeventfilter.cpp
     contexts/abstractwindowcontext_p.h
diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h
index 2934b4d..bcc6ae8 100644
--- a/src/core/contexts/abstractwindowcontext_p.h
+++ b/src/core/contexts/abstractwindowcontext_p.h
@@ -5,16 +5,16 @@
 #include <memory>
 
 #include <QtCore/QSet>
+#include <QtGui/QRegion>
 #include <QtGui/QWindow>
-#include <QtGui/QPolygon>
 
 #include <QWKCore/windowagentbase.h>
-#include <QWKCore/private/eventobserver_p.h>
+#include <QWKCore/private/nativeeventfilter_p.h>
 #include <QWKCore/private/windowitemdelegate_p.h>
 
 namespace QWK {
 
-    class QWK_CORE_EXPORT AbstractWindowContext : public QObject, public EventDispatcher {
+    class QWK_CORE_EXPORT AbstractWindowContext : public QObject, public NativeEventDispatcher {
         Q_OBJECT
     public:
         AbstractWindowContext();
diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 3f0ac32..86ec6bd 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -27,7 +27,6 @@
 #include <dwmapi.h>
 #include <timeapi.h>
 
-#include "nativeeventfilter_p.h"
 #include "qwkglobal_p.h"
 
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@@ -635,7 +634,7 @@
     // DefWindowProc(). Consequently, we have to add a global native filter that forwards the result
     // of the hook function, telling Qt whether we have filtered the events before. Since Qt only
     // handles Windows window messages in the main thread, it is safe to do so.
-    class WindowsNativeEventFilter : public NativeEventFilter {
+    class WindowsNativeEventFilter : public AppNativeEventFilter {
     public:
         bool nativeEventFilter(const QByteArray &eventType, void *message,
                                QT_NATIVE_EVENT_RESULT_TYPE *result) override {
@@ -933,10 +932,19 @@
             return true;
         }
 
-        if (themeStuffHandler(hWnd, message, wParam, lParam, result)) {
-            return true;
+        // Forward to native event filter subscribers
+        if (!m_nativeEventFilters.isEmpty()) {
+            MSG msg;
+            msg.hwnd = hWnd;
+            msg.message = message;
+            msg.wParam = wParam;
+            msg.lParam = lParam;
+            QT_NATIVE_EVENT_RESULT_TYPE res = 0;
+            if (dispatch(QByteArrayLiteral("windows_generic_MSG"), &msg, &res)) {
+                *result = LRESULT(res);
+                return true;
+            }
         }
-
         return false; // Not handled
     }
 
@@ -1923,48 +1931,4 @@
         return false;
     }
 
-    bool Win32WindowContext::themeStuffHandler(HWND hWnd, UINT message, WPARAM wParam,
-                                               LPARAM lParam, LRESULT *resul) {
-        switch (message) {
-            case WM_DPICHANGED: {
-                const auto dpiX = UINT(LOWORD(wParam));
-                const auto dpiY = UINT(HIWORD(wParam));
-
-                QEvent e(QEvent::ScreenChangeInternal);
-                dispatch(&e);
-                break;
-            }
-
-            case WM_THEMECHANGED:
-            case WM_SYSCOLORCHANGE: {
-                QEvent e(QEvent::UpdateLater);
-                dispatch(&e);
-                break;
-            }
-
-            case WM_DWMCOLORIZATIONCOLORCHANGED: {
-                const QColor color = QColor::fromRgba(wParam);
-                const auto blendedWithOpacity = *reinterpret_cast<LPBOOL>(lParam);
-
-                QEvent e(QEvent::UpdateLater);
-                dispatch(&e);
-                break;
-            }
-
-            case WM_SETTINGCHANGE: {
-                if (!wParam && lParam &&
-                    std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0) {
-                    const QColor color = getAccentColor();
-
-                    QEvent e(QEvent::UpdateLater);
-                    dispatch(&e);
-                }
-                break;
-            }
-
-            default:
-                break;
-        }
-        return false;
-    }
 }
diff --git a/src/core/contexts/win32windowcontext_p.h b/src/core/contexts/win32windowcontext_p.h
index ce51265..9303938 100644
--- a/src/core/contexts/win32windowcontext_p.h
+++ b/src/core/contexts/win32windowcontext_p.h
@@ -51,9 +51,6 @@
         bool nonClientCalcSizeHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
                                       LRESULT *result);
 
-        bool themeStuffHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
-                               LRESULT *resul);
-
     protected:
         WId windowId = 0;
 
diff --git a/src/core/kernel/eventobserver.cpp b/src/core/kernel/eventobserver.cpp
deleted file mode 100644
index 98b8fcc..0000000
--- a/src/core/kernel/eventobserver.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "eventobserver_p.h"
-
-namespace QWK {
-
-    EventObserver::EventObserver() : m_dispatcher(nullptr) {
-    }
-
-    EventObserver::~EventObserver() {
-        if (m_dispatcher)
-            m_dispatcher->removeObserver(this);
-    }
-
-    EventDispatcher::EventDispatcher() = default;
-
-    EventDispatcher::~EventDispatcher() {
-        for (const auto &observer : std::as_const(m_observers)) {
-            observer->m_dispatcher = nullptr;
-        }
-    }
-
-    bool EventDispatcher::dispatch(QEvent *event) {
-        for (const auto &observer : std::as_const(m_observers)) {
-            if (observer->observe(event))
-                return true;
-        }
-        return true;
-    }
-
-    void EventDispatcher::addObserver(EventObserver *observer) {
-        if (!observer || observer->m_dispatcher)
-            return;
-
-        m_observers.append(observer);
-        observer->m_dispatcher = this;
-    }
-
-    void EventDispatcher::removeObserver(EventObserver *observer) {
-        if (!m_observers.removeOne(observer)) {
-            return;
-        }
-        observer->m_dispatcher = nullptr;
-    }
-
-}
\ No newline at end of file
diff --git a/src/core/kernel/eventobserver_p.h b/src/core/kernel/eventobserver_p.h
deleted file mode 100644
index 558b549..0000000
--- a/src/core/kernel/eventobserver_p.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef EVENTFILTER_P_H
-#define EVENTFILTER_P_H
-
-#include <QtGui/QtEvents>
-
-#include <QWKCore/qwkglobal.h>
-
-namespace QWK {
-
-    class EventDispatcher;
-
-    class QWK_CORE_EXPORT EventObserver {
-    public:
-        EventObserver();
-        virtual ~EventObserver();
-
-    protected:
-        virtual bool observe(QEvent *event) = 0;
-
-    protected:
-        EventDispatcher *m_dispatcher;
-
-        Q_DISABLE_COPY(EventObserver)
-
-        friend class EventDispatcher;
-    };
-
-    class QWK_CORE_EXPORT EventDispatcher {
-    public:
-        EventDispatcher();
-        virtual ~EventDispatcher();
-
-        virtual bool dispatch(QEvent *event);
-
-    public:
-        void addObserver(EventObserver *observer);
-        void removeObserver(EventObserver *observer);
-
-    protected:
-        QVector<EventObserver *> m_observers;
-
-        Q_DISABLE_COPY(EventDispatcher)
-    };
-
-}
-
-#endif // EVENTFILTER_P_H
diff --git a/src/core/kernel/nativeeventfilter.cpp b/src/core/kernel/nativeeventfilter.cpp
index 58650db..be5666b 100644
--- a/src/core/kernel/nativeeventfilter.cpp
+++ b/src/core/kernel/nativeeventfilter.cpp
@@ -5,47 +5,83 @@
 
 namespace QWK {
 
-    // Avoid adding multiple global native event filters to QGuiApplication
-    // in this library.
-    class MasterNativeEventFilter : public QAbstractNativeEventFilter {
-    public:
-        MasterNativeEventFilter() {
-            qApp->installNativeEventFilter(this);
-        }
-
-        ~MasterNativeEventFilter() override {
-            // The base class removes automatically
-        }
-
-        bool nativeEventFilter(const QByteArray &eventType, void *message,
-                               QT_NATIVE_EVENT_RESULT_TYPE *result) override {
-            for (const auto &child : std::as_const(children)) {
-                if (child->nativeEventFilter(eventType, message, result)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        QVector<NativeEventFilter *> children;
-
-        static MasterNativeEventFilter *instance;
-    };
-
-    MasterNativeEventFilter *MasterNativeEventFilter::instance = nullptr;
-
-    NativeEventFilter::NativeEventFilter() {
-        if (!MasterNativeEventFilter::instance) {
-            MasterNativeEventFilter::instance = new MasterNativeEventFilter();
-        }
-        MasterNativeEventFilter::instance->children.append(this);
+    NativeEventFilter::NativeEventFilter() : m_dispatcher(nullptr) {
     }
 
     NativeEventFilter::~NativeEventFilter() {
-        MasterNativeEventFilter::instance->children.removeOne(this);
-        if (MasterNativeEventFilter::instance->children.isEmpty()) {
-            delete MasterNativeEventFilter::instance;
-            MasterNativeEventFilter::instance = nullptr;
+        if (m_dispatcher)
+            m_dispatcher->removeNativeEventFilter(this);
+    }
+
+    NativeEventDispatcher::NativeEventDispatcher() = default;
+
+    NativeEventDispatcher::~NativeEventDispatcher() {
+        for (const auto &observer : std::as_const(m_nativeEventFilters)) {
+            observer->m_dispatcher = nullptr;
+        }
+    }
+
+    bool NativeEventDispatcher::dispatch(const QByteArray &eventType, void *message,
+                                         QT_NATIVE_EVENT_RESULT_TYPE *result) {
+        for (const auto &ef : std::as_const(m_nativeEventFilters)) {
+            if (ef->nativeEventFilter(eventType, message, result))
+                return true;
+        }
+        return false;
+    }
+
+    void NativeEventDispatcher::installNativeEventFilter(NativeEventFilter *filter) {
+        if (!filter || filter->m_dispatcher)
+            return;
+
+        m_nativeEventFilters.append(filter);
+        filter->m_dispatcher = this;
+    }
+
+    void NativeEventDispatcher::removeNativeEventFilter(NativeEventFilter *filter) {
+        if (!m_nativeEventFilters.removeOne(filter)) {
+            return;
+        }
+        filter->m_dispatcher = nullptr;
+    }
+
+
+    // Avoid adding multiple global native event filters to QGuiApplication
+    // in this library.
+    class AppMasterNativeEventFilter : public QAbstractNativeEventFilter,
+                                       public NativeEventDispatcher {
+    public:
+        AppMasterNativeEventFilter() {
+            qApp->installNativeEventFilter(this);
+        }
+
+        // The base class removes automatically
+        ~AppMasterNativeEventFilter() override = default;
+
+        bool nativeEventFilter(const QByteArray &eventType, void *message,
+                               QT_NATIVE_EVENT_RESULT_TYPE *result) override {
+            return dispatch(eventType, message, result);
+        }
+
+        static AppMasterNativeEventFilter *instance;
+
+        friend class AppNativeEventFilter;
+    };
+
+    AppMasterNativeEventFilter *AppMasterNativeEventFilter::instance = nullptr;
+
+    AppNativeEventFilter::AppNativeEventFilter() {
+        if (!AppMasterNativeEventFilter::instance) {
+            AppMasterNativeEventFilter::instance = new AppMasterNativeEventFilter();
+        }
+        AppMasterNativeEventFilter::instance->installNativeEventFilter(this);
+    }
+
+    AppNativeEventFilter::~AppNativeEventFilter() {
+        AppMasterNativeEventFilter::instance->removeNativeEventFilter(this);
+        if (AppMasterNativeEventFilter::instance->m_nativeEventFilters.isEmpty()) {
+            delete AppMasterNativeEventFilter::instance;
+            AppMasterNativeEventFilter::instance = nullptr;
         }
     }
 
diff --git a/src/core/kernel/nativeeventfilter_p.h b/src/core/kernel/nativeeventfilter_p.h
index b7ce167..45228df 100644
--- a/src/core/kernel/nativeeventfilter_p.h
+++ b/src/core/kernel/nativeeventfilter_p.h
@@ -5,6 +5,27 @@
 
 namespace QWK {
 
+    class NativeEventFilter;
+
+    class QWK_CORE_EXPORT NativeEventDispatcher {
+    public:
+        NativeEventDispatcher();
+        virtual ~NativeEventDispatcher();
+
+    public:
+        virtual bool dispatch(const QByteArray &eventType, void *message,
+                              QT_NATIVE_EVENT_RESULT_TYPE *result);
+
+    public:
+        void installNativeEventFilter(NativeEventFilter *filter);
+        void removeNativeEventFilter(NativeEventFilter *filter);
+
+    protected:
+        QVector<NativeEventFilter *> m_nativeEventFilters;
+
+        Q_DISABLE_COPY(NativeEventDispatcher)
+    };
+
     class QWK_CORE_EXPORT NativeEventFilter {
     public:
         NativeEventFilter();
@@ -14,8 +35,19 @@
         virtual bool nativeEventFilter(const QByteArray &eventType, void *message,
                                        QT_NATIVE_EVENT_RESULT_TYPE *result) = 0;
 
-    private:
+    protected:
+        NativeEventDispatcher *m_dispatcher;
+
         Q_DISABLE_COPY(NativeEventFilter)
+
+        friend class NativeEventDispatcher;
+    };
+
+    // Automatically install to QApplication at construction
+    class QWK_CORE_EXPORT AppNativeEventFilter : public NativeEventFilter {
+    public:
+        AppNativeEventFilter();
+        ~AppNativeEventFilter() override;
     };
 
 }
diff --git a/src/quick/quickwindowagent_win.cpp b/src/quick/quickwindowagent_win.cpp
index 2049d29..15418e2 100644
--- a/src/quick/quickwindowagent_win.cpp
+++ b/src/quick/quickwindowagent_win.cpp
@@ -3,11 +3,11 @@
 #include <QtQuick/QQuickPaintedItem>
 #include <QtQuick/private/qquickitem_p.h>
 
-#include <QWKCore/private/eventobserver_p.h>
+#include <QWKCore/private/nativeeventfilter_p.h>
 
 namespace QWK {
 
-    class BorderItem : public QQuickPaintedItem, public EventObserver {
+    class BorderItem : public QQuickPaintedItem, public NativeEventFilter {
         Q_OBJECT
     public:
         explicit BorderItem(QQuickItem *parent, AbstractWindowContext *context);
@@ -20,7 +20,8 @@
         void itemChange(ItemChange change, const ItemChangeData &data) override;
 
     protected:
-        bool observe(QEvent *event) override;
+        bool nativeEventFilter(const QByteArray &eventType, void *message,
+                               QT_NATIVE_EVENT_RESULT_TYPE *result) override;
 
         AbstractWindowContext *context;
 
@@ -44,7 +45,7 @@
 
         setZ(10);
 
-        context->addObserver(this);
+        context->installNativeEventFilter(this);
         connect(window(), &QQuickWindow::activeChanged, this,
                 &BorderItem::_q_windowActivityChanged);
         updateGeometry();
@@ -80,13 +81,27 @@
         }
     }
 
-    bool BorderItem::observe(QEvent *event) {
-        switch (event->type()) {
-            case QEvent::UpdateLater: {
+    bool BorderItem::nativeEventFilter(const QByteArray &eventType, void *message,
+                                       QT_NATIVE_EVENT_RESULT_TYPE *result) {
+        Q_UNUSED(eventType)
+        auto msg = reinterpret_cast<const MSG *>(message);
+        switch (msg->message) {
+            case WM_THEMECHANGED:
+            case WM_SYSCOLORCHANGE:
+            case WM_DWMCOLORIZATIONCOLORCHANGED: {
                 update();
                 break;
             }
 
+            case WM_SETTINGCHANGE: {
+                if (!msg->wParam && msg->lParam &&
+                    std::wcscmp(reinterpret_cast<LPCWSTR>(msg->lParam), L"ImmersiveColorSet") ==
+                        0) {
+                    update();
+                }
+                break;
+            }
+
             default:
                 break;
         }
diff --git a/src/widgets/widgetwindowagent_win.cpp b/src/widgets/widgetwindowagent_win.cpp
index d2a49a2..2a67ebb 100644
--- a/src/widgets/widgetwindowagent_win.cpp
+++ b/src/widgets/widgetwindowagent_win.cpp
@@ -2,19 +2,19 @@
 
 #include <QtGui/QPainter>
 
-#include <QWKCore/private/eventobserver_p.h>
+#include <QWKCore/qwindowkit_windows.h>
+#include <QWKCore/private/nativeeventfilter_p.h>
 
 namespace QWK {
 
-    class WidgetBorderHandler : public QObject, public EventObserver {
+    class WidgetBorderHandler : public QObject, public NativeEventFilter {
         Q_OBJECT
     public:
-        explicit WidgetBorderHandler(QWidget *widget, AbstractWindowContext *ctx,
-                                     QObject *parent = nullptr)
-            : QObject(parent), widget(widget), ctx(ctx) {
+        explicit WidgetBorderHandler(QWidget *widget, AbstractWindowContext *ctx)
+            : QObject(ctx), widget(widget), ctx(ctx) {
             widget->installEventFilter(this);
 
-            ctx->addObserver(this);
+            ctx->installNativeEventFilter(this);
             updateGeometry();
         }
 
@@ -32,15 +32,29 @@
         }
 
     protected:
-        bool observe(QEvent *event) override {
-            switch (event->type()) {
-                case QEvent::UpdateLater: {
+        bool nativeEventFilter(const QByteArray &eventType, void *message,
+                               QT_NATIVE_EVENT_RESULT_TYPE *result) override {
+            Q_UNUSED(eventType)
+            auto msg = reinterpret_cast<const MSG *>(message);
+            switch (msg->message) {
+                case WM_DPICHANGED: {
+                    updateGeometry();
+                    break;
+                }
+
+                case WM_THEMECHANGED:
+                case WM_SYSCOLORCHANGE:
+                case WM_DWMCOLORIZATIONCOLORCHANGED: {
                     widget->update();
                     break;
                 }
 
-                case QEvent::ScreenChangeInternal: {
-                    updateGeometry();
+                case WM_SETTINGCHANGE: {
+                    if (!msg->wParam && msg->lParam &&
+                        std::wcscmp(reinterpret_cast<LPCWSTR>(msg->lParam), L"ImmersiveColorSet") ==
+                            0) {
+                        widget->update();
+                    }
                     break;
                 }
 
@@ -95,7 +109,7 @@
         // Install painting hook
         auto ctx = context.get();
         if (ctx->property("needBorderPainter").toBool()) {
-            std::ignore = new WidgetBorderHandler(hostWidget, ctx, ctx);
+            std::ignore = new WidgetBorderHandler(hostWidget, ctx);
         }
     }
 

--
Gitblit v1.9.1