Sine Striker
2023-12-13 44c08f3cc456155b960ca5a115df93109d2202ce
Remove event observer
8个文件已修改
2个文件已删除
349 ■■■■■ 已修改文件
src/core/CMakeLists.txt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/abstractwindowcontext_p.h 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/win32windowcontext.cpp 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/win32windowcontext_p.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/kernel/eventobserver.cpp 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/kernel/eventobserver_p.h 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/kernel/nativeeventfilter.cpp 86 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/kernel/nativeeventfilter_p.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/quick/quickwindowagent_win.cpp 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent_win.cpp 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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
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();
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)) {
        // 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;
    }
}
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;
src/core/kernel/eventobserver.cpp
File was deleted
src/core/kernel/eventobserver_p.h
File was deleted
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);
    NativeEventFilter::NativeEventFilter() : m_dispatcher(nullptr) {
        }
        ~MasterNativeEventFilter() override {
            // The base class removes automatically
    NativeEventFilter::~NativeEventFilter() {
        if (m_dispatcher)
            m_dispatcher->removeNativeEventFilter(this);
        }
        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)) {
    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;
        }
        QVector<NativeEventFilter *> children;
    void NativeEventDispatcher::installNativeEventFilter(NativeEventFilter *filter) {
        if (!filter || filter->m_dispatcher)
            return;
        static MasterNativeEventFilter *instance;
        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;
    };
    MasterNativeEventFilter *MasterNativeEventFilter::instance = nullptr;
    AppMasterNativeEventFilter *AppMasterNativeEventFilter::instance = nullptr;
    NativeEventFilter::NativeEventFilter() {
        if (!MasterNativeEventFilter::instance) {
            MasterNativeEventFilter::instance = new MasterNativeEventFilter();
    AppNativeEventFilter::AppNativeEventFilter() {
        if (!AppMasterNativeEventFilter::instance) {
            AppMasterNativeEventFilter::instance = new AppMasterNativeEventFilter();
        }
        MasterNativeEventFilter::instance->children.append(this);
        AppMasterNativeEventFilter::instance->installNativeEventFilter(this);
    }
    NativeEventFilter::~NativeEventFilter() {
        MasterNativeEventFilter::instance->children.removeOne(this);
        if (MasterNativeEventFilter::instance->children.isEmpty()) {
            delete MasterNativeEventFilter::instance;
            MasterNativeEventFilter::instance = nullptr;
    AppNativeEventFilter::~AppNativeEventFilter() {
        AppMasterNativeEventFilter::instance->removeNativeEventFilter(this);
        if (AppMasterNativeEventFilter::instance->m_nativeEventFilters.isEmpty()) {
            delete AppMasterNativeEventFilter::instance;
            AppMasterNativeEventFilter::instance = nullptr;
        }
    }
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;
    };
}
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;
        }
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);
        }
    }