Skip to content

Conversation

@AlanGriffiths
Copy link
Contributor

No description provided.

Copy link
Contributor

@Saviq Saviq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is still a draft, but just leaving some notes on it.

@AlanGriffiths AlanGriffiths force-pushed the MIRENG-1493-input-triggers branch from 47bbff0 to 7ef9f66 Compare October 6, 2025 15:41
@AlanGriffiths AlanGriffiths changed the title MIRENG-1493-input-triggers Draft ext-input-triggers Oct 7, 2025
Copy link
Contributor

@tarek-y-ismail tarek-y-ismail left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Activation part is mostly fine except handling oneshot/continuous actions, but I think registration still needs more discussion

@AlanGriffiths AlanGriffiths force-pushed the MIRENG-1493-input-triggers branch 2 times, most recently from 627266b to b36df35 Compare October 10, 2025 16:09
@tarek-y-ismail tarek-y-ismail requested a review from Saviq October 17, 2025 14:12
Copy link
Contributor

@tarek-y-ismail tarek-y-ismail left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor nits, but I think it might be good enough for a quick spike.

@AlanGriffiths AlanGriffiths force-pushed the MIRENG-1493-input-triggers branch from 759ea0c to 6489d90 Compare October 22, 2025 11:54
@AlanGriffiths AlanGriffiths marked this pull request as ready for review October 23, 2025 10:34
@AlanGriffiths AlanGriffiths requested a review from a team as a code owner October 23, 2025 10:34
@AlanGriffiths AlanGriffiths force-pushed the MIRENG-1493-input-triggers branch from f1620c2 to f60b0cf Compare October 23, 2025 13:43
Addresses feedback from #4328 where the protocol specification stated
the compositor "should raise a protocol error" without defining which
error to raise.

**Changes:**
- Added `invalid_token` error enum to
`ext_input_trigger_action_manager_v1` interface
- Updated `get_input_trigger_action` request description to
prescriptively specify when the `invalid_token` error must be raised

The error is raised when a client provides a token that was not issued
by the compositor, following the pattern established in other Wayland
protocols like `ext-data-control-v1` and `ext-image-copy-capture-v1`.
@tarek-y-ismail
Copy link
Contributor

tarek-y-ismail commented Nov 14, 2025

So I used Copilot as a rubber duck, here's a quick "summary" of the points it brought up about the protocol and my opinions/responses. Apologies in advance for the wall of text.


Concrete protocol bug (must fix)

  • enum name mismatch in register_modifier_tap_trigger
  • Fix: change enum="modifier" to enum="modifiers" and/or rename arg to modifiers if you intend a bitfield (and document if multiple modifiers are allowed).

It's worth discussing whether we want to allow just one modifier in this request, or multiple ones. The use case I recall from when we discussed this was tapping both the left and right shifts to toggle mute, which would require us to specify two modifiers.


High priority semantic and security issues

  1. Token/auth model is underspecified: token generation properties (entropy, unguessability), token format / length,

Tokens are mostly meant to be opaque strings similar to tokens used in ext_activation_v1.

  1. No seat/device scoping (multi-seat/multi-device implications)

This is true. Do we want to take this into account for v1?

  1. register_pointer_trigger takes edges but does not say whether edges are per-output, global screen-space, or per-monitor; it doesn’t accept an output id or bounding region.

I think we discussed this before. We settled on this being compositor-defined.

  1. Lack of ownership/consumption semantics for captured input
  • When a trigger is “done” and the manager “owns” it, the docs say “This client is now responsible for handling this input trigger.” That is vague:
    • Does the compositor stop delivering the underlying raw input events to normal clients?
    • Does the compositor synthesize events for the manager only (i.e., exclusive grab) or are events still delivered to applications?

We should clear this up. From memory, we decided that all inputs will be delivered to the focused client as usual. Once a registered trigger is invoked, that input will be consumed by the compositor and diverted to the listening client.

Implementation details: As @RAOF mentioned before, the modifier state will need to be reset by synthesizing events to clear the pressed modifiers so the focused client is not confused when focus returns to it.

