diff --git a/src/dpmsinputeventfilter.cpp b/src/dpmsinputeventfilter.cpp index 7dbaed8d0d..86d7b8754a 100644 --- a/src/dpmsinputeventfilter.cpp +++ b/src/dpmsinputeventfilter.cpp @@ -23,7 +23,7 @@ namespace KWin { DpmsInputEventFilter::DpmsInputEventFilter() - : InputEventFilter() + : InputEventFilter(InputFilterOrder::Dpms) { KSharedConfig::Ptr kwinSettings = kwinApp()->config(); m_enableDoubleTap = kwinSettings->group(QStringLiteral("Wayland")).readEntry("DoubleTapWakeup", true); diff --git a/src/input.cpp b/src/input.cpp index e26865ea8d..acba7d7d0d 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -101,7 +101,10 @@ static PointerAxisSource kwinAxisSourceToKWaylandAxisSource(InputRedirection::Po } } -InputEventFilter::InputEventFilter() = default; +InputEventFilter::InputEventFilter(InputFilterOrder::Order weight) + : m_weight(weight) +{ +} InputEventFilter::~InputEventFilter() { @@ -110,6 +113,11 @@ InputEventFilter::~InputEventFilter() } } +int InputEventFilter::weight() const +{ + return m_weight; +} + bool InputEventFilter::pointerEvent(MouseEvent *event, quint32 nativeButton) { return false; @@ -281,6 +289,10 @@ bool InputEventFilter::passToInputMethod(QKeyEvent *event) class VirtualTerminalFilter : public InputEventFilter { public: + VirtualTerminalFilter() + : InputEventFilter(InputFilterOrder::VirtualTerminal) + { + } bool keyEvent(KeyEvent *event) override { // really on press and not on release? X11 switches on press. @@ -298,6 +310,10 @@ public: class LockScreenFilter : public InputEventFilter { public: + LockScreenFilter() + : InputEventFilter(InputFilterOrder::LockScreen) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { if (!waylandServer()->isScreenLocked()) { @@ -511,6 +527,10 @@ private: class EffectsFilter : public InputEventFilter { public: + EffectsFilter() + : InputEventFilter(InputFilterOrder::Effects) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { if (!effects) { @@ -596,6 +616,10 @@ public: class MoveResizeFilter : public InputEventFilter { public: + MoveResizeFilter() + : InputEventFilter(InputFilterOrder::InteractiveMoveResize) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { Window *window = workspace()->moveResizeWindow(); @@ -706,6 +730,10 @@ private: class WindowSelectorFilter : public InputEventFilter { public: + WindowSelectorFilter() + : InputEventFilter(InputFilterOrder::WindowSelector) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { if (!m_active) { @@ -873,6 +901,7 @@ class GlobalShortcutFilter : public InputEventFilter { public: GlobalShortcutFilter() + : InputEventFilter(InputFilterOrder::GlobalShortcut) { m_powerDown.setSingleShot(true); m_powerDown.setInterval(1000); @@ -1181,6 +1210,11 @@ std::pair performWindowWheelAction(QWheelEvent *event, Window *windo class InternalWindowEventFilter : public InputEventFilter { +public: + InternalWindowEventFilter() + : InputEventFilter(InputFilterOrder::InternalWindow) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { if (!input()->pointer()->focus() || !input()->pointer()->focus()->isInternal()) { @@ -1387,6 +1421,10 @@ private: class DecorationEventFilter : public InputEventFilter { public: + DecorationEventFilter() + : InputEventFilter(InputFilterOrder::Decoration) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { auto decoration = input()->pointer()->decoration(); @@ -1603,6 +1641,10 @@ private: class TabBoxInputFilter : public InputEventFilter { public: + TabBoxInputFilter() + : InputEventFilter(InputFilterOrder::TabBox) + { + } bool pointerEvent(MouseEvent *event, quint32 button) override { if (!workspace()->tabbox() || !workspace()->tabbox()->isGrabbed()) { @@ -1646,6 +1688,10 @@ public: class ScreenEdgeInputFilter : public InputEventFilter { public: + ScreenEdgeInputFilter() + : InputEventFilter(InputFilterOrder::ScreenEdge) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { workspace()->screenEdges()->isEntered(event); @@ -1702,6 +1748,10 @@ private: class WindowActionInputFilter : public InputEventFilter { public: + WindowActionInputFilter() + : InputEventFilter(InputFilterOrder::WindowAction) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { if (event->type() != QEvent::MouseButtonPress) { @@ -1771,6 +1821,10 @@ public: class InputKeyboardFilter : public InputEventFilter { public: + InputKeyboardFilter() + : InputEventFilter(InputFilterOrder::InputMethod) + { + } bool keyEvent(KeyEvent *event) override { return passToInputMethod(event); @@ -1783,6 +1837,10 @@ public: class ForwardInputFilter : public InputEventFilter { public: + ForwardInputFilter() + : InputEventFilter(InputFilterOrder::Forward) + { + } bool pointerEvent(MouseEvent *event, quint32 nativeButton) override { auto seat = waylandServer()->seat(); @@ -2008,6 +2066,7 @@ class TabletInputFilter : public QObject, public InputEventFilter { public: TabletInputFilter() + : InputEventFilter(InputFilterOrder::Tablet) { const auto devices = input()->devices(); for (InputDevice *device : devices) { @@ -2386,6 +2445,7 @@ class DragAndDropInputFilter : public QObject, public InputEventFilter Q_OBJECT public: DragAndDropInputFilter() + : InputEventFilter(InputFilterOrder::DragAndDrop) { connect(waylandServer()->seat(), &SeatInterface::dragStarted, this, []() { AbstractDataSource *dragSource = waylandServer()->seat()->dragSource(); @@ -2693,13 +2753,11 @@ InputRedirection::~InputRedirection() void InputRedirection::installInputEventFilter(InputEventFilter *filter) { Q_ASSERT(!m_filters.contains(filter)); - m_filters << filter; -} -void InputRedirection::prependInputEventFilter(InputEventFilter *filter) -{ - Q_ASSERT(!m_filters.contains(filter)); - m_filters.prepend(filter); + auto it = std::lower_bound(m_filters.begin(), m_filters.end(), filter, [](InputEventFilter *a, InputEventFilter *b) { + return a->weight() < b->weight(); + }); + m_filters.insert(it, filter); } void InputRedirection::uninstallInputEventFilter(InputEventFilter *filter) diff --git a/src/input.h b/src/input.h index 9494e3194c..65dcbb7256 100644 --- a/src/input.h +++ b/src/input.h @@ -136,14 +136,7 @@ public: bool supportsPointerWarping() const; void warpPointer(const QPointF &pos); - /** - * Adds the @p filter to the list of event filters and makes it the first - * event filter in processing. - * - * Note: the event filter will get events before the lock screen can get them, thus - * this is a security relevant method. - */ - void prependInputEventFilter(InputEventFilter *filter); + void installInputEventFilter(InputEventFilter *filter); void uninstallInputEventFilter(InputEventFilter *filter); /** @@ -311,7 +304,6 @@ private: void setupTouchpadShortcuts(); void setupWorkspace(); void setupInputFilters(); - void installInputEventFilter(InputEventFilter *filter); void updateLeds(LEDs leds); void updateAvailableInputDevices(); KeyboardInputRedirection *m_keyboard; @@ -367,6 +359,35 @@ private: friend class ForwardInputFilter; }; +namespace InputFilterOrder +{ +enum Order { + PlaceholderOutput, + Dpms, + ButtonRebind, + BounceKeys, + StickyKeys, + EisInput, + + VirtualTerminal, + LockScreen, + ScreenEdge, + DragAndDrop, + WindowSelector, + TabBox, + GlobalShortcut, + Effects, + InteractiveMoveResize, + Popup, + Decoration, + WindowAction, + InternalWindow, + InputMethod, + Forward, + Tablet +}; +} + /** * Base class for filtering input events inside InputRedirection. * @@ -389,9 +410,22 @@ private: class KWIN_EXPORT InputEventFilter { public: - InputEventFilter(); + /** + * Construct and install the InputEventFilter + * @param weight The position in the input chain, lower values come first. + * @note the filter is not installed automatically + */ + InputEventFilter(InputFilterOrder::Order weight); + /** + * @brief ~InputEventFilter + * This will uninstall the event filter if needed + */ virtual ~InputEventFilter(); + /** + * The position in the input chain, lower values come first. + */ + int weight() const; /** * Event filter for pointer events which can be described by a QMouseEvent. * @@ -451,6 +485,9 @@ public: protected: void passToWaylandServer(QKeyEvent *event); bool passToInputMethod(QKeyEvent *event); + +private: + int m_weight = 0; }; class KWIN_EXPORT InputDeviceHandler : public QObject diff --git a/src/placeholderinputeventfilter.cpp b/src/placeholderinputeventfilter.cpp index 4839b5a7f2..be8c0f95df 100644 --- a/src/placeholderinputeventfilter.cpp +++ b/src/placeholderinputeventfilter.cpp @@ -12,6 +12,11 @@ namespace KWin { +PlaceholderInputEventFilter::PlaceholderInputEventFilter() + : InputEventFilter(InputFilterOrder::PlaceholderOutput) +{ +} + bool PlaceholderInputEventFilter::pointerEvent(MouseEvent *event, quint32 nativeButton) { return true; diff --git a/src/placeholderinputeventfilter.h b/src/placeholderinputeventfilter.h index 2272a4357f..0d6504076d 100644 --- a/src/placeholderinputeventfilter.h +++ b/src/placeholderinputeventfilter.h @@ -16,6 +16,7 @@ namespace KWin class PlaceholderInputEventFilter : public InputEventFilter { public: + PlaceholderInputEventFilter(); bool pointerEvent(MouseEvent *event, quint32 nativeButton) override; bool wheelEvent(WheelEvent *event) override; bool keyEvent(KeyEvent *event) override; diff --git a/src/plugins/bouncekeys/bouncekeys.cpp b/src/plugins/bouncekeys/bouncekeys.cpp index 27bf015cc9..0b74c56bf6 100644 --- a/src/plugins/bouncekeys/bouncekeys.cpp +++ b/src/plugins/bouncekeys/bouncekeys.cpp @@ -8,7 +8,8 @@ #include "keyboard_input.h" BounceKeysFilter::BounceKeysFilter() - : m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("kaccessrc"))) + : KWin::InputEventFilter(KWin::InputFilterOrder::BounceKeys) + , m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("kaccessrc"))) { const QLatin1String groupName("Keyboard"); connect(m_configWatcher.get(), &KConfigWatcher::configChanged, this, [this, groupName](const KConfigGroup &group) { @@ -24,7 +25,7 @@ void BounceKeysFilter::loadConfig(const KConfigGroup &group) KWin::input()->uninstallInputEventFilter(this); if (group.readEntry("BounceKeys", false)) { - KWin::input()->prependInputEventFilter(this); + KWin::input()->installInputEventFilter(this); m_delay = std::chrono::milliseconds(group.readEntry("BounceKeysDelay", 500)); } else { diff --git a/src/plugins/buttonrebinds/buttonrebindsfilter.cpp b/src/plugins/buttonrebinds/buttonrebindsfilter.cpp index 8e12694e2e..a0d36e6881 100644 --- a/src/plugins/buttonrebinds/buttonrebindsfilter.cpp +++ b/src/plugins/buttonrebinds/buttonrebindsfilter.cpp @@ -120,7 +120,8 @@ bool InputDevice::isTouchpad() const } ButtonRebindsFilter::ButtonRebindsFilter() - : m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("kcminputrc"))) + : KWin::InputEventFilter(KWin::InputFilterOrder::ButtonRebind) + , m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("kcminputrc"))) { KWin::input()->addInputDevice(&m_inputDevice); const QLatin1String groupName("ButtonRebinds"); @@ -189,7 +190,7 @@ void ButtonRebindsFilter::loadConfig(const KConfigGroup &group) } if (foundActions) { - KWin::input()->prependInputEventFilter(this); + KWin::input()->installInputEventFilter(this); } } diff --git a/src/plugins/eis/eisinputcapturefilter.cpp b/src/plugins/eis/eisinputcapturefilter.cpp index 6c76797579..6f30abda67 100644 --- a/src/plugins/eis/eisinputcapturefilter.cpp +++ b/src/plugins/eis/eisinputcapturefilter.cpp @@ -16,7 +16,8 @@ namespace KWin { EisInputCaptureFilter::EisInputCaptureFilter(EisInputCaptureManager *manager) - : m_manager(manager) + : InputEventFilter(InputFilterOrder::EisInput) + , m_manager(manager) { } diff --git a/src/plugins/eis/eisinputcapturemanager.cpp b/src/plugins/eis/eisinputcapturemanager.cpp index 20cca4144a..0056665881 100644 --- a/src/plugins/eis/eisinputcapturemanager.cpp +++ b/src/plugins/eis/eisinputcapturemanager.cpp @@ -174,7 +174,7 @@ void EisInputCaptureManager::barrierHit(KWin::EisInputCapture *capture, const QP } m_activeCapture = capture; capture->activate(position); - input()->prependInputEventFilter(m_inputFilter.get()); + input()->installInputEventFilter(m_inputFilter.get()); // Even though the input events are filtered out the cursor is updated on screen which looks weird Cursors::self()->hideCursor(); } diff --git a/src/plugins/stickykeys/stickykeys.cpp b/src/plugins/stickykeys/stickykeys.cpp index 887fb0ff45..54bcf8ab4a 100644 --- a/src/plugins/stickykeys/stickykeys.cpp +++ b/src/plugins/stickykeys/stickykeys.cpp @@ -29,7 +29,8 @@ static const std::array modifiers = { }; StickyKeysFilter::StickyKeysFilter() - : m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("kaccessrc"))) + : KWin::InputEventFilter(KWin::InputFilterOrder::StickyKeys) + , m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("kaccessrc"))) { const QLatin1String groupName("Keyboard"); connect(m_configWatcher.get(), &KConfigWatcher::configChanged, this, [this, groupName](const KConfigGroup &group) { @@ -82,7 +83,7 @@ void StickyKeysFilter::loadConfig(const KConfigGroup &group) } if (group.readEntry("StickyKeys", false)) { - KWin::input()->prependInputEventFilter(this); + KWin::input()->installInputEventFilter(this); } else { // sticky keys are deactivated, unlatch all latched/locked keys for (auto it = m_keyStates.keyValueBegin(); it != m_keyStates.keyValueEnd(); ++it) { diff --git a/src/popup_input_filter.cpp b/src/popup_input_filter.cpp index 751b1721a8..5b288b61bb 100644 --- a/src/popup_input_filter.cpp +++ b/src/popup_input_filter.cpp @@ -18,6 +18,7 @@ namespace KWin PopupInputFilter::PopupInputFilter() : QObject() + , InputEventFilter(InputFilterOrder::Popup) { connect(workspace(), &Workspace::windowAdded, this, &PopupInputFilter::handleWindowAdded); } diff --git a/src/workspace.cpp b/src/workspace.cpp index 7edf6faeaa..02d6b48194 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -1235,7 +1235,7 @@ void Workspace::updateOutputs(const std::optional> &outputOrder) if (!m_placeholderOutput) { m_placeholderOutput = new PlaceholderOutput(QSize(1920, 1080), 1); m_placeholderFilter = std::make_unique(); - input()->prependInputEventFilter(m_placeholderFilter.get()); + input()->installInputEventFilter(m_placeholderFilter.get()); } m_outputs.append(m_placeholderOutput); } else { @@ -1345,7 +1345,7 @@ void Workspace::createDpmsFilter() { if (!m_dpmsFilter) { m_dpmsFilter = std::make_unique(); - input()->prependInputEventFilter(m_dpmsFilter.get()); + input()->installInputEventFilter(m_dpmsFilter.get()); } }