git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit98ecef729f036c368c3bf437ce8b35a907972677
parent4b901e1fa0
authorIsaac Freund <[email protected]>
date2024-06-12 12:54
xkb-keybinds: improve naming and descriptions

Embrace the state machine naming conventions more fully. I think this
gives the best mental model for how this protocol is intended to be
used.

 protocol/river-xkb-keybinds-v1.xml | 142 ++++++++++++++++++++-----------------
 1 file changed, 78 insertions(+), 64 deletions(-)

diff --git a/protocol/river-xkb-keybinds-v1.xml b/protocol/river-xkb-keybinds-v1.xml
index c73cdbf..f4ac2ce 100644
--- a/protocol/river-xkb-keybinds-v1.xml
+++ b/protocol/river-xkb-keybinds-v1.xml
@@ -70,82 +70,89 @@
       </description>
     </request>
 
-    <request name="get_default_mode">
-      <description summary="get the mode object for the default mode">
-        The default mode is the initial active mode.
+    <request name="get_initial_state">
+      <description summary="get the object for the initial state">
+        The initial state is the the state started in before any key events are
+        processed and the state transitioned to when the session is unlocked.
 
         It is a protocol error to make this request more than once.
       </description>
-      <arg name="id" type="new_id" interface="river_xkb_keybind_mode_v1"/>
+      <arg name="id" type="new_id" interface="river_xkb_keybind_state_v1"/>
     </request>
 
-    <request name="get_locked_mode">
-      <description summary="get the mode object for the locked mode">
-        The locked mode is automatically activated when the session is locked.
+    <request name="get_locked_state">
+      <description summary="get the object for the locked state">
+        The locked state is automatically transitioned to when the session is
+        locked.
 
-        When the session is unlocked, the mode that was active prior to locking
-        will be re-activated. If that mode has been destroyed, the default mode
-        will be activated.
+        When the session is unlocked, the initial state is automatically
+        transitioned to.
 
         It is a protocol error to make this request more than once.
       </description>
-      <arg name="id" type="new_id" interface="river_xkb_keybind_mode_v1"/>
+      <arg name="id" type="new_id" interface="river_xkb_keybind_state_v1"/>
     </request>
 
-    <request name="create_custom_mode">
-      <description summary="create a new custom mode">
-        This request creates a new custom mode that may be activated through
-        keybinds created in the default mode, locked mode, or other custom
-        modes.
+    <request name="create_custom_state">
+      <description summary="create a new custom state">
+        This request creates a new custom state that may be transitioned to by
+        keybinds defined in the initial state, locked state, or other custom
+        state.
       </description>
-      <arg name="id" type="new_id" interface="river_xkb_keybind_mode_v1"/>
+      <arg name="id" type="new_id" interface="river_xkb_keybind_state_v1"/>
     </request>
   </interface>
 
-  <interface name="river_xkb_keybind_mode_v1" version="1">
+  <interface name="river_xkb_keybind_state_v1" version="1">
     <description summary="a set of keybinds">
-      A mode is a set of keybinds that are activated/deactivated together.
-      Exactly one keybind mode is active at a time. Modes are transitioned
-      between using keybinds with a "next mode" defined through the
-      river_xkb_keybind_v1.set_next_mode request.
-
-      Modes can be seen as states in a Deterministic Finite Automaton with
-      keybinds as the transitions.
-
-      Key events that do not trigger a keybind in the currently active mode are
-      passed on to whatever client currently has keyboard focus.
-
-      Rationale: this protocol makes modes a first-class concept in order to
-      avoid the need for roundtrips when processing keybinds. If the compositor
-      process were not aware of the full, modal set of keybinds it would be
-      necessary to roundtrip with the keybind manager client after every keybind
-      trigger to allow the client to modify the active set of keybinds before
-      the next key event is processed.
-
-      It is considered acceptable that modifying modes and keybinds may race
-      with incoming keybind triggers. For this reason, modes and keybinds should
-      generally not be modified dynamically in response to keybind triggers.
+      A keybind state is a set of keybinds that are activated/deactivated
+      together. Exactly one keybind state is active at a time. States are
+      transitioned between using keybinds with a state transition defined
+      through the river_xkb_keybind_v1.set_state_transition request.
+
+      Conceptually, keybind states are the states in a Deterministic Finite
+      Automaton or "State Machine" where keybinds are the transitions.
+
+      Keybind states may also be thought of as "modes" similar to the modes in
+      modal text editors.
+
+      Key events that do not trigger a keybind defined in the active keybind
+      state are passed on to whatever client currently has keyboard focus.
+
+      Rationale: using a state machine to describe the key event routing done by
+      the server avoids the need for roundtrips with the keybind manager client
+      when processing keybinds. Without the ability to predefine changes in
+      routing in response to key events it would be necessary to roundtrip on
+      every keybind trigger to allow the keybind manager client to modify the
+      set of active keybinds in response before the next key event is processed.
+      This would require buffering key events on the server side during the
+      roundtrip and have higher global complexity in my opinion.
+
+      It is considered acceptable that modifying the keybind state machine may
+      race with incoming keybind triggers. For this reason, the state machine
+      should generally not be modified dynamically in response to keybind
+      triggers, only in response to manual user re-configuration.
     </description>
 
     <request name="destroy" type="destructor">
-      <description summary="destroy the mode object">
-        This request indicates that the client will no longer use the mode
-        object and that it may be safely destroyed.
+      <description summary="destroy the keybind state object">
+        This request indicates that the client will no longer use the keybind
+        state object and that it may be safely destroyed.
 
-        If the destroyed mode is currently active, either the default mode or
-        the locked mode will be activated.
+        If the destroyed keybind state is currently active, either the initial
+        state or the locked state will be activated.
 
-        The default mode and locked mode are special and should only be
+        The initial state and locked state are special and should only be
         destroyed when the keybind manager client is terminated and is cleaning
         up resources.
       </description>
     </request>
 
-    <request name="create_keybind">
-      <description summary="create a new keybind">
-        Create a new keybind in the mode. The new keybind is not enabled until
-        initial configuration is completed and the river_xkb_keybind_v1.enable
-        request is made.
+    <request name="define_keybind">
+      <description summary="define a new keybind">
+        Define a keybind in the keybind state. The new keybind is not
+        enabled until initial configuration is completed and the
+        river_xkb_keybind_v1.enable request is made.
       </description>
       <arg name="id" type="new_id" interface="river_xkb_keybind_v1"/>
       <arg name="keysym" type="uint" summary="an xkbcommon keysym"/>
@@ -153,19 +160,26 @@
   </interface>
 
   <interface name="river_xkb_keybind_v1" version="1">
-    <description summary="define a keybind and receive trigger events">
-      This object allows the keybind manager to define a keybind and receive
+    <description summary="configure a keybind and receive trigger events">
+      This object allows the keybind manager to configure a keybind and receive
       events when the keybind is triggered.
 
       The new keybind is not enabled until initial configuration is completed
       and the enable request is made.
 
-      If multiple keybinds with identical keysym, modifiers, trigger, and layout
-      override are enabled it is compositor policy which keybind will receive
-      trigger events or if all of the duplicate keybinds receive trigger events.
-      If the duplicate keybinds have differing next modes configured it is
-      compositor policy which mode from the set of possible next modes is
-      transitioned to.
+      If multiple keybinds enabled in the same keybind state would be triggered
+      by the a single physical key event on the compositor side, it is
+      compositor policy which keybind(s) will receive a trigger event or if all
+      of the matched keybinds receive trigger events.
+
+      If the keybinds matched by a single key event have differing state
+      transitions configured it is compositor policy which transition is
+      executed.
+
+      Keybinds might be matched by the same physical key event due to shared
+      keysym, modifiers, and trigger. The layout override feature may also cause
+      the same physical key event to trigger two keybinds with different keysyms
+      and different layout overrides configured.
     </description>
 
     <request name="destroy" type="destructor">
@@ -238,16 +252,16 @@
       <arg name="layout" type="uint" summary="0-indexed xkbcommon layout"/>
     </request>
 
-    <request name="set_next_mode">
-      <description summary="activate the given mode on trigger">
-        Set the mode to be activate when the keybind is triggered.
+    <request name="set_state_transition">
+      <description summary="transition to a given keybind state on trigger">
+        Transition to a given keybind state when the keybind is triggered.
 
-        If this request is not made before the enable request the currently
-        active mode will remain active.
+        If this request is not made before the enable request the current
+        keybind state will not be changed when this keybind is triggered.
 
         It is a protocol error to make this request after the enable request.
       </description>
-      <arg name="mode" type="object" interface="river_xkb_keybind_mode_v1"/>
+      <arg name="mode" type="object" interface="river_xkb_keybind_state_v1"/>
     </request>
 
     <request name="enable">