Example, Ctrl + Shift + X. The focused client would get Ctrl, then Shift. If another app takes focus temporarily and the user lets go of the two modifiers before returning to the first app, then the app will still think the two modifiers are still down.

  1. Concurrency and correlation of begin/update/end events
    • ext_input_trigger_action_v1 has begin, update, end events but no identifier to correlate multiple simultaneous activations for the same action token. The protocol doesn't forbid simultaneous activations; it doesn't state whether begin/end pairs are strictly nested or distinct, or whether multiple begins can be outstanding.

Is this even possible? Unless you have multiple input devices (keyboards / mice), I don't think it is.

  1. Time/timestamp semantics unclear
    • Each event includes time (uint) "timestamp with millisecond granularity" but it doesn't state the epoch or clock reference (compositor monotonic clock? boot time?), wrap-around behavior, or whether the client should use it for ordering vs the Wayland event order.

I think we should specify this. For us, our clocks are usually relative to the UNIX epoch, right? I don't think we need to worry about wrap-around. And ordering of the events should match the Wayland event order so that's also a non-issue.

  1. activation_token semantics and lifecycle are ambiguous
    • activation_token is a string described as “an xdg_activation token” but there’s no link to exact usage: should clients call xdg_activation_v1.activate with it? Is it optional/nullable? Who issues these tokens and when do they expire?

We should clear up the usage of the token. From the API, it's obviously not nullable/optional, so that's not a concern. We should specify that tokens are issued by the compositor and expire after a certain (compositor-defined) period of time.

Medium priority design omissions / missing error handling

  1. Poor/few error codes and lack of failure reasons
    • ext_input_trigger_v1 has done/failed with no failure reason, and the action manager only has invalid_token as an error. There is no reason code taxonomy (e.g., conflict, unsupported capability, insufficient privileges, out of resources).

Maybe we want to explore this a bit. I believe we discussed the conflict case before and settled on leaving it up to the DE maintainers to handle conflicts between the various previliged clients externally. Though, this doesn't rule out the user modifying a trigger and accidentally using one that's already taken. Which in this case would just call failed. I'm not so sure about the other modes of failure.

  1. Missing constraints, thresholds and configuration options for gestures
    • Touch drag/tap triggers have touches, direction, hold_delay, but no tolerances:
      • angle tolerance for "direction",
      • minimum/maximum movement distance to classify as drag vs tap,
      • inter-tap timeout for tap_count,
      • maximum finger spread or bounding box, velocity thresholds.
    • Result: different compositors may implement wildly different behavior; false positives/negatives are likely.

Again, I believe we discussed this before and agreed that it should be up to the compositor to define these to ensure a consistent experience.

  1. Pointer trigger hysteresis and debouncing unspecified
    • For screen edge triggers: what counts as “pushed to the target edge(s)”? If a pointer is at x=1 pixel from edge, does that count? Without hysteresis, you can get flapping between begin/end as the pointer hovers near the edge.

Compositor defined, again.

  1. register_keyboard_sym_trigger vs register_keyboard_code_trigger implications & layout issues
    • Using keysyms is layout-dependent; the semantics are currently “interpreted according to xkbcommon-keysyms.h” but there’s no guidance on how layout changes affect registered triggers, or whether triggers bind to physical key locations vs interpreted symbols (i.e., Ctrl+comma vs Ctrl+less).

I think Copilot got a bit confused, but this probably means we need to clarify things a bit. Code triggers should not change with the layout, but sym triggers should. Though the more I think about it, the more I see sym triggers as superfluous, what was their use case again?

  1. Tap/hold semantics vagueness
    • register_modifier_hold_trigger and register_modifier_tap_trigger are underspecified: what exactly is a 'tap' (press+release within time/without movement), maximum allowed inter-key times for multi-taps, etc.

