|
1 | 1 | # xx-hotkey |
2 | 2 |
|
3 | | -A revision of [`vicinae-hotkey`](../../staging/vicinae-hotkey/) prepared for the |
4 | | -`experimental/` track of wayland-protocols. Same goal — an application binds its |
5 | | -own global hotkeys — with a different shape. |
| 3 | +A reworked [`vicinae-hotkey`](../../staging/vicinae-hotkey/) aimed at the |
| 4 | +`experimental/` track of wayland-protocols. |
6 | 5 |
|
7 | | -The two are **parallel, not sequential**. `vicinae-hotkey-v1` is what Hyprland, |
8 | | -Ghostty and Vicinae ship today and cannot change without breaking them. |
9 | | -`xx-hotkey-v1` is the upstream proposal. They are not wire-compatible. |
10 | | - |
11 | | -## At a glance |
12 | | - |
13 | | -```c |
14 | | -xx_hotkey_manager_v1_set_app_id(manager, "com.example.app"); |
15 | | - |
16 | | -struct xx_hotkey_v1 *hotkey = |
17 | | - xx_hotkey_manager_v1_create_hotkey(manager, "toggle-launcher"); |
18 | | -xx_hotkey_v1_add_listener(hotkey, &listener, NULL); |
19 | | - |
20 | | -xx_hotkey_v1_set_description(hotkey, "Toggle the launcher"); |
21 | | -xx_hotkey_v1_set_key_trigger(hotkey, XKB_KEY_space, |
22 | | - XX_HOTKEY_MANAGER_V1_MODIFIERS_SUPER); |
23 | | -xx_hotkey_v1_commit(hotkey); |
24 | | -``` |
25 | | -
|
26 | | -Runnable client in [`../../examples/xx-hotkey-demo.c`](../../examples/xx-hotkey-demo.c). |
27 | | -
|
28 | | -## What changed, and why |
29 | | -
|
30 | | -**A builder instead of one `bind` call.** With three trigger kinds and a name to |
31 | | -carry, a single request would take seven arguments and grow one more each time a |
32 | | -trigger kind is added. Building state and applying it with `commit` also gives |
33 | | -somewhere for protocol errors to live. |
34 | | -
|
35 | | -**`commit` is repeatable.** Committing again changes the trigger while keeping |
36 | | -the binding's identity, so reconfiguring no longer means destroying and |
37 | | -recreating the object. A denied commit leaves the previous binding active, so a |
38 | | -rejected reconfiguration never leaves the user with no hotkey. |
39 | | -
|
40 | | -**A stable `name`.** A machine-readable identifier distinct from the localized |
41 | | -description, so a client can correlate a binding with its own configuration. It |
42 | | -is a `create_hotkey` argument rather than a setter, being mandatory and |
43 | | -immutable. |
44 | | -
|
45 | | -**Pointer buttons and modifier-only taps.** A key was the only possible trigger |
46 | | -before. Buttons use the `wl_pointer.button` code space. A modifier-only trigger |
47 | | -fires on release, and only if nothing else was pressed, which is the |
48 | | -tap-Super-to-launch idiom; for press-and-hold on a modifier, bind its keysym as |
49 | | -a key trigger instead. |
50 | | -
|
51 | | -**`app_id` moved to the manager.** It identifies the connection, not each |
52 | | -binding. Setting it per hotkey meant repeating one string, and let a client |
53 | | -claim two identities. |
54 | | -
|
55 | | -**Protocol errors.** `invalid_trigger` and `no_trigger` on the hotkey, |
56 | | -`invalid_app_id` and `invalid_name` on the manager. The builder makes illegal |
57 | | -orderings expressible, so they need to be defined. |
58 | | -
|
59 | | -**RFC 2119 boilerplate**, lowercase keywords, and the `experimental/` disclaimer |
60 | | -rather than the `staging/` one. |
61 | | -
|
62 | | -## Boundaries |
63 | | -
|
64 | | -Two things this deliberately does not do, both because they would require the |
65 | | -compositor to store the user's trigger assignments: |
66 | | -
|
67 | | -- **The compositor never originates or reassigns a binding.** It answers a |
68 | | - commit with `bound` or `denied` and may later `revoke`, but never substitutes |
69 | | - a trigger of its own. Compositor-assigned, persisted shortcuts are what the |
70 | | - desktop portal's GlobalShortcuts interface is for. |
71 | | -- **Nothing is persisted.** A binding lives as long as its object and the client |
72 | | - connection. Compositor state is limited to policy, which it may persist freely. |
73 | | -
|
74 | | -There is also no request to refuse a client outright: a compositor that does not |
75 | | -want a client to have hotkeys should not advertise the global to it, as with |
76 | | -other restricted protocols. |
| 6 | +See [`xx-hotkey-v1.xml`](xx-hotkey-v1.xml) and the client in |
| 7 | +[`../../examples/xx-hotkey-demo.c`](../../examples/xx-hotkey-demo.c). |
0 commit comments