core: Introduce explicit weight to InputEventFilter
This is problematic as it means anything requiring a fixed position in the chain cannot be added or removed at runtime. This is bad for both performance and code cleanliness as all code ends up input.cpp rather than where it semantically belongs. Remaining users that prepend event filters have the problem of the order being effectively undefined. This patch adds a weight attribute to the filter allowing filters to be installed and removed at runtime whilst maintaining a specific deterministic order. Currently the order is defined by an enum based on the filter names. This gives an easy to read explicit order for anyone reading kwin code, but it is left cast to an int so we have future flexibility.
This commit is contained in:
parent
f22ef1f090
commit
99caa54901
12 changed files with 134 additions and 28 deletions
|
@ -23,7 +23,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
DpmsInputEventFilter::DpmsInputEventFilter()
|
||||
: InputEventFilter()
|
||||
: InputEventFilter(InputFilterOrder::Dpms)
|
||||
{
|
||||
KSharedConfig::Ptr kwinSettings = kwinApp()->config();
|
||||
m_enableDoubleTap = kwinSettings->group(QStringLiteral("Wayland")).readEntry<bool>("DoubleTapWakeup", true);
|
||||
|
|
|
@ -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<bool, bool> 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)
|
||||
|
|
57
src/input.h
57
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
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
PlaceholderInputEventFilter::PlaceholderInputEventFilter()
|
||||
: InputEventFilter(InputFilterOrder::PlaceholderOutput)
|
||||
{
|
||||
}
|
||||
|
||||
bool PlaceholderInputEventFilter::pointerEvent(MouseEvent *event, quint32 nativeButton)
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<bool>("BounceKeys", false)) {
|
||||
KWin::input()->prependInputEventFilter(this);
|
||||
KWin::input()->installInputEventFilter(this);
|
||||
|
||||
m_delay = std::chrono::milliseconds(group.readEntry<int>("BounceKeysDelay", 500));
|
||||
} else {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
namespace KWin
|
||||
{
|
||||
EisInputCaptureFilter::EisInputCaptureFilter(EisInputCaptureManager *manager)
|
||||
: m_manager(manager)
|
||||
: InputEventFilter(InputFilterOrder::EisInput)
|
||||
, m_manager(manager)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ static const std::array<Modifier, 5> 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<bool>("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) {
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace KWin
|
|||
|
||||
PopupInputFilter::PopupInputFilter()
|
||||
: QObject()
|
||||
, InputEventFilter(InputFilterOrder::Popup)
|
||||
{
|
||||
connect(workspace(), &Workspace::windowAdded, this, &PopupInputFilter::handleWindowAdded);
|
||||
}
|
||||
|
|
|
@ -1235,7 +1235,7 @@ void Workspace::updateOutputs(const std::optional<QList<Output *>> &outputOrder)
|
|||
if (!m_placeholderOutput) {
|
||||
m_placeholderOutput = new PlaceholderOutput(QSize(1920, 1080), 1);
|
||||
m_placeholderFilter = std::make_unique<PlaceholderInputEventFilter>();
|
||||
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<DpmsInputEventFilter>();
|
||||
input()->prependInputEventFilter(m_dpmsFilter.get());
|
||||
input()->installInputEventFilter(m_dpmsFilter.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue