From 9e999fe2a190a8ebdb0428da16be4975ad077764 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sun, 31 Jan 2021 14:12:02 +0200 Subject: [PATCH] x11: Move event filter logic to kwinApp() This allows the X11 platform plugin to create event filters before the workspace object is created. --- src/events.cpp | 117 ---------------------------------- src/main.cpp | 141 ++++++++++++++++++++++++++++++++++++++--- src/main.h | 20 ++++++ src/main_x11.cpp | 1 + src/workspace.h | 20 ------ src/x11eventfilter.cpp | 10 +-- 6 files changed, 158 insertions(+), 151 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 2dfbb55f87..2ad539665d 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -141,129 +141,12 @@ static xcb_window_t findEventWindow(xcb_generic_event_t *event) } } -QVector s_xcbEerrors({ - QByteArrayLiteral("Success"), - QByteArrayLiteral("BadRequest"), - QByteArrayLiteral("BadValue"), - QByteArrayLiteral("BadWindow"), - QByteArrayLiteral("BadPixmap"), - QByteArrayLiteral("BadAtom"), - QByteArrayLiteral("BadCursor"), - QByteArrayLiteral("BadFont"), - QByteArrayLiteral("BadMatch"), - QByteArrayLiteral("BadDrawable"), - QByteArrayLiteral("BadAccess"), - QByteArrayLiteral("BadAlloc"), - QByteArrayLiteral("BadColor"), - QByteArrayLiteral("BadGC"), - QByteArrayLiteral("BadIDChoice"), - QByteArrayLiteral("BadName"), - QByteArrayLiteral("BadLength"), - QByteArrayLiteral("BadImplementation"), - QByteArrayLiteral("Unknown")}); - - -void Workspace::registerEventFilter(X11EventFilter *filter) -{ - if (filter->isGenericEvent()) { - m_genericEventFilters.append(new X11EventFilterContainer(filter)); - } else { - m_eventFilters.append(new X11EventFilterContainer(filter)); - } -} - -static X11EventFilterContainer *takeEventFilter(X11EventFilter *eventFilter, - QList> &list) -{ - for (int i = 0; i < list.count(); ++i) { - X11EventFilterContainer *container = list.at(i); - if (container->filter() == eventFilter) { - return list.takeAt(i); - } - } - return nullptr; -} - -void Workspace::unregisterEventFilter(X11EventFilter *filter) -{ - X11EventFilterContainer *container = nullptr; - if (filter->isGenericEvent()) { - container = takeEventFilter(filter, m_genericEventFilters); - } else { - container = takeEventFilter(filter, m_eventFilters); - } - delete container; -} - - /** * Handles workspace specific XCB event */ bool Workspace::workspaceEvent(xcb_generic_event_t *e) { const uint8_t eventType = e->response_type & ~0x80; - if (!eventType) { - // let's check whether it's an error from one of the extensions KWin uses - xcb_generic_error_t *error = reinterpret_cast(e); - const QVector extensions = Xcb::Extensions::self()->extensions(); - for (const auto &extension : extensions) { - if (error->major_code == extension.majorOpcode) { - QByteArray errorName; - if (error->error_code < s_xcbEerrors.size()) { - errorName = s_xcbEerrors.at(error->error_code); - } else if (error->error_code >= extension.errorBase) { - const int index = error->error_code - extension.errorBase; - if (index >= 0 && index < extension.errorCodes.size()) { - errorName = extension.errorCodes.at(index); - } - } - if (errorName.isEmpty()) { - errorName = QByteArrayLiteral("Unknown"); - } - qCWarning(KWIN_CORE, "XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d (%s)", - int(error->error_code), errorName.constData(), - int(error->sequence), int(error->resource_id), - int(error->major_code), extension.name.constData(), - int(error->minor_code), - extension.opCodes.size() > error->minor_code ? extension.opCodes.at(error->minor_code).constData() : "Unknown"); - return true; - } - } - return false; - } - - if (eventType == XCB_GE_GENERIC) { - xcb_ge_generic_event_t *ge = reinterpret_cast(e); - - // We need to make a shadow copy of the event filter list because an activated event - // filter may mutate it by removing or installing another event filter. - const auto eventFilters = m_genericEventFilters; - - for (X11EventFilterContainer *container : eventFilters) { - if (!container) { - continue; - } - X11EventFilter *filter = container->filter(); - if (filter->extension() == ge->extension && filter->genericEventTypes().contains(ge->event_type) && filter->event(e)) { - return true; - } - } - } else { - // We need to make a shadow copy of the event filter list because an activated event - // filter may mutate it by removing or installing another event filter. - const auto eventFilters = m_eventFilters; - - for (X11EventFilterContainer *container : eventFilters) { - if (!container) { - continue; - } - X11EventFilter *filter = container->filter(); - if (filter->eventTypes().contains(eventType) && filter->event(e)) { - return true; - } - } - } - if (effects && static_cast< EffectsHandlerImpl* >(effects)->hasKeyboardGrab() && (eventType == XCB_KEY_PRESS || eventType == XCB_KEY_RELEASE)) return false; // let Qt process it, it'll be intercepted again in eventFilter() diff --git a/src/main.cpp b/src/main.cpp index 48763cf1f0..069547bd6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,6 +25,7 @@ #include "screenlockerwatcher.h" #include "sm.h" #include "workspace.h" +#include "x11eventfilter.h" #include "xcbutils.h" #include @@ -357,6 +358,134 @@ void Application::destroyColorManager() #endif } +void Application::registerEventFilter(X11EventFilter *filter) +{ + if (filter->isGenericEvent()) { + m_genericEventFilters.append(new X11EventFilterContainer(filter)); + } else { + m_eventFilters.append(new X11EventFilterContainer(filter)); + } +} + +static X11EventFilterContainer *takeEventFilter(X11EventFilter *eventFilter, + QList> &list) +{ + for (int i = 0; i < list.count(); ++i) { + X11EventFilterContainer *container = list.at(i); + if (container->filter() == eventFilter) { + return list.takeAt(i); + } + } + return nullptr; +} + +void Application::unregisterEventFilter(X11EventFilter *filter) +{ + X11EventFilterContainer *container = nullptr; + if (filter->isGenericEvent()) { + container = takeEventFilter(filter, m_genericEventFilters); + } else { + container = takeEventFilter(filter, m_eventFilters); + } + delete container; +} + +bool Application::dispatchEvent(xcb_generic_event_t *event) +{ + static const QVector s_xcbEerrors({ + QByteArrayLiteral("Success"), + QByteArrayLiteral("BadRequest"), + QByteArrayLiteral("BadValue"), + QByteArrayLiteral("BadWindow"), + QByteArrayLiteral("BadPixmap"), + QByteArrayLiteral("BadAtom"), + QByteArrayLiteral("BadCursor"), + QByteArrayLiteral("BadFont"), + QByteArrayLiteral("BadMatch"), + QByteArrayLiteral("BadDrawable"), + QByteArrayLiteral("BadAccess"), + QByteArrayLiteral("BadAlloc"), + QByteArrayLiteral("BadColor"), + QByteArrayLiteral("BadGC"), + QByteArrayLiteral("BadIDChoice"), + QByteArrayLiteral("BadName"), + QByteArrayLiteral("BadLength"), + QByteArrayLiteral("BadImplementation"), + QByteArrayLiteral("Unknown") + }); + + kwinApp()->updateX11Time(event); + + const uint8_t x11EventType = event->response_type & ~0x80; + if (!x11EventType) { + // let's check whether it's an error from one of the extensions KWin uses + xcb_generic_error_t *error = reinterpret_cast(event); + const QVector extensions = Xcb::Extensions::self()->extensions(); + for (const auto &extension : extensions) { + if (error->major_code == extension.majorOpcode) { + QByteArray errorName; + if (error->error_code < s_xcbEerrors.size()) { + errorName = s_xcbEerrors.at(error->error_code); + } else if (error->error_code >= extension.errorBase) { + const int index = error->error_code - extension.errorBase; + if (index >= 0 && index < extension.errorCodes.size()) { + errorName = extension.errorCodes.at(index); + } + } + if (errorName.isEmpty()) { + errorName = QByteArrayLiteral("Unknown"); + } + qCWarning(KWIN_CORE, "XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d (%s)", + int(error->error_code), errorName.constData(), + int(error->sequence), int(error->resource_id), + int(error->major_code), extension.name.constData(), + int(error->minor_code), + extension.opCodes.size() > error->minor_code ? extension.opCodes.at(error->minor_code).constData() : "Unknown"); + return true; + } + } + return false; + } + + if (x11EventType == XCB_GE_GENERIC) { + xcb_ge_generic_event_t *ge = reinterpret_cast(event); + + // We need to make a shadow copy of the event filter list because an activated event + // filter may mutate it by removing or installing another event filter. + const auto eventFilters = m_genericEventFilters; + + for (X11EventFilterContainer *container : eventFilters) { + if (!container) { + continue; + } + X11EventFilter *filter = container->filter(); + if (filter->extension() == ge->extension && filter->genericEventTypes().contains(ge->event_type) && filter->event(event)) { + return true; + } + } + } else { + // We need to make a shadow copy of the event filter list because an activated event + // filter may mutate it by removing or installing another event filter. + const auto eventFilters = m_eventFilters; + + for (X11EventFilterContainer *container : eventFilters) { + if (!container) { + continue; + } + X11EventFilter *filter = container->filter(); + if (filter->eventTypes().contains(x11EventType) && filter->event(event)) { + return true; + } + } + } + + if (workspace()) { + return workspace()->workspaceEvent(event); + } + + return false; +} + void Application::updateX11Time(xcb_generic_event_t *event) { xcb_timestamp_t time = XCB_TIME_CURRENT_TIME; @@ -434,16 +563,10 @@ void Application::updateX11Time(xcb_generic_event_t *event) bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long int *result) { Q_UNUSED(result) - if (eventType != "xcb_generic_event_t") { - return false; + if (eventType == "xcb_generic_event_t") { + return kwinApp()->dispatchEvent(static_cast(message)); } - auto event = static_cast(message); - kwinApp()->updateX11Time(event); - if (!Workspace::self()) { - // Workspace not yet created - return false; - } - return Workspace::self()->workspaceEvent(event); + return false; } static bool s_useLibinput = false; diff --git a/src/main.h b/src/main.h index 2146bfd2a8..77a66b0beb 100644 --- a/src/main.h +++ b/src/main.h @@ -27,6 +27,7 @@ namespace KWin { class Platform; +class X11EventFilter; class XcbEventFilter : public QAbstractNativeEventFilter { @@ -34,6 +35,19 @@ public: bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override; }; +class X11EventFilterContainer : public QObject +{ + Q_OBJECT + +public: + explicit X11EventFilterContainer(X11EventFilter *filter); + + X11EventFilter *filter() const; + +private: + X11EventFilter *m_filter; +}; + class KWIN_EXPORT Application : public QApplication { Q_OBJECT @@ -96,6 +110,10 @@ public: void setupCommandLine(QCommandLineParser *parser); void processCommandLine(QCommandLineParser *parser); + void registerEventFilter(X11EventFilter *filter); + void unregisterEventFilter(X11EventFilter *filter); + bool dispatchEvent(xcb_generic_event_t *event); + xcb_timestamp_t x11Time() const { return m_x11Time; } @@ -255,6 +273,8 @@ protected: static int crashes; private: + QList> m_eventFilters; + QList> m_genericEventFilters; QScopedPointer m_eventFilter; bool m_configLock; KSharedConfigPtr m_config; diff --git a/src/main_x11.cpp b/src/main_x11.cpp index 6b48d8de06..6484e8f887 100644 --- a/src/main_x11.cpp +++ b/src/main_x11.cpp @@ -194,6 +194,7 @@ void ApplicationX11::lostSelection() destroyWorkspace(); // Remove windowmanager privileges Xcb::selectInput(rootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE); + removeNativeX11EventFilter(); quit(); } diff --git a/src/workspace.h b/src/workspace.h index e46fd91d9d..8e3cb1c05b 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -56,19 +56,6 @@ class X11Client; class X11EventFilter; enum class Predicate; -class X11EventFilterContainer : public QObject -{ - Q_OBJECT - -public: - explicit X11EventFilterContainer(X11EventFilter *filter); - - X11EventFilter *filter() const; - -private: - X11EventFilter *m_filter; -}; - class KWIN_EXPORT Workspace : public QObject { Q_OBJECT @@ -384,10 +371,6 @@ public: * @returns Whether we have a Compositor and it is active (Scene created) */ bool compositing() const; - - void registerEventFilter(X11EventFilter *filter); - void unregisterEventFilter(X11EventFilter *filter); - void markXStackingOrderAsDirty(); void quickTileWindow(QuickTileMode mode); @@ -669,9 +652,6 @@ private: friend class StackingUpdatesBlocker; QScopedPointer m_windowKiller; - - QList> m_eventFilters; - QList> m_genericEventFilters; QScopedPointer m_movingClientFilter; QScopedPointer m_syncAlarmFilter; diff --git a/src/x11eventfilter.cpp b/src/x11eventfilter.cpp index 8d71056a2c..3a89bebac4 100644 --- a/src/x11eventfilter.cpp +++ b/src/x11eventfilter.cpp @@ -8,7 +8,7 @@ */ #include "x11eventfilter.h" -#include +#include "main.h" namespace KWin { @@ -17,7 +17,7 @@ X11EventFilter::X11EventFilter(const QVector &eventTypes) : m_eventTypes(eventTypes) , m_extension(0) { - Workspace::self()->registerEventFilter(this); + kwinApp()->registerEventFilter(this); } @@ -29,13 +29,13 @@ X11EventFilter::X11EventFilter(int eventType, int opcode, int genericEventType) X11EventFilter::X11EventFilter(int eventType, int opcode, const QVector< int > &genericEventTypes) : m_eventTypes(QVector{eventType}), m_extension(opcode), m_genericEventTypes(genericEventTypes) { - Workspace::self()->registerEventFilter(this); + kwinApp()->registerEventFilter(this); } X11EventFilter::~X11EventFilter() { - if (auto w = Workspace::self()) { - w->unregisterEventFilter(this); + if (kwinApp()) { + kwinApp()->unregisterEventFilter(this); } }