Fair point. I think this should also be compositor-defined to ensure consistency.

  1. Lack of clarity about lifecycle interactions between cancel vs destroy
    • ext_input_trigger_action_control_v1 has cancel (destructor) making actions unavailable and destroy (destructor) that leaves created action objects unaffected. This is potentially confusing: documentation should explain use-cases for each and guarantee ordering semantics when clients hold existing ext_input_trigger_action_v1 objects.
    • Also, ext_input_trigger_action_manager_v1.get_input_trigger_action is supposed to emit unavailable if the token is no longer available — the relationship between cancel, destroy, and token invalidation needs to be clarified.

I agree with this. I confuse all three quite a bit.

Lower priority / niceties / improvements

  1. Missing documentation about key repeat and update events
    • For keyboard triggers, how should repeated key events (auto-repeat) be treated? Should they produce update events? The document states begin on depression and end on change, but it should clarify how repeats are treated.

I just had to handle this in the spike. I don't have a use case in mind where repeat would be that useful, so I believe we should specify that it's should not emit update events.

  1. progress fixed type precision and range
    • progress is a Wayland fixed normalized to [0.0, 1.0]. It’s good to specify whether values must be clamped, whether 1.0 must be sent before end, and how to interpret fractional precision (Wayland fixed is 16.16 usually — but calling out the expected precision is helpful).

Fair point, my opinion at the moment is that 1.0 must be sent.

  1. No means to enumerate current triggers or query which triggers belong to an action
    • Once you create an action and add triggers, there is no introspection API to list them later. This can make debugging and synchronization complex.

Again, I remember that we agreed that this should not be a part of these two protocols.

  1. No way to attach metadata to tokens or actions
    • name is a free-form description but there’s no capability for richer metadata / display name / icon that the compositor might show to users. Consider allowing optional metadata.

This might be a minor issue for applications that want to show button icons instead of Ctrl + Shift + C, but I don't believe it's a major issue at the moment.

  1. Unclear how gloves/virtual keyboard input is handled
    • Not critical, but worth mentioning: the protocol assumes physical devices; if applications synthesize input, should synthesized events trigger global actions?

I don't think virtual devices or OSKs should trigger global actions.

  1. Documentation comments in XML mention “This protocol allows for a privileged Wayland client” but the actual interface offers no way for the compositor/ecosystem to differentiate privileged vs normal clients. You must define how compositors expose these globals (e.g., only to trusted clients) and how clients obtain the global.

We talked about this before as well. "Priviliged clients" can mean clients launched explicitly by the compositor. In which case we would advertise the globals. Otherwise, we don't.

@tarek-y-ismail
Copy link
Contributor

Fair point, my opinion at the moment is that 1.0 must be sent.

Thinking about this again, maybe this isn't the best idea as it might introduce some unwanted jank. For example, if a user is moving to the right workspace via a gesture, the DE might have a threshold of 0.5 progress after which the move is done whether the gesture is cancelled or not. Requiring compositors to send 1.0 will just introduce complexity as they'll have to handle and ignore sudden jumps in progress.

@tarek-y-ismail tarek-y-ismail force-pushed the MIRENG-1493-input-triggers branch from 41c94a9 to 3599e06 Compare November 18, 2025 08:01
Comment on lines 120 to 139
<event name="activated">
<description summary="activate the input action">
The input trigger has been activated. This can be on the leading or
trailing edge of the input being pressed. It's up to the user to
configure this as they see fit.

The app may interpret this as a request to perform the action it
associates with the trigger.

The time argument is a timestamp with millisecond granularity, with an
undefined base. clients must not assume any relation to wall-clock
time; timestamps are only valid for comparison/deltas.

The activation token argument is a short-lived opaque token that may be
used with `xdg_activation_v1` to request to focus another surface.
</description>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="activation_token" type="string" summary="an xdg_activation token"/>
</event>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we decided against introducing that (yet)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that was shorty after I updated the PR. Haven't gotten around to it again, sorry

@github-actions
Copy link

TICS Quality Gate

✔️ Passed

No changed files applicable for TICS analysis quality gating.

TICS / TICS / Run TICS analysis

@Saviq Saviq force-pushed the main branch 4 times, most recently from 39740d9 to 43ac49a Compare December 15, 2025 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants