From fd8aca4a20f52f696aa239ead1baa20cea5879f6 Mon Sep 17 00:00:00 2001
From: SineStriker <55847490+SineStriker@users.noreply.github.com>
Date: 周一, 11 12月 2023 14:58:25 +0800
Subject: [PATCH] Merge pull request #2 from stdware/refactor

---
 src/quick/quickwindowagent.h                |    4 
 qmsetup                                     |    2 
 src/core/contexts/abstractwindowcontext_p.h |   23 +
 src/quick/CMakeLists.txt                    |    2 
 src/core/qwkglobal.h                        |   16 +
 src/core/contexts/win32windowcontext.cpp    |   89 ++++++--
 src/core/windowitemdelegate.cpp             |    2 
 src/core/windowitemdelegate_p.h             |    8 
 src/widgets/CMakeLists.txt                  |    2 
 src/core/CMakeLists.txt                     |   16 
 src/quick/quickitemdelegate_p.h             |    2 
 src/core/contexts/qtwindowcontext.cpp       |    9 
 src/core/kernel/nativeeventfilter.h         |   23 ++
 src/widgets/widgetwindowagent.h             |    4 
 src/core/qwkglobal_p.h                      |   18 +
 src/core/windowagentbase_p.h                |   30 +++
 examples/mainwindow/mainwindow.cpp          |    8 
 src/quick/quickwindowagent.cpp              |    7 
 src/widgets/widgetitemdelegate_p.h          |    2 
 src/core/contexts/abstractwindowcontext.cpp |   58 ++---
 src/core/windowagentbase.h                  |   18 
 src/quick/quickwindowagent_p.h              |    6 
 src/core/windowagentbase.cpp                |   86 ++++++++
 src/widgets/widgetwindowagent_p.h           |    6 
 src/core/contexts/qtwindowcontext_p.h       |    4 
 /dev/null                                   |   34 ---
 src/core/contexts/win32windowcontext_p.h    |    3 
 src/widgets/widgetwindowagent.cpp           |    7 
 src/core/kernel/nativeeventfilter.cpp       |   52 +++++
 29 files changed, 373 insertions(+), 168 deletions(-)

diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp
index e0c7151..f98f43f 100644
--- a/examples/mainwindow/mainwindow.cpp
+++ b/examples/mainwindow/mainwindow.cpp
@@ -77,10 +77,10 @@
     windowBar->setHostWidget(this);
 
     agent->setTitleBar(windowBar);
-    agent->setSystemButton(QWK::CoreWindowAgent::WindowIcon, iconButton);
-    agent->setSystemButton(QWK::CoreWindowAgent::Minimize, minButton);
-    agent->setSystemButton(QWK::CoreWindowAgent::Maximize, maxButton);
-    agent->setSystemButton(QWK::CoreWindowAgent::Close, closeButton);
+    agent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
+    agent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
+    agent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
+    agent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
     agent->setHitTestVisible(menuBar, true);
 
     connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
diff --git a/qmsetup b/qmsetup
index 35836d6..c8d69a4 160000
--- a/qmsetup
+++ b/qmsetup
@@ -1 +1 @@
-Subproject commit 35836d6e80f4395f187e58d94e2030b615d757e9
+Subproject commit c8d69a4895784220061c3cf8be5f092da2ac013e
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 654a259..837baa0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -5,13 +5,15 @@
 
 set(_src
     qwkcoreglobal.h
-    qwkcoreglobal_p.h
-    qwkcoreglobal.cpp
-    corewindowagent.h
-    corewindowagent_p.h
-    corewindowagent.cpp
-    windowitemdelegate.h
+    qwkglobal.h
+    qwkglobal_p.h
+    windowagentbase.h
+    windowagentbase_p.h
+    windowagentbase.cpp
+    windowitemdelegate_p.h
     windowitemdelegate.cpp
+    kernel/nativeeventfilter.h
+    kernel/nativeeventfilter.cpp
     contexts/abstractwindowcontext_p.h
     contexts/abstractwindowcontext.cpp
 )
@@ -43,7 +45,7 @@
     LINKS
     QT_LINKS Core Gui
     QT_INCLUDE_PRIVATE Core Gui
-    INCLUDE_PRIVATE contexts
+    INCLUDE_PRIVATE kernel contexts
     PREFIX QWK_CORE
 )
 
diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp
index c33f98c..d60a6c7 100644
--- a/src/core/contexts/abstractwindowcontext.cpp
+++ b/src/core/contexts/abstractwindowcontext.cpp
@@ -8,24 +8,6 @@
 
     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;
@@ -46,14 +28,6 @@
             m_windowHandle = nullptr;
             return false;
         }
-
-        // Install specific event filter
-        host->installEventFilter(new EventFilterForwarder(
-            [](QEvent *event, void *user) {
-                return static_cast<AbstractWindowContext *>(user)->hostEventFilter(event);
-            },
-            this, this));
-
         return true;
     }
 
@@ -86,11 +60,11 @@
         return true;
     }
 
-    bool AbstractWindowContext::setSystemButton(CoreWindowAgent::SystemButton button,
+    bool AbstractWindowContext::setSystemButton(WindowAgentBase::SystemButton button,
                                                 const QObject *obj) {
         Q_ASSERT(obj);
-        Q_ASSERT(button != CoreWindowAgent::Unknown);
-        if (!obj || (button == CoreWindowAgent::Unknown)) {
+        Q_ASSERT(button != WindowAgentBase::Unknown);
+        if (!obj || (button == WindowAgentBase::Unknown)) {
             return false;
         }
 
@@ -115,7 +89,7 @@
     }
 
     void AbstractWindowContext::showSystemMenu(const QPoint &pos) {
-        // ?
+        virtual_hook(ShowSystemMenuHook, &const_cast<QPoint &>(pos));
     }
 
     QRegion AbstractWindowContext::hitTestShape() const {
@@ -130,16 +104,16 @@
     }
 
     bool AbstractWindowContext::isInSystemButtons(const QPoint &pos,
-                                                  CoreWindowAgent::SystemButton *button) const {
-        *button = CoreWindowAgent::Unknown;
-        for (int i = CoreWindowAgent::WindowIcon; i <= CoreWindowAgent::Close; ++i) {
+                                                  WindowAgentBase::SystemButton *button) const {
+        *button = WindowAgentBase::Unknown;
+        for (int i = WindowAgentBase::WindowIcon; i <= WindowAgentBase::Close; ++i) {
             auto currentButton = m_systemButtons[i];
             if (!currentButton || !m_delegate->isVisible(currentButton) ||
                 !m_delegate->isEnabled(currentButton)) {
                 continue;
             }
             if (m_delegate->mapGeometryToScene(currentButton).contains(pos)) {
-                *button = static_cast<CoreWindowAgent::SystemButton>(i);
+                *button = static_cast<WindowAgentBase::SystemButton>(i);
                 return true;
             }
         }
@@ -168,7 +142,7 @@
             return false;
         }
 
-        for (int i = CoreWindowAgent::WindowIcon; i <= CoreWindowAgent::Close; ++i) {
+        for (int i = WindowAgentBase::WindowIcon; i <= WindowAgentBase::Close; ++i) {
             auto currentButton = m_systemButtons[i];
             if (currentButton && m_delegate->isVisible(currentButton) &&
                 m_delegate->isEnabled(currentButton) &&
@@ -190,9 +164,17 @@
         return true;
     }
 
-    bool AbstractWindowContext::hostEventFilter(QEvent *event) {
-        Q_UNUSED(event)
-        return false;
+    QString AbstractWindowContext::key() const {
+        return {};
+    }
+
+    void AbstractWindowContext::virtual_hook(int id, void *data) {
+        switch (id) {
+            case CentralizeHook:
+                break;
+            default:
+                break;
+        }
     }
 
 }
\ No newline at end of file
diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h
index 30ea3c1..fde76b0 100644
--- a/src/core/contexts/abstractwindowcontext_p.h
+++ b/src/core/contexts/abstractwindowcontext_p.h
@@ -8,8 +8,8 @@
 #include <QtGui/QWindow>
 #include <QtGui/QPolygon>
 
-#include <QWKCore/corewindowagent.h>
-#include <QWKCore/windowitemdelegate.h>
+#include <QWKCore/windowagentbase.h>
+#include <QWKCore/private/windowitemdelegate_p.h>
 
 namespace QWK {
 
@@ -29,8 +29,8 @@
         bool setHitTestVisible(const QObject *obj, bool visible);
         bool setHitTestVisible(const QRect &rect, bool visible);
 
-        inline const QObject *systemButton(CoreWindowAgent::SystemButton button) const;
-        bool setSystemButton(CoreWindowAgent::SystemButton button, const QObject *obj);
+        inline const QObject *systemButton(WindowAgentBase::SystemButton button) const;
+        bool setSystemButton(WindowAgentBase::SystemButton button, const QObject *obj);
 
         inline const QObject *titleBar() const;
         bool setTitleBar(const QObject *obj);
@@ -38,12 +38,19 @@
         void showSystemMenu(const QPoint &pos);
 
         QRegion hitTestShape() const;
-        bool isInSystemButtons(const QPoint &pos, CoreWindowAgent::SystemButton *button) const;
+        bool isInSystemButtons(const QPoint &pos, WindowAgentBase::SystemButton *button) const;
         bool isInTitleBarDraggableArea(const QPoint &pos) const;
+
+        virtual QString key() const;
+
+        enum WindowContextHook {
+            CentralizeHook = 1,
+            ShowSystemMenuHook,
+        };
+        virtual void virtual_hook(int id, void *data);
 
     protected:
         virtual bool setupHost() = 0;
-        virtual bool hostEventFilter(QEvent *event);
 
     protected:
         QObject *m_host;
@@ -54,7 +61,7 @@
         QList<QRect> m_hitTestVisibleRects;
 
         const QObject *m_titleBar{};
-        std::array<const QObject *, CoreWindowAgent::NumSystemButton> m_systemButtons{};
+        std::array<const QObject *, WindowAgentBase::NumSystemButton> m_systemButtons{};
 
         // Cached shape
         mutable bool hitTestVisibleShapeDirty{};
@@ -74,7 +81,7 @@
     }
 
     inline const QObject *
-        AbstractWindowContext::systemButton(CoreWindowAgent::SystemButton button) const {
+        AbstractWindowContext::systemButton(WindowAgentBase::SystemButton button) const {
         return m_systemButtons[button];
     }
 
diff --git a/src/core/contexts/qtwindowcontext.cpp b/src/core/contexts/qtwindowcontext.cpp
index 5fa7787..631c7e2 100644
--- a/src/core/contexts/qtwindowcontext.cpp
+++ b/src/core/contexts/qtwindowcontext.cpp
@@ -46,11 +46,14 @@
     QtWindowContext::~QtWindowContext() {
     }
 
-    bool QtWindowContext::setupHost() {
-        return false;
+    QString QtWindowContext::key() const {
+        return "qt";
     }
 
-    bool QtWindowContext::hostEventFilter(QEvent *event) {
+    void QtWindowContext::virtual_hook(int id, void *data) {
+    }
+
+    bool QtWindowContext::setupHost() {
         return false;
     }
 
diff --git a/src/core/contexts/qtwindowcontext_p.h b/src/core/contexts/qtwindowcontext_p.h
index 6046633..6c264d2 100644
--- a/src/core/contexts/qtwindowcontext_p.h
+++ b/src/core/contexts/qtwindowcontext_p.h
@@ -11,9 +11,11 @@
         QtWindowContext();
         ~QtWindowContext();
 
+        QString key() const override;
+        void virtual_hook(int id, void *data) override;
+
     protected:
         bool setupHost() override;
-        bool hostEventFilter(QEvent *event) override;
     };
 
 }
diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 4d08adc..c1f3dbd 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -1,10 +1,8 @@
 #include "win32windowcontext_p.h"
-#include "qwkcoreglobal_p.h"
 
 #include <optional>
 
 #include <QtCore/QHash>
-#include <QtCore/QAbstractNativeEventFilter>
 #include <QtCore/QScopeGuard>
 #include <QtGui/QGuiApplication>
 
@@ -24,6 +22,8 @@
 #include <dwmapi.h>
 #include <timeapi.h>
 #include <versionhelpers.h>
+
+#include "nativeeventfilter.h"
 
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
 Q_DECLARE_METATYPE(QMargins)
@@ -62,7 +62,8 @@
 //            }
 //        };
 //
-// #define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME = DefaultFunc<decltype(&::NAME)>::func
+// #define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME =
+// DefaultFunc<decltype(&::NAME)>::func
 #define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME = nullptr
 
         DYNAMIC_API_DECLARE(DwmFlush);
@@ -78,7 +79,8 @@
 #undef DYNAMIC_API_DECLARE
 
         DynamicApis() {
-#define DYNAMIC_API_RESOLVE(DLL, NAME) p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME))
+#define DYNAMIC_API_RESOLVE(DLL, NAME)                                                             \
+    p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME))
 
             QSystemLibrary user32(QStringLiteral("user32"));
             DYNAMIC_API_RESOLVE(user32, GetDpiForWindow);
@@ -207,7 +209,8 @@
     }
 
     static inline bool isWin11OrGreater() {
-        static const bool result = ::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 22000);
+        static const bool result = ::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10),
+                                                               LOBYTE(_WIN32_WINNT_WIN10), 22000);
         return result;
     }
 
@@ -383,8 +386,8 @@
         apis.ptimeEndPeriod(ms_granularity);
     }
 
-    static inline void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry, const bool fixedSize)
-    {
+    static inline void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry,
+                                       const bool fixedSize) {
         const HMENU hMenu = ::GetSystemMenu(hWnd, FALSE);
         if (!hMenu) {
             // The corresponding window doesn't have a system menu, most likely due to the
@@ -395,8 +398,10 @@
 
         const bool maxOrFull = IsMaximized(hWnd) || isFullScreen(hWnd);
         ::EnableMenuItem(hMenu, SC_CLOSE, (MF_BYCOMMAND | MFS_ENABLED));
-        ::EnableMenuItem(hMenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
-        ::EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
+        ::EnableMenuItem(hMenu, SC_MAXIMIZE,
+                         (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
+        ::EnableMenuItem(hMenu, SC_RESTORE,
+                         (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
         // The first menu item should be selected by default if the menu is brought
         // up by keyboard. I don't know how to pre-select a menu item but it seems
         // highlight can do the job. However, there's an annoying issue if we do
@@ -406,9 +411,11 @@
         // highlight bar will not move accordingly, the OS will generate another
         // highlight bar to indicate the current selected menu item, which will make
         // the menu look kind of weird. Currently I don't know how to fix this issue.
-        ::HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
+        ::HiliteMenuItem(hWnd, hMenu, SC_RESTORE,
+                         (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
         ::EnableMenuItem(hMenu, SC_MINIMIZE, (MF_BYCOMMAND | MFS_ENABLED));
-        ::EnableMenuItem(hMenu, SC_SIZE, (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
+        ::EnableMenuItem(hMenu, SC_SIZE,
+                         (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
         ::EnableMenuItem(hMenu, SC_MOVE, (MF_BYCOMMAND | (maxOrFull ? MFS_DISABLED : MFS_ENABLED)));
 
         // The default menu item will appear in bold font. There can only be one default
@@ -428,7 +435,10 @@
         ::SetMenuDefaultItem(hMenu, defaultItemId, FALSE);
 
         // Popup the system menu at the required position.
-        const auto result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), pos.x, pos.y, 0, hWnd, nullptr);
+        const auto result = ::TrackPopupMenu(
+            hMenu,
+            (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)),
+            pos.x, pos.y, 0, hWnd, nullptr);
 
         // Unhighlight the first menu item after the popup menu is closed, otherwise it will keep
         // highlighting until we unhighlight it manually.
@@ -511,7 +521,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 QAbstractNativeEventFilter {
+    class WindowsNativeEventFilter : public NativeEventFilter {
     public:
         bool nativeEventFilter(const QByteArray &eventType, void *message,
                                QT_NATIVE_EVENT_RESULT_TYPE *result) override {
@@ -546,14 +556,12 @@
                 return;
             }
             instance = new WindowsNativeEventFilter();
-            installNativeEventFilter(instance);
         }
 
         static inline void uninstall() {
             if (!instance) {
                 return;
             }
-            removeNativeEventFilter(instance);
             delete instance;
             instance = nullptr;
         }
@@ -661,6 +669,26 @@
         }
     }
 
+    QString Win32WindowContext::key() const {
+        return "win32";
+    }
+
+    void Win32WindowContext::virtual_hook(int id, void *data) {
+        switch (id) {
+            case ShowSystemMenuHook: {
+                const auto &pos = *reinterpret_cast<const QPoint *>(data);
+                auto winId = m_windowHandle->winId();
+                auto hWnd = reinterpret_cast<HWND>(winId);
+                showSystemMenu2(hWnd, {pos.x(), pos.y()}, false,
+                                m_delegate->isHostSizeFixed(m_host));
+                return;
+            }
+            default:
+                break;
+        }
+        AbstractWindowContext::virtual_hook(id, data);
+    }
+
     bool Win32WindowContext::setupHost() {
         // Install window hook
         auto winId = m_windowHandle->winId();
@@ -728,7 +756,7 @@
         return false; // Not handled
     }
 
-    static constexpr const auto kMessageTag = WPARAM(0x97CCEA99);
+    static constexpr const auto kMessageTag = WPARAM(0xF1C9ADD4);
 
     static inline constexpr bool isTaggedMessage(WPARAM wParam) {
         return (wParam == kMessageTag);
@@ -884,8 +912,9 @@
                     DWORD dwScreenPos = ::GetMessagePos();
                     POINT screenPoint{GET_X_LPARAM(dwScreenPos), GET_Y_LPARAM(dwScreenPos)};
                     ::ScreenToClient(hWnd, &screenPoint);
-                    QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(screenPoint), m_windowHandle);
-                    auto dummy = CoreWindowAgent::Unknown;
+                    QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(screenPoint),
+                                                                          m_windowHandle);
+                    auto dummy = WindowAgentBase::Unknown;
                     if (isInSystemButtons(qtScenePos, &dummy)) {
                         // We must record whether the last WM_MOUSELEAVE was filtered, because if
                         // Qt does not receive this message it will not call TrackMouseEvent()
@@ -1116,13 +1145,14 @@
                 auto clientWidth = RECT_WIDTH(clientRect);
                 auto clientHeight = RECT_HEIGHT(clientRect);
 
-                QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
+                QPoint qtScenePos =
+                    QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
 
                 bool isFixedSize = m_delegate->isHostSizeFixed(m_host);
                 bool isTitleBar = isInTitleBarDraggableArea(qtScenePos);
                 bool dontOverrideCursor = false; // ### TODO
 
-                CoreWindowAgent::SystemButton sysButtonType = CoreWindowAgent::Unknown;
+                WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown;
                 if (!isFixedSize && isInSystemButtons(qtScenePos, &sysButtonType)) {
                     // Firstly, we set the hit test result to a default value to be able to detect
                     // whether we have changed it or not afterwards.
@@ -1166,19 +1196,19 @@
                         // exact role of our button. The Snap Layout feature introduced in Windows
                         // 11 won't work without this.
                         switch (sysButtonType) {
-                            case CoreWindowAgent::WindowIcon:
+                            case WindowAgentBase::WindowIcon:
                                 *result = HTSYSMENU;
                                 break;
-                            case CoreWindowAgent::Help:
+                            case WindowAgentBase::Help:
                                 *result = HTHELP;
                                 break;
-                            case CoreWindowAgent::Minimize:
+                            case WindowAgentBase::Minimize:
                                 *result = HTREDUCE;
                                 break;
-                            case CoreWindowAgent::Maximize:
+                            case WindowAgentBase::Maximize:
                                 *result = HTZOOM;
                                 break;
-                            case CoreWindowAgent::Close:
+                            case WindowAgentBase::Close:
                                 *result = HTCLOSE;
                                 break;
                             default:
@@ -1628,7 +1658,8 @@
             }();
             RECT windowPos{};
             ::GetWindowRect(hWnd, &windowPos);
-            return {static_cast<LONG>(windowPos.left + horizontalOffset), static_cast<LONG>(windowPos.top + verticalOffset)};
+            return {static_cast<LONG>(windowPos.left + horizontalOffset),
+                    static_cast<LONG>(windowPos.top + verticalOffset)};
         };
         bool shouldShowSystemMenu = false;
         bool broughtByKeyboard = false;
@@ -1636,7 +1667,8 @@
         switch (message) {
             case WM_RBUTTONUP: {
                 const POINT nativeLocalPos = getNativePosFromMouse();
-                const QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
+                const QPoint qtScenePos =
+                    QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
                 if (isInTitleBarDraggableArea(qtScenePos)) {
                     shouldShowSystemMenu = true;
                     nativeGlobalPos = nativeLocalPos;
@@ -1675,7 +1707,8 @@
                 break;
         }
         if (shouldShowSystemMenu) {
-            showSystemMenu2(hWnd, nativeGlobalPos, broughtByKeyboard, m_delegate->isHostSizeFixed(m_host));
+            showSystemMenu2(hWnd, nativeGlobalPos, broughtByKeyboard,
+                            m_delegate->isHostSizeFixed(m_host));
             // QPA's internal code will handle system menu events separately, and its
             // behavior is not what we would want to see because it doesn't know our
             // window doesn't have any window frame now, so return early here to avoid
diff --git a/src/core/contexts/win32windowcontext_p.h b/src/core/contexts/win32windowcontext_p.h
index 27b4e1f..a56aac8 100644
--- a/src/core/contexts/win32windowcontext_p.h
+++ b/src/core/contexts/win32windowcontext_p.h
@@ -21,6 +21,9 @@
             TitleBar,
         };
 
+        QString key() const override;
+        void virtual_hook(int id, void *data) override;
+
     protected:
         bool setupHost() override;
 
diff --git a/src/core/corewindowagent.cpp b/src/core/corewindowagent.cpp
deleted file mode 100644
index d5dff5a..0000000
--- a/src/core/corewindowagent.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "corewindowagent.h"
-#include "corewindowagent_p.h"
-
-#include "qwkcoreglobal_p.h"
-
-#ifdef Q_OS_WINDOWS
-#  include "win32windowcontext_p.h"
-#else
-#  include "qtwindowcontext_p.h"
-#endif
-
-Q_LOGGING_CATEGORY(qWindowKitLog, "qwindowkit")
-
-namespace QWK {
-
-    CoreWindowAgentPrivate::CoreWindowAgentPrivate() : q_ptr(nullptr), context(nullptr) {
-    }
-
-    CoreWindowAgentPrivate::~CoreWindowAgentPrivate() = default;
-
-    void CoreWindowAgentPrivate::init() {
-    }
-
-    AbstractWindowContext *CoreWindowAgentPrivate::createContext() const {
-        return
-#ifdef Q_OS_WINDOWS
-            new Win32WindowContext()
-#else
-            new QtWindowContext()
-#endif
-                ;
-    }
-
-
-    bool CoreWindowAgentPrivate::setup(QObject *host, WindowItemDelegate *delegate) {
-        std::unique_ptr<AbstractWindowContext> ctx(createContext());
-        if (!ctx->setup(host, delegate)) {
-            return false;
-        }
-        context = std::move(ctx);
-        return true;
-    }
-
-    CoreWindowAgent::~CoreWindowAgent() = default;
-
-    void CoreWindowAgent::showSystemMenu(const QPoint &pos) {
-        Q_D(CoreWindowAgent);
-        d->context->showSystemMenu(pos);
-    }
-
-    void CoreWindowAgent::startSystemMove(const QPoint &pos) {
-        Q_D(CoreWindowAgent);
-        auto win = d->context->window();
-        if (!win) {
-            return;
-        }
-
-        Q_UNUSED(pos)
-        win->startSystemMove();
-    }
-
-    void CoreWindowAgent::startSystemResize(Qt::Edges edges, const QPoint &pos) {
-        Q_D(CoreWindowAgent);
-        auto win = d->context->window();
-        if (!win) {
-            return;
-        }
-
-        Q_UNUSED(pos)
-        win->startSystemResize(edges);
-    }
-
-    void CoreWindowAgent::centralize() {
-    }
-
-    void CoreWindowAgent::raise() {
-    }
-
-    CoreWindowAgent::CoreWindowAgent(CoreWindowAgentPrivate &d, QObject *parent)
-        : QObject(parent), d_ptr(&d) {
-        d.q_ptr = this;
-
-        d.init();
-    }
-
-}
diff --git a/src/core/corewindowagent_p.h b/src/core/corewindowagent_p.h
deleted file mode 100644
index 7ff6825..0000000
--- a/src/core/corewindowagent_p.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef COREWINDOWAGENTPRIVATE_H
-#define COREWINDOWAGENTPRIVATE_H
-
-#include <QWKCore/corewindowagent.h>
-#include <QWKCore/private/abstractwindowcontext_p.h>
-
-namespace QWK {
-
-    class QWK_CORE_EXPORT CoreWindowAgentPrivate {
-        Q_DECLARE_PUBLIC(CoreWindowAgent)
-    public:
-        CoreWindowAgentPrivate();
-        virtual ~CoreWindowAgentPrivate();
-
-        void init();
-
-        CoreWindowAgent *q_ptr; // no need to initialize
-
-        virtual AbstractWindowContext *createContext() const;
-
-        bool setup(QObject *host, WindowItemDelegate *delegate);
-
-        std::unique_ptr<AbstractWindowContext> context;
-
-        Q_DISABLE_COPY_MOVE(CoreWindowAgentPrivate)
-    };
-
-}
-
-#endif // COREWINDOWAGENTPRIVATE_H
\ No newline at end of file
diff --git a/src/core/kernel/nativeeventfilter.cpp b/src/core/kernel/nativeeventfilter.cpp
new file mode 100644
index 0000000..44a1337
--- /dev/null
+++ b/src/core/kernel/nativeeventfilter.cpp
@@ -0,0 +1,52 @@
+#include "nativeeventfilter.h"
+
+#include <QtCore/QAbstractNativeEventFilter>
+#include <QtCore/QCoreApplication>
+
+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 {
+            qApp->removeNativeEventFilter(this);
+        }
+
+        bool nativeEventFilter(const QByteArray &eventType, void *message,
+                               QT_NATIVE_EVENT_RESULT_TYPE *result) override {
+            for (const auto &child : qAsConst(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() {
+        MasterNativeEventFilter::instance->children.removeOne(this);
+        if (MasterNativeEventFilter::instance->children.isEmpty()) {
+            delete MasterNativeEventFilter::instance;
+            MasterNativeEventFilter::instance = nullptr;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/core/kernel/nativeeventfilter.h b/src/core/kernel/nativeeventfilter.h
new file mode 100644
index 0000000..103c025
--- /dev/null
+++ b/src/core/kernel/nativeeventfilter.h
@@ -0,0 +1,23 @@
+#ifndef NATIVEEVENTFILTER_H
+#define NATIVEEVENTFILTER_H
+
+#include <QWKCore/qwkglobal.h>
+
+namespace QWK {
+
+    class QWK_CORE_EXPORT NativeEventFilter {
+    public:
+        NativeEventFilter();
+        virtual ~NativeEventFilter();
+
+    public:
+        virtual bool nativeEventFilter(const QByteArray &eventType, void *message,
+                                       QT_NATIVE_EVENT_RESULT_TYPE *result) = 0;
+
+    private:
+        Q_DISABLE_COPY(NativeEventFilter)
+    };
+
+}
+
+#endif // NATIVEEVENTFILTER_H
diff --git a/src/core/qwkcoreglobal.cpp b/src/core/qwkcoreglobal.cpp
deleted file mode 100644
index 9047b5d..0000000
--- a/src/core/qwkcoreglobal.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#include "qwkcoreglobal_p.h"
-
-#include <QtCore/QAbstractNativeEventFilter>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QSet>
-
-namespace QWK {
-
-    // Avoid adding multiple global native event filters to QCoreApplication
-    // in this library.
-    class NativeEventFilterManager : public QAbstractNativeEventFilter {
-    public:
-        NativeEventFilterManager() {
-            qApp->installNativeEventFilter(this);
-        }
-
-        ~NativeEventFilterManager() override {
-            qApp->removeNativeEventFilter(this);
-        }
-
-        bool nativeEventFilter(const QByteArray &eventType, void *message,
-                               QT_NATIVE_EVENT_RESULT_TYPE *result) override {
-            for (const auto &child : qAsConst(m_children)) {
-                if (child->nativeEventFilter(eventType, message, result)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        inline int count() const {
-            return m_children.size();
-        }
-
-        inline void addChild(QAbstractNativeEventFilter *child) {
-            m_children.append(child);
-        }
-
-        inline void removeChild(QAbstractNativeEventFilter *child) {
-            m_children.removeOne(child);
-        }
-
-        static NativeEventFilterManager *instance;
-
-    protected:
-        QVector<QAbstractNativeEventFilter *> m_children;
-    };
-
-    NativeEventFilterManager *NativeEventFilterManager::instance = nullptr;
-
-    void installNativeEventFilter(QAbstractNativeEventFilter *eventFilter) {
-        if (!eventFilter) {
-            return;
-        }
-
-        if (!NativeEventFilterManager::instance) {
-            NativeEventFilterManager::instance = new NativeEventFilterManager();
-        }
-        NativeEventFilterManager::instance->addChild(eventFilter);
-    }
-
-    void removeNativeEventFilter(QAbstractNativeEventFilter *eventFilter) {
-        if (!eventFilter || !NativeEventFilterManager::instance) {
-            return;
-        }
-        NativeEventFilterManager::instance->removeChild(eventFilter);
-
-        if (NativeEventFilterManager::instance->count() == 0) {
-            delete NativeEventFilterManager::instance;
-            NativeEventFilterManager::instance = nullptr;
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/src/core/qwkcoreglobal_p.h b/src/core/qwkcoreglobal_p.h
deleted file mode 100644
index d18b54f..0000000
--- a/src/core/qwkcoreglobal_p.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef QWKCOREGLOBAL_P_H
-#define QWKCOREGLOBAL_P_H
-
-#include <QtCore/QEvent>
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QAbstractNativeEventFilter>
-#include <QtGui/QtEvents>
-
-#include <QWKCore/qwkcoreglobal.h>
-
-#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
-using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
-using QT_ENTER_EVENT_TYPE = QEnterEvent;
-#else
-using QT_NATIVE_EVENT_RESULT_TYPE = long;
-using QT_ENTER_EVENT_TYPE = QEvent;
-#endif
-
-QWK_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(qWindowKitLog)
-
-#define QWK_INFO     qCInfo(qWindowKitLog)
-#define QWK_DEBUG    qCDebug(qWindowKitLog)
-#define QWK_WARNING  qCWarning(qWindowKitLog)
-#define QWK_CRITICAL qCCritical(qWindowKitLog)
-#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
-#  define QWK_FATAL qCFatal(qWindowKitLog)
-#endif
-
-
-namespace QWK {
-
-    QWK_CORE_EXPORT void installNativeEventFilter(QAbstractNativeEventFilter *eventFilter);
-
-    QWK_CORE_EXPORT void removeNativeEventFilter(QAbstractNativeEventFilter *eventFilter);
-
-}
-
-#endif // QWKCOREGLOBAL_P_H
diff --git a/src/core/qwkglobal.h b/src/core/qwkglobal.h
new file mode 100644
index 0000000..fb15d4f
--- /dev/null
+++ b/src/core/qwkglobal.h
@@ -0,0 +1,16 @@
+#ifndef QWKGLOBAL_H
+#define QWKGLOBAL_H
+
+#include <QtCore/QEvent>
+
+#include <QWKCore/qwkcoreglobal.h>
+
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
+using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
+using QT_ENTER_EVENT_TYPE = QEnterEvent;
+#else
+using QT_NATIVE_EVENT_RESULT_TYPE = long;
+using QT_ENTER_EVENT_TYPE = QEvent;
+#endif
+
+#endif // QWKGLOBAL_H
diff --git a/src/core/qwkglobal_p.h b/src/core/qwkglobal_p.h
new file mode 100644
index 0000000..1a1f626
--- /dev/null
+++ b/src/core/qwkglobal_p.h
@@ -0,0 +1,18 @@
+#ifndef QWKGLOBAL_P_H
+#define QWKGLOBAL_P_H
+
+#include <QtCore/QLoggingCategory>
+
+#include <QWKCore/qwkcoreglobal.h>
+
+QWK_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(qWindowKitLog)
+
+#define QWK_INFO     qCInfo(qWindowKitLog)
+#define QWK_DEBUG    qCDebug(qWindowKitLog)
+#define QWK_WARNING  qCWarning(qWindowKitLog)
+#define QWK_CRITICAL qCCritical(qWindowKitLog)
+#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
+#  define QWK_FATAL qCFatal(qWindowKitLog)
+#endif
+
+#endif // QWKGLOBAL_P_H
diff --git a/src/core/windowagentbase.cpp b/src/core/windowagentbase.cpp
new file mode 100644
index 0000000..94d1fca
--- /dev/null
+++ b/src/core/windowagentbase.cpp
@@ -0,0 +1,86 @@
+#include "windowagentbase.h"
+#include "windowagentbase_p.h"
+
+#include "qwkglobal_p.h"
+
+#ifdef Q_OS_WINDOWS
+#  include "win32windowcontext_p.h"
+#else
+#  include "qtwindowcontext_p.h"
+#endif
+
+Q_LOGGING_CATEGORY(qWindowKitLog, "qwindowkit")
+
+namespace QWK {
+
+    WindowAgentBasePrivate::WindowAgentBasePrivate() : q_ptr(nullptr), context(nullptr) {
+    }
+
+    WindowAgentBasePrivate::~WindowAgentBasePrivate() = default;
+
+    void WindowAgentBasePrivate::init() {
+    }
+
+    AbstractWindowContext *WindowAgentBasePrivate::createContext() const {
+        return
+#ifdef Q_OS_WINDOWS
+            new Win32WindowContext()
+#else
+            new QtWindowContext()
+#endif
+                ;
+    }
+
+
+    bool WindowAgentBasePrivate::setup(QObject *host, WindowItemDelegate *delegate) {
+        std::unique_ptr<AbstractWindowContext> ctx(createContext());
+        if (!ctx->setup(host, delegate)) {
+            return false;
+        }
+        context = std::move(ctx);
+        return true;
+    }
+
+    WindowAgentBase::~WindowAgentBase() = default;
+
+    void WindowAgentBase::showSystemMenu(const QPoint &pos) {
+        Q_D(WindowAgentBase);
+        d->context->showSystemMenu(pos);
+    }
+
+    void WindowAgentBase::startSystemMove(const QPoint &pos) {
+        Q_D(WindowAgentBase);
+        auto win = d->context->window();
+        if (!win) {
+            return;
+        }
+
+        Q_UNUSED(pos)
+        win->startSystemMove();
+    }
+
+    void WindowAgentBase::startSystemResize(Qt::Edges edges, const QPoint &pos) {
+        Q_D(WindowAgentBase);
+        auto win = d->context->window();
+        if (!win) {
+            return;
+        }
+
+        Q_UNUSED(pos)
+        win->startSystemResize(edges);
+    }
+
+    void WindowAgentBase::centralize() {
+    }
+
+    void WindowAgentBase::raise() {
+    }
+
+    WindowAgentBase::WindowAgentBase(WindowAgentBasePrivate &d, QObject *parent)
+        : QObject(parent), d_ptr(&d) {
+        d.q_ptr = this;
+
+        d.init();
+    }
+
+}
diff --git a/src/core/corewindowagent.h b/src/core/windowagentbase.h
similarity index 62%
rename from src/core/corewindowagent.h
rename to src/core/windowagentbase.h
index 1681acc..1f5e50a 100644
--- a/src/core/corewindowagent.h
+++ b/src/core/windowagentbase.h
@@ -1,5 +1,5 @@
-#ifndef COREWINDOWAGENT_H
-#define COREWINDOWAGENT_H
+#ifndef WINDOWAGENTBASE_H
+#define WINDOWAGENTBASE_H
 
 #include <memory>
 
@@ -9,13 +9,13 @@
 
 namespace QWK {
 
-    class CoreWindowAgentPrivate;
+    class WindowAgentBasePrivate;
 
-    class QWK_CORE_EXPORT CoreWindowAgent : public QObject {
+    class QWK_CORE_EXPORT WindowAgentBase : public QObject {
         Q_OBJECT
-        Q_DECLARE_PRIVATE(CoreWindowAgent)
+        Q_DECLARE_PRIVATE(WindowAgentBase)
     public:
-        ~CoreWindowAgent() override;
+        ~WindowAgentBase() override;
 
         enum SystemButton {
             Unknown,
@@ -36,11 +36,11 @@
         void raise();
 
     protected:
-        explicit CoreWindowAgent(CoreWindowAgentPrivate &d, QObject *parent = nullptr);
+        explicit WindowAgentBase(WindowAgentBasePrivate &d, QObject *parent = nullptr);
 
-        const std::unique_ptr<CoreWindowAgentPrivate> d_ptr;
+        const std::unique_ptr<WindowAgentBasePrivate> d_ptr;
     };
 
 }
 
-#endif // COREWINDOWAGENT_H
\ No newline at end of file
+#endif // WINDOWAGENTBASE_H
\ No newline at end of file
diff --git a/src/core/windowagentbase_p.h b/src/core/windowagentbase_p.h
new file mode 100644
index 0000000..0fffb9c
--- /dev/null
+++ b/src/core/windowagentbase_p.h
@@ -0,0 +1,30 @@
+#ifndef WINDOWAGENTBASEPRIVATE_H
+#define WINDOWAGENTBASEPRIVATE_H
+
+#include <QWKCore/windowagentbase.h>
+#include <QWKCore/private/abstractwindowcontext_p.h>
+
+namespace QWK {
+
+    class QWK_CORE_EXPORT WindowAgentBasePrivate {
+        Q_DECLARE_PUBLIC(WindowAgentBase)
+    public:
+        WindowAgentBasePrivate();
+        virtual ~WindowAgentBasePrivate();
+
+        void init();
+
+        WindowAgentBase *q_ptr; // no need to initialize
+
+        virtual AbstractWindowContext *createContext() const;
+
+        bool setup(QObject *host, WindowItemDelegate *delegate);
+
+        std::unique_ptr<AbstractWindowContext> context;
+
+        Q_DISABLE_COPY_MOVE(WindowAgentBasePrivate)
+    };
+
+}
+
+#endif // WINDOWAGENTBASEPRIVATE_H
\ No newline at end of file
diff --git a/src/core/windowitemdelegate.cpp b/src/core/windowitemdelegate.cpp
index 1539b3f..a460add 100644
--- a/src/core/windowitemdelegate.cpp
+++ b/src/core/windowitemdelegate.cpp
@@ -1,4 +1,4 @@
-#include "windowitemdelegate.h"
+#include "windowitemdelegate_p.h"
 
 namespace QWK {
 
diff --git a/src/core/windowitemdelegate.h b/src/core/windowitemdelegate_p.h
similarity index 86%
rename from src/core/windowitemdelegate.h
rename to src/core/windowitemdelegate_p.h
index 58dba1d..ee47067 100644
--- a/src/core/windowitemdelegate.h
+++ b/src/core/windowitemdelegate_p.h
@@ -1,11 +1,11 @@
-#ifndef WINDOWITEMDELEGATE_H
-#define WINDOWITEMDELEGATE_H
+#ifndef WINDOWITEMDELEGATE_P_H
+#define WINDOWITEMDELEGATE_P_H
 
 #include <QtCore/QObject>
 #include <QtCore/QPoint>
 #include <QtGui/QWindow>
 
-#include <QWKCore/corewindowagent.h>
+#include <QWKCore/qwkcoreglobal.h>
 
 namespace QWK {
 
@@ -34,4 +34,4 @@
 
 }
 
-#endif // WINDOWITEMDELEGATE_H
+#endif // WINDOWITEMDELEGATE_P_H
diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt
index 5d00ff2..0591a42 100644
--- a/src/quick/CMakeLists.txt
+++ b/src/quick/CMakeLists.txt
@@ -10,8 +10,6 @@
     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
deleted file mode 100644
index 4014ef1..0000000
--- a/src/quick/contexts/quickwindowcontext.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#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
deleted file mode 100644
index 9479f3d..0000000
--- a/src/quick/contexts/quickwindowcontext_p.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#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/quick/quickitemdelegate_p.h b/src/quick/quickitemdelegate_p.h
index a63aa71..482d25f 100644
--- a/src/quick/quickitemdelegate_p.h
+++ b/src/quick/quickitemdelegate_p.h
@@ -4,7 +4,7 @@
 #include <QtCore/QObject>
 #include <QtGui/QWindow>
 
-#include <QWKCore/windowitemdelegate.h>
+#include <QWKCore/private/windowitemdelegate_p.h>
 #include <QWKQuick/qwkquickglobal.h>
 
 namespace QWK {
diff --git a/src/quick/quickwindowagent.cpp b/src/quick/quickwindowagent.cpp
index be70ca6..7fc72f5 100644
--- a/src/quick/quickwindowagent.cpp
+++ b/src/quick/quickwindowagent.cpp
@@ -4,7 +4,6 @@
 #include <QtQuick/QQuickWindow>
 
 #include "quickitemdelegate_p.h"
-#include "quickwindowcontext_p.h"
 
 namespace QWK {
 
@@ -15,10 +14,6 @@
     }
 
     void QuickWindowAgentPrivate::init() {
-    }
-
-    AbstractWindowContext *QuickWindowAgentPrivate::createContext() const {
-        return new QuickWindowContext();
     }
 
     QuickWindowAgent::QuickWindowAgent(QObject *parent)
@@ -88,7 +83,7 @@
     }
 
     QuickWindowAgent::QuickWindowAgent(QuickWindowAgentPrivate &d, QObject *parent)
-        : CoreWindowAgent(d, parent) {
+        : WindowAgentBase(d, parent) {
         d.init();
     }
 }
diff --git a/src/quick/quickwindowagent.h b/src/quick/quickwindowagent.h
index 53e8652..714ffcf 100644
--- a/src/quick/quickwindowagent.h
+++ b/src/quick/quickwindowagent.h
@@ -4,14 +4,14 @@
 #include <QtQuick/QQuickItem>
 #include <QtQuick/QQuickWindow>
 
-#include <QWKCore/corewindowagent.h>
+#include <QWKCore/windowagentbase.h>
 #include <QWKQuick/qwkquickglobal.h>
 
 namespace QWK {
 
     class QuickWindowAgentPrivate;
 
-    class QWK_QUICK_EXPORT QuickWindowAgent : public CoreWindowAgent {
+    class QWK_QUICK_EXPORT QuickWindowAgent : public WindowAgentBase {
         Q_OBJECT
         Q_DECLARE_PRIVATE(QuickWindowAgent)
     public:
diff --git a/src/quick/quickwindowagent_p.h b/src/quick/quickwindowagent_p.h
index d1e7eb4..243f534 100644
--- a/src/quick/quickwindowagent_p.h
+++ b/src/quick/quickwindowagent_p.h
@@ -1,20 +1,18 @@
 #ifndef QUICKWINDOWAGENTPRIVATE_H
 #define QUICKWINDOWAGENTPRIVATE_H
 
-#include <QWKCore/private/corewindowagent_p.h>
+#include <QWKCore/private/windowagentbase_p.h>
 #include <QWKQuick/quickwindowagent.h>
 
 namespace QWK {
 
-    class QuickWindowAgentPrivate : public CoreWindowAgentPrivate {
+    class QuickWindowAgentPrivate : public WindowAgentBasePrivate {
         Q_DECLARE_PUBLIC(QuickWindowAgent)
     public:
         QuickWindowAgentPrivate();
         ~QuickWindowAgentPrivate() override;
 
         void init();
-
-        AbstractWindowContext * createContext() const override;
 
         // Host
         QQuickWindow *hostWindow{};
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index 91119c8..4153460 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -10,8 +10,6 @@
     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
deleted file mode 100644
index 3aa91f2..0000000
--- a/src/widgets/contexts/widgetwindowcontext.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#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
deleted file mode 100644
index ce50acc..0000000
--- a/src/widgets/contexts/widgetwindowcontext_p.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#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
diff --git a/src/widgets/widgetitemdelegate_p.h b/src/widgets/widgetitemdelegate_p.h
index 1056f35..d04bfac 100644
--- a/src/widgets/widgetitemdelegate_p.h
+++ b/src/widgets/widgetitemdelegate_p.h
@@ -4,7 +4,7 @@
 #include <QtCore/QObject>
 #include <QtGui/QWindow>
 
-#include <QWKCore/windowitemdelegate.h>
+#include <QWKCore/private/windowitemdelegate_p.h>
 #include <QWKWidgets/qwkwidgetsglobal.h>
 
 namespace QWK {
diff --git a/src/widgets/widgetwindowagent.cpp b/src/widgets/widgetwindowagent.cpp
index b183951..f7d016e 100644
--- a/src/widgets/widgetwindowagent.cpp
+++ b/src/widgets/widgetwindowagent.cpp
@@ -2,7 +2,6 @@
 #include "widgetwindowagent_p.h"
 
 #include "widgetitemdelegate_p.h"
-#include "widgetwindowcontext_p.h"
 
 namespace QWK {
 
@@ -13,10 +12,6 @@
     }
 
     void WidgetWindowAgentPrivate::init() {
-    }
-
-    AbstractWindowContext *WidgetWindowAgentPrivate::createContext() const {
-        return new WidgetWindowContext();
     }
 
     WidgetWindowAgent::WidgetWindowAgent(QObject *parent)
@@ -89,7 +84,7 @@
     }
 
     WidgetWindowAgent::WidgetWindowAgent(WidgetWindowAgentPrivate &d, QObject *parent)
-        : CoreWindowAgent(d, parent) {
+        : WindowAgentBase(d, parent) {
         d.init();
     }
 }
diff --git a/src/widgets/widgetwindowagent.h b/src/widgets/widgetwindowagent.h
index cec5a88..d13d628 100644
--- a/src/widgets/widgetwindowagent.h
+++ b/src/widgets/widgetwindowagent.h
@@ -3,14 +3,14 @@
 
 #include <QtWidgets/QWidget>
 
-#include <QWKCore/corewindowagent.h>
+#include <QWKCore/windowagentbase.h>
 #include <QWKWidgets/qwkwidgetsglobal.h>
 
 namespace QWK {
 
     class WidgetWindowAgentPrivate;
 
-    class QWK_WIDGETS_EXPORT WidgetWindowAgent : public CoreWindowAgent {
+    class QWK_WIDGETS_EXPORT WidgetWindowAgent : public WindowAgentBase {
         Q_OBJECT
         Q_DECLARE_PRIVATE(WidgetWindowAgent)
     public:
diff --git a/src/widgets/widgetwindowagent_p.h b/src/widgets/widgetwindowagent_p.h
index 3a4e682..d433064 100644
--- a/src/widgets/widgetwindowagent_p.h
+++ b/src/widgets/widgetwindowagent_p.h
@@ -1,20 +1,18 @@
 #ifndef WIDGETWINDOWAGENTPRIVATE_H
 #define WIDGETWINDOWAGENTPRIVATE_H
 
-#include <QWKCore/private/corewindowagent_p.h>
+#include <QWKCore/private/windowagentbase_p.h>
 #include <QWKWidgets/widgetwindowagent.h>
 
 namespace QWK {
 
-    class WidgetWindowAgentPrivate : public CoreWindowAgentPrivate {
+    class WidgetWindowAgentPrivate : public WindowAgentBasePrivate {
         Q_DECLARE_PUBLIC(WidgetWindowAgent)
     public:
         WidgetWindowAgentPrivate();
         ~WidgetWindowAgentPrivate();
 
         void init();
-
-        AbstractWindowContext * createContext() const override;
 
         // Host
         QWidget *hostWidget{};

--
Gitblit v1.9.1