Customize gestures with a little help from KGlobalAccelD

Continuation of !8085 (and also !9100) with a new dependency on kglobalacceld!96 to load gestures from kglobalshortcutsrc and generally to integrate gestures with existing global actions.

CCBUG: 402857

@zamundaaa @nclarius @vladz

Rough idea

On the API user side, I slightly modified @zamundaaa's ConfigurableGesture so an Effect like OverviewEffect integrates with KGlobalAccel gestures like this:

    KGlobalAccel::setInverseShortcutActions(cycleAction, reverseCycleAction);

    ConfigurableGesture *forwardGesture = effects->registerGesture(cycleAction);
    ConfigurableGesture *backwardGesture = effects->registerGesture(reverseCycleAction);
    m_overviewState->addGesture(forwardGesture.get(), backwardGesture.get());
    m_transitionState->addGesture(forwardGesture.get(), backwardGesture.get());
    m_gridState->addGesture(backwardGesture.get(), forwardGesture.get());

Let's break that down:

setInverseShortcutActions() is a new API method that would go into KGlobalAccel public API. Introduced separately via !9100.

Independently of KWin code flow, ideally in a separate thread in the future, KGlobalAccel tries to grab keys activate gestures for any active action by calling the new virtual setTriggerActive() on its plugin interface.

  • In KWin, the plugin interface is KGlobalAccelImpl from src/plugins/kglobalacceld.
  • KGlobalAccelImpl::setTriggerActive() is forwarded to GlobalShortcutsManager::onKGlobalShortcutTriggerActive(), giving KWin a complete picture of configured gestures both for the "kwin" component and any other apps/components.
  • GlobalShortcutsManager::onKGlobalShortcutTriggerActive() activates the KWin gesture that corresponds to KGlobalAccelD's trigger.
    • If the gesture was manually registered by a KWin component using GlobalShortcutsManager::registerGesture(shortcutAction), the component that called it will take responsibility for handling gesture updates via started(), cancelled() and triggered() signals. registerGesture() replaces hardcoding several concrete gestures.
    • If the gesture wasn't manually registered, then we'll create an autoGesture which will send a triggerEvent() back to KGlobalAccelD upon completion. This will invoke the regularly assigned global action, similar to how global keyboard shortcuts are performed, allowing for assigned gestures to trigger any arbitrary global action.
      • In the future, I'd like to adopt and visualize auto gestures by an additional Effect, for any actions that aren't explicitly registered with registerGesture().

EffectTogglableState::addGesture() hooks up the gesture's progress and released (=triggered+cancelled) signals to the corresponding code in EffectTogglableState itself.

  • In this revision (as opposed to @zamundaaa's !8085), the association of gesture with inverse gesture happens here, and not in ConfigurableGesture directly.

ConfigurableGesture loses the forwardAction/backwardAction members from !8085, and instead becomes responsible only for a single action.

  • One action, however, can have multiple gestures assigned to it; e.g. one TouchpadSwipe and one TouchscreenSwipe, and why not also perhaps a PointerAxis and a LineShape in the future. All independently able to trigger and (if supported by that trigger type) provide a progress ratio.
  • Each concrete KWin gesture shortcut, in the GlobalShortcutsManager/GlobalShortcut sense, is associated to a given action and auto-removed when that action is destroyed. ConfigurableGesture now keeps a map of internal shortcut actions, which allows KGlobalAccelD to individually disable gestures (presumably on config change) without necessarily dropping all other gestures associated to the same action.

Default shortcuts are set in-process by KWin via KGlobalAccelD::setDefaultShortcutTriggers(). We're not interested in letting apps define their own default gestures. There's only a handful of them, it doesn't seem to be much of an issue to centralize the assignment of all the default gestures in one place.

At a later point, we'll add a private D-Bus API for System Settings to fetch default shortcut triggers and assign overrides from the KCM. We'll also add an API to record a gesture, so System Settings can have a "Record Gesture..." button instead of having to configure gestures through form fields. Just a quick mention in case you were wondering if that's included in this MR; it's not.

This MR is not coupled to GUI changes, it's config file only. If this passes review, here and in KGlobalAccel/KGlobalAccelD, then I would like to propose merging it for 6.7 without GUI. Customizable gestures are a widely requested feature, large parts of the target audience is not afraid to deal with config files directly, and we have a solid UX concept with agreement from several Plasma devs that matches the data model from this MR (still need to update it for the outcomes from the Graz MegaSprint).

Testing

Build this only on top of the aforementioned changes for kglobalaccel and kglobalacceld. Run it to get an update to kglobalshortcutsrc with newly written inverse actions and default trigger assignments for the kwin component.

Change the trigger assignments by overriding the defaults or adding new ones altogether. You can find an example of the resulting config entries in kglobalacceld!96.

You can assign any global action and it will trigger upon successful gesture completion. However, these following ones have live gesture updates like before:

  • Cycle Overview
  • Cycle Overview Opposite
  • Switch One Desktop Down
  • Switch One Desktop Up
  • Switch One Desktop to the Left
  • Switch One Desktop to the Right
  • Zoom In
  • Zoom Out

You can reassign them to any other gesture or unassign them altogether. Have fun!

Edited by Jakob Petsovits

Merge request reports

Loading