Add API and config storage for triggers, to support gesture customization

This sits on top of !95, mainly to avoid merge conflicts, functionally independent though.

Without additional code by the host process of KGlobalAccelD (i.e. KWin, on Wayland), no behavior change is intended and no new config entries are written.

I'm uploading a couple of fixups in addition to the three commits, for posterity and to try conveying the idea. The main commit surely touches a bunch of files, but if you know KGlobalAccelD then you know that most of it is container classes forwarding function calls to their children. Which I mostly copied and adapted from the analogous key-centric functions. In terms of complexity, it's really not that bad imho.

Because it's all self-contained in KGlobalAccelD now, which is part of the plasma group just like KWin, there's no binary compatibility concern at this time. As long as the config format is sane and the MR doesn't introduce any bugs of note, we can iterate on this as needed.


This introduces a new class called KGlobalShortcutTrigger. It can represent a number of different gestures and their respective parameters (like fingers, direction, points, etc.) but avoids representing keyboard shortcuts to prevent clashes with the existing key-based API.

Like existing keyboard shortcuts, triggers are considered shortcuts that are meant to invoke an assigned action upon completion. Likewise, an action can have default trigger assignments and user-defined override assignments. Trigger assignments are stored independently per trigger type to allow introducing new trigger types later, without having to explicitly migrate the overrides.

Unlike keyboard shortcuts, an application is not allowed to set its own trigger assignments. The number of possible gestures is usually much more limited than the number of available keys. Assigning default triggers for an action is therefore exposed as in-process API for KGlobalAccelD's host process, usually KWin.

The same host process is also responsible for actually recognizing triggers. The host can proactively observe the triggers' activation status as advertised by KGlobalAccelInterface::setTriggerActive(), or it can send KGlobalAccelInterface::triggerEvent() to KGlobalAccelD in the same way that KGlobalAccelInterface::keyEvent() receives key presses and invokes the corresponding action. Or a mix of both, which is what my upcoming MR is doing.


On the kglobalshortcutsrc config file side, this will write default shortcuts and read any shortcut overrides, which can look like this:

# This first group already exists, included for your convenience, not getting changed by this MR
[kwin]
Activate Window Demanding Attention=Meta+Ctrl+A,Meta+Ctrl+A,Activate Window Demanding Attention
ClearLastMouseMark=Meta+Shift+F12,Meta+Shift+F12,Clear Last Mouse Mark
ClearMouseMarks=Meta+Shift+F11,Meta+Shift+F11,Clear Mouse Marks
Cycle Overview=none,none,Cycle through Overview and Grid View
Cycle Overview Opposite=none,none,Cycle through Grid View and Overview
(...)

# Newly added not by this MR, but by https://invent.kde.org/plasma/kglobalacceld/-/merge_requests/95
[kwin][$InverseAction]
Cycle Overview=Cycle Overview Opposite
(...)

[kwin][$Triggers][Cycle Overview]
TouchpadSwipe|Default=3:Up
TouchscreenSwipe|Default=3:Up

[kwin][$Triggers][Cycle Overview Opposite]
TouchpadSwipe|Current=3:Down,4:Up
TouchpadSwipe|Default=3:Down
TouchscreenSwipe|Current=3:Down,4:Up
TouchscreenSwipe|Default=3:Down

[kwin][$Triggers][Edit Tiles]
TouchpadSwipe|Current=3:Right

[kwin][$Triggers][Switch One Desktop Down]
TouchpadSwipe|Current=
TouchpadSwipe|Default=3:Down
TouchscreenSwipe|Current=
TouchscreenSwipe|Default=3:Down

[kwin][$Triggers][Switch One Desktop Up]
TouchpadSwipe|Current=
TouchpadSwipe|Default=3:Down
TouchscreenSwipe|Current=
TouchscreenSwipe|Default=3:Down

[kwin][$Triggers][Switch One Desktop to the Left]
TouchpadSwipe|Default=4:Right
TouchscreenSwipe|Default=4:Right

[kwin][$Triggers][Switch One Desktop to the Right]
TouchpadSwipe|Default=4:Left
TouchscreenSwipe|Default=4:Left

[kwin][$Triggers][view_zoom_in]
TouchpadPinch|Default=3:Expanding
TouchscreenPinch|Default=3:Expanding

[kwin][$Triggers][view_zoom_out]
TouchpadPinch|Default=3:Contracting
TouchscreenPinch|Default=3:Contracting

This format is different from either of the two that we previously proposed at kwin#298, I'll add an "Option 3" comment there to explain the exact syntax. These triggers are applied to the corresponding shortcut action that gets defined either in this file or in a .desktop file.

In a nutshell, this format is the result of several motivations:

  • Ability to add new trigger types without requiring a config file migration every time, hence different keys for defaults vs. overrides (Current) as well as for different trigger types.
  • Straightforward implementation that reuses the same KConfigGroup which Component::loadSettings() and writeSettings() is already getting passed in.
  • Keeping the config file relatively readable, putting related entries adjacent to each other as good as possible, and not blowing up its size by too much. (It helps that you can probably count the number of default gestures on two hands.)
  • If we later want to add more trigger-specific info, say SupportsLiveGestureUpdates=true, then that can go into the same [...][$Trigger][Action] group.

Did I forget anything? Let me know!

CC @nclarius, @nicolasfella, @zamundaaa, @whoisahmad

Edited by Kristen McWilliam

Merge request reports

Loading