From 09287f3d9e9e88271de2bfd5388dae5a53e8c6f5 Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 摹曛, 07 12月 2023 15:03:24 +0800
Subject: [PATCH] Add host event filter

---
 src/core/contexts/abstractwindowcontext.cpp  |   38 ++++++++++++
 src/core/contexts/win32windowcontext_p.h     |    5 +
 src/widgets/contexts/widgetwindowcontext_p.h |   34 +++++++++++
 src/quick/contexts/quickwindowcontext.cpp    |    9 +++
 src/widgets/CMakeLists.txt                   |    2 
 src/core/contexts/abstractwindowcontext_p.h  |    6 +
 src/quick/CMakeLists.txt                     |    2 
 src/core/contexts/qtwindowcontext.cpp        |    9 +--
 src/quick/contexts/quickwindowcontext_p.h    |   34 +++++++++++
 src/widgets/contexts/widgetwindowcontext.cpp |    9 +++
 src/core/contexts/qtwindowcontext_p.h        |    6 -
 src/core/contexts/win32windowcontext.cpp     |    6 -
 12 files changed, 142 insertions(+), 18 deletions(-)

diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp
index 679a9ee..c7a5c85 100644
--- a/src/core/contexts/abstractwindowcontext.cpp
+++ b/src/core/contexts/abstractwindowcontext.cpp
@@ -8,6 +8,24 @@
 
     AbstractWindowContext::~AbstractWindowContext() = default;
 
+    class EventFilterForwarder : public QObject {
+    public:
+        using EventProc = bool (*)(QEvent *, void *);
+
+        EventFilterForwarder(EventProc proc, void *user, QObject *parent = nullptr)
+            : QObject(parent), proc(proc), user(user) {
+        }
+
+        bool eventFilter(QObject *obj, QEvent *event) override {
+            Q_UNUSED(obj)
+            return proc(event, user);
+        }
+
+    protected:
+        EventProc proc;
+        void *user;
+    };
+
     bool AbstractWindowContext::setup(QObject *host, WindowItemDelegate *delegate) {
         if (!host || !delegate) {
             return false;
@@ -21,6 +39,21 @@
         m_host = host;
         m_delegate.reset(delegate);
         m_windowHandle = windowHandle;
+
+        if (!setupHost()) {
+            m_host = nullptr;
+            m_delegate = nullptr;
+            m_windowHandle = nullptr;
+            return false;
+        }
+
+        // Install specific event filter
+        host->installEventFilter(new EventFilterForwarder(
+            [](QEvent *event, void *user) {
+                return reinterpret_cast<AbstractWindowContext *>(user)->hostEventFilter(event);
+            },
+            this, this));
+
         return true;
     }
 
@@ -157,4 +190,9 @@
         return true;
     }
 
+    bool AbstractWindowContext::hostEventFilter(QEvent *event) {
+        Q_UNUSED(event)
+        return false;
+    }
+
 }
\ No newline at end of file
diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h
index a73f7c4..30ea3c1 100644
--- a/src/core/contexts/abstractwindowcontext_p.h
+++ b/src/core/contexts/abstractwindowcontext_p.h
@@ -20,7 +20,7 @@
         ~AbstractWindowContext() override;
 
     public:
-        virtual bool setup(QObject *host, WindowItemDelegate *delegate);
+        bool setup(QObject *host, WindowItemDelegate *delegate);
 
         inline QObject *host() const;
         inline QWindow *window() const;
@@ -42,6 +42,10 @@
         bool isInTitleBarDraggableArea(const QPoint &pos) const;
 
     protected:
+        virtual bool setupHost() = 0;
+        virtual bool hostEventFilter(QEvent *event);
+
+    protected:
         QObject *m_host;
         std::unique_ptr<WindowItemDelegate> m_delegate;
         QWindow *m_windowHandle;
diff --git a/src/core/contexts/qtwindowcontext.cpp b/src/core/contexts/qtwindowcontext.cpp
index 4f4764e..5fa7787 100644
--- a/src/core/contexts/qtwindowcontext.cpp
+++ b/src/core/contexts/qtwindowcontext.cpp
@@ -46,15 +46,12 @@
     QtWindowContext::~QtWindowContext() {
     }
 
-    bool QtWindowContext::setup(QObject *host, WindowItemDelegate *delegate) {
-        if (!AbstractWindowContext::setup(host, delegate)) {
-            return false;
-        }
+    bool QtWindowContext::setupHost() {
         return false;
     }
 
-    bool QtWindowContext::eventFilter(QObject *obj, QEvent *event) {
-        return AbstractWindowContext::eventFilter(obj, event);
+    bool QtWindowContext::hostEventFilter(QEvent *event) {
+        return false;
     }
 
 }
\ No newline at end of file
diff --git a/src/core/contexts/qtwindowcontext_p.h b/src/core/contexts/qtwindowcontext_p.h
index 242dcd2..6046633 100644
--- a/src/core/contexts/qtwindowcontext_p.h
+++ b/src/core/contexts/qtwindowcontext_p.h
@@ -11,11 +11,9 @@
         QtWindowContext();
         ~QtWindowContext();
 
-    public:
-        bool setup(QObject *host, WindowItemDelegate *delegate) override;
-
     protected:
-        bool eventFilter(QObject *obj, QEvent *event) override;
+        bool setupHost() override;
+        bool hostEventFilter(QEvent *event) override;
     };
 
 }
diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 538188d..c5c1cbd 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -525,11 +525,7 @@
         }
     }
 
-    bool Win32WindowContext::setup(QObject *host, WindowItemDelegate *delegate) {
-        if (!AbstractWindowContext::setup(host, delegate)) {
-            return false;
-        }
-
+    bool Win32WindowContext::setupHost() {
         // Install window hook
         auto winId = m_windowHandle->winId();
         auto hWnd = reinterpret_cast<HWND>(winId);
diff --git a/src/core/contexts/win32windowcontext_p.h b/src/core/contexts/win32windowcontext_p.h
index 0d7b14b..dd506aa 100644
--- a/src/core/contexts/win32windowcontext_p.h
+++ b/src/core/contexts/win32windowcontext_p.h
@@ -21,9 +21,10 @@
             TitleBar,
         };
 
-    public:
-        bool setup(QObject *host, WindowItemDelegate *delegate) override;
+    protected:
+        bool setupHost() override;
 
+    public:
         bool windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
 
         // In order to perfectly apply Windows 11 Snap Layout into the Qt window, we need to
diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt
index f5feb3e..7381738 100644
--- a/src/quick/CMakeLists.txt
+++ b/src/quick/CMakeLists.txt
@@ -10,6 +10,8 @@
     quickwindowagent.h
     quickwindowagent_p.h
     quickwindowagent.cpp
+    contexts/quickwindowcontext_p.h
+    contexts/quickwindowcontext.cpp
 )
 
 qwk_add_library(${PROJECT_NAME} AUTOGEN
diff --git a/src/quick/contexts/quickwindowcontext.cpp b/src/quick/contexts/quickwindowcontext.cpp
new file mode 100644
index 0000000..4014ef1
--- /dev/null
+++ b/src/quick/contexts/quickwindowcontext.cpp
@@ -0,0 +1,9 @@
+#include "quickwindowcontext_p.h"
+
+namespace QWK {
+
+    bool QuickWindowContext::hostEventFilter(QEvent *event) {
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/src/quick/contexts/quickwindowcontext_p.h b/src/quick/contexts/quickwindowcontext_p.h
new file mode 100644
index 0000000..9479f3d
--- /dev/null
+++ b/src/quick/contexts/quickwindowcontext_p.h
@@ -0,0 +1,34 @@
+#ifndef QUICKWINDOWCONTEXT_P_H
+#define QUICKWINDOWCONTEXT_P_H
+
+#include <QtGlobal>
+
+#ifdef Q_OS_WINDOWS
+#  include <QWKCore/private/win32windowcontext_p.h>
+#else
+#  include <QWKCore/private/qtwindowcontext_p.h>
+#endif
+
+namespace QWK {
+
+    using CoreWindowContext =
+#ifdef Q_OS_WINDOWS
+        Win32WindowContext
+#else
+        QtWindowContext
+#endif
+        ;
+
+    class QuickWindowContext : public CoreWindowContext {
+        Q_OBJECT
+    public:
+        QuickWindowContext() = default;
+        ~QuickWindowContext() override = default;
+
+    protected:
+        bool hostEventFilter(QEvent *event) override;
+    };
+
+}
+
+#endif // QUICKWINDOWCONTEXT_P_H
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index 8543997..f74a6b0 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -10,6 +10,8 @@
     widgetwindowagent.h
     widgetwindowagent_p.h
     widgetwindowagent.cpp
+    contexts/widgetwindowcontext_p.h
+    contexts/widgetwindowcontext.cpp
 )
 
 qwk_add_library(${PROJECT_NAME} AUTOGEN
diff --git a/src/widgets/contexts/widgetwindowcontext.cpp b/src/widgets/contexts/widgetwindowcontext.cpp
new file mode 100644
index 0000000..3aa91f2
--- /dev/null
+++ b/src/widgets/contexts/widgetwindowcontext.cpp
@@ -0,0 +1,9 @@
+#include "widgetwindowcontext_p.h"
+
+namespace QWK {
+
+    bool WidgetWindowContext::hostEventFilter(QEvent *event) {
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/src/widgets/contexts/widgetwindowcontext_p.h b/src/widgets/contexts/widgetwindowcontext_p.h
new file mode 100644
index 0000000..ce50acc
--- /dev/null
+++ b/src/widgets/contexts/widgetwindowcontext_p.h
@@ -0,0 +1,34 @@
+#ifndef WIDGETWINDOWCONTEXT_P_H
+#define WIDGETWINDOWCONTEXT_P_H
+
+#include <QtGlobal>
+
+#ifdef Q_OS_WINDOWS
+#  include <QWKCore/private/win32windowcontext_p.h>
+#else
+#  include <QWKCore/private/qtwindowcontext_p.h>
+#endif
+
+namespace QWK {
+
+    using CoreWindowContext =
+#ifdef Q_OS_WINDOWS
+        Win32WindowContext
+#else
+        QtWindowContext
+#endif
+        ;
+
+    class WidgetWindowContext : public CoreWindowContext {
+        Q_OBJECT
+    public:
+        WidgetWindowContext() = default;
+        ~WidgetWindowContext() override = default;
+
+    protected:
+        bool hostEventFilter(QEvent *event) override;
+    };
+
+}
+
+#endif // WIDGETWINDOWCONTEXT_P_H

--
Gitblit v1.9.1