Add exit_river keybinding

Recently, river removed the hardcoded Ctrl+Alt Delete keybinding that
exits river and replaces it with a new `exit_session` request. This adds
support for that request via the new `exit_session` bind. We also added
3 hardcoded default keybinds to: exit river, reload the config, and
open foot. This way, if the config fails to load or is missing, you
should still be able to try reload. I guess you're still SOL if you have
at least one keybind and it's not reload_config, but you do what you can
do.
This commit is contained in:
Ben Buhse 2026-03-06 09:21:07 -06:00
commit 678d0563ed
No known key found for this signature in database
GPG key ID: 7916ACFCD38FD0B4
11 changed files with 293 additions and 108 deletions

View file

@ -32,14 +32,9 @@
The key words "must", "must not", "required", "shall", "shall not",
"should", "should not", "recommended", "may", and "optional" in this
document are to be interpreted as described in IETF RFC 2119.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can only
be done by creating a new major version of the extension.
</description>
<interface name="river_window_manager_v1" version="3">
<interface name="river_window_manager_v1" version="4">
<description summary="window manager global interface">
This global interface should only be advertised to the window manager
process. Only one window management client may be active at a time. The
@ -272,7 +267,7 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="id" type="new_id" interface="river_window_v1"/>
<arg name="id" type="new_id" interface="river_window_v1" summary="new window"/>
</event>
<event name="output">
@ -284,7 +279,7 @@
events as well as a manage_start event after all other new state has
been sent by the server.
</description>
<arg name="id" type="new_id" interface="river_output_v1"/>
<arg name="id" type="new_id" interface="river_output_v1" summary="new output"/>
</event>
<event name="seat">
@ -294,7 +289,7 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="id" type="new_id" interface="river_seat_v1"/>
<arg name="id" type="new_id" interface="river_seat_v1" summary="new seat"/>
</event>
<request name="get_shell_surface">
@ -305,20 +300,34 @@
Providing a wl_surface which already has a role or already has a buffer
attached or committed is a protocol error.
</description>
<arg name="id" type="new_id" interface="river_shell_surface_v1"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="new_id" interface="river_shell_surface_v1"
summary="new river shell surface"/>
<arg name="surface" type="object" interface="wl_surface"
summary="base surface"/>
</request>
<request name="exit_session" since="4">
<description summary="exit the Wayland session">
End the current Wayland session and exit the compositor.
All Wayland clients running in the current session, including
the window manager, will be disconnected.
Window managers should only make this request if the user explicitly
asks to exit the Wayland session, not for example on normal window
manager termination.
</description>
</request>
</interface>
<interface name="river_window_v1" version="3">
<interface name="river_window_v1" version="4">
<description summary="a logical window">
This represents a logical window. For example, a window may correspond to
an xdg_toplevel or Xwayland window.
A newly created window will not be displayed until the window manager
proposes window dimensions with the propose_dimensions request as part of
a manage sequence, the server replies with a dimensions event as part of
a render sequence, and that render sequence is finished.
makes a propose_dimensions or fullscreen request as part of a manage
sequence, the server replies with a dimensions event as part of a render
sequence, and that render sequence is finished.
</description>
<enum name="error">
@ -379,7 +388,7 @@
It is a protocol error to make this request more than once for a single
window.
</description>
<arg name="id" type="new_id" interface="river_node_v1"/>
<arg name="id" type="new_id" interface="river_node_v1" summary="new node"/>
</request>
<event name="dimensions_hint">
@ -398,10 +407,10 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="min_width" type="int"/>
<arg name="min_height" type="int"/>
<arg name="max_width" type="int"/>
<arg name="max_height" type="int"/>
<arg name="min_width" type="int" summary="minimum width"/>
<arg name="min_height" type="int" summary="minimum height"/>
<arg name="max_width" type="int" summary="maximum width"/>
<arg name="max_height" type="int" summary="maximum height"/>
</event>
<event name="dimensions">
@ -417,12 +426,15 @@
This event is sent as part of a render sequence before the render_start
event.
It may be sent due to a propose_dimensions request in a previous manage
sequence or because a window independently decides to change its
dimensions.
It may be sent due to a propose_dimensions or fullscreen request in a
previous manage sequence or because a window independently decides to
change its dimensions.
The window will not be displayed until the first dimensions event is
received and the render sequence is finished.
</description>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="width" type="int" summary="window content width"/>
<arg name="height" type="int" summary="window content height"/>
</event>
<request name="propose_dimensions">
@ -442,10 +454,9 @@
When a propose_dimensions request is made, the server must send a
dimensions event in response as soon as possible. It may not be possible
to send a dimensions event in the very next render sequence if, for
example, the window takes too long to respond to the first proposed
example, the window takes too long to respond to the proposed
dimensions. In this case, the server will send the dimensions event in a
future render sequence. The window will not be displayed until the first
dimensions event is received and the render sequence is finished.
future render sequence.
Note that the dimensions of a river_window_v1 refer to the dimensions of
the window content and are unaffected by the presence of borders or
@ -454,8 +465,8 @@
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="width" type="int" summary="proposed content width"/>
<arg name="height" type="int" summary="proposed content height"/>
</request>
<request name="hide">
@ -496,7 +507,8 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="app_id" type="string" allow-null="true"/>
<arg name="app_id" type="string" allow-null="true"
summary="window application ID"/>
</event>
<event name="title">
@ -510,7 +522,7 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="title" type="string" allow-null="true"/>
<arg name="title" type="string" allow-null="true" summary="window title"/>
</event>
<event name="parent">
@ -530,7 +542,7 @@
state has been sent by the server.
</description>
<arg name="parent" type="object" allow-null="true"
interface="river_window_v1"/>
interface="river_window_v1" summary="parent window, if any"/>
</event>
<enum name="decoration_hint">
@ -555,7 +567,7 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="hint" type="uint" enum="decoration_hint"/>
<arg name="hint" type="uint" enum="decoration_hint" summary="decoration hint"/>
</event>
<request name="use_csd">
@ -621,12 +633,12 @@
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="edges" type="uint" enum="edges"/>
<arg name="width" type="int"/>
<arg name="r" type="uint"/>
<arg name="g" type="uint"/>
<arg name="b" type="uint"/>
<arg name="a" type="uint"/>
<arg name="edges" type="uint" enum="edges" summary="border edges"/>
<arg name="width" type="int" summary="border width"/>
<arg name="r" type="uint" summary="32-bit red value"/>
<arg name="g" type="uint" summary="32-bit green value"/>
<arg name="b" type="uint" summary="32-bit blue value"/>
<arg name="a" type="uint" summary="32-bit alpha value"/>
</request>
<request name="set_tiled">
@ -645,7 +657,7 @@
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="edges" type="uint" enum="edges"/>
<arg name="edges" type="uint" enum="edges" summary="tiled edges"/>
</request>
<request name="get_decoration_above">
@ -657,8 +669,10 @@
Providing a wl_surface which already has a role or already has a buffer
attached or committed is a protocol error.
</description>
<arg name="id" type="new_id" interface="river_decoration_v1"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="new_id" interface="river_decoration_v1"
summary="new decoration surface"/>
<arg name="surface" type="object" interface="wl_surface"
summary="base surface"/>
</request>
<request name="get_decoration_below">
@ -670,8 +684,10 @@
Providing a wl_surface which already has a role or already has a buffer
attached or committed is a protocol error.
</description>
<arg name="id" type="new_id" interface="river_decoration_v1"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="new_id" interface="river_decoration_v1"
summary="new decoration surface"/>
<arg name="surface" type="object" interface="wl_surface"
summary="base surface"/>
</request>
<event name="pointer_move_requested">
@ -690,7 +706,8 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="seat" type="object" interface="river_seat_v1"/>
<arg name="seat" type="object" interface="river_seat_v1"
summary="requested seat"/>
</event>
<event name="pointer_resize_requested">
@ -713,8 +730,10 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="seat" type="object" interface="river_seat_v1"/>
<arg name="edges" type="uint" enum="edges"/>
<arg name="seat" type="object" interface="river_seat_v1"
summary="requested seat"/>
<arg name="edges" type="uint" enum="edges"
summary="requested edges"/>
</event>
<request name="inform_resize_start">
@ -766,7 +785,8 @@
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="caps" type="uint" enum="capabilities"/>
<arg name="caps" type="uint" enum="capabilities"
summary="supported capabilities"/>
</request>
<event name="show_window_menu_requested">
@ -853,7 +873,7 @@
state has been sent by the server.
</description>
<arg name="output" type="object" allow-null="true"
interface="river_output_v1" />
interface="river_output_v1" summary="fullscreen output requested"/>
</event>
<event name="exit_fullscreen_requested">
@ -913,6 +933,12 @@
shall not affect the current position and dimensions of a fullscreen
window.
When a fullscreen request is made, the server must send a dimensions
event in response as soon as possible. It may not be possible to send a
dimensions event in the very next render sequence if, for example, the
window takes too long to respond. In this case, the server will send the
dimensions event in a future render sequence.
The compositor will clip window content, decoration surfaces, and
borders to the given output's dimensions while the window is fullscreen.
The effects of set_clip_box and set_content_clip_box are ignored while
@ -928,7 +954,8 @@
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="output" type="object" interface="river_output_v1"/>
<arg name="output" type="object" interface="river_output_v1"
summary="fullscreen output"/>
</request>
<request name="exit_fullscreen">
@ -981,10 +1008,10 @@
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="x" type="int" summary="x relative to top left window corner"/>
<arg name="y" type="int" summary="y relative to top left window corner"/>
<arg name="width" type="int" summary="clip box width"/>
<arg name="height" type="int" summary="clip box height"/>
</request>
<event name="unreliable_pid" since="2">
@ -1000,7 +1027,7 @@
This event is sent once when the river_window_v1 is created and never
sent again.
</description>
<arg name="unreliable_pid" type="int"/>
<arg name="unreliable_pid" type="int" summary="unreliable PID"/>
</event>
<request name="set_content_clip_box" since="3">
@ -1025,14 +1052,70 @@
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="x" type="int" summary="x relative to top left window corner"/>
<arg name="y" type="int" summary="y relative to top left window corner"/>
<arg name="width" type="int" summary="clip box width"/>
<arg name="height" type="int" summary="clip box height"/>
</request>
<event name="presentation_hint" since="4">
<description summary="presentation hint set by the window">
This event communicates the window's preferred presentation mode.
This event will be followed by a render_start event after all other new
state has been sent by the server.
</description>
<arg name="hint" type="uint" enum="river_output_v1.presentation_mode"
summary="presentation hint"/>
</event>
<event name="identifier" since="4">
<description summary="unique window identifier">
The identifier is a string that contains up to 32 printable ASCII bytes.
The identifier must not be an empty string.
It is compositor policy how the identifier is generated, but the following
properties must be upheld:
1. The identifier must uniquely identify the window. Two windows must not
share the same identifier.
2. The identifier must not be reused. This avoids races around window
creation/destruction when identifiers are used in out-of-band IPC.
If the compositor implements the ext-foreign-toplevel-list-v1 protocol,
the river_window_v1.identifier event must match the corresponding
ext_foreign_toplevel_handle_v1.identifier event.
This event is sent once when the river_window_v1 is created and never
sent again.
</description>
<arg name="identifier" type="string" summary="unique identifier"/>
</event>
<request name="set_dimension_bounds" since="4">
<description summary="recommend maximum dimensions to the window">
Recommend that the window keep its dimensions within a given
maximum width/height. This recommendation is only a hint and the window
may ignore it.
Setting the width and height to 0 indicates that there are no bounds
and is equivalent to having never made this request.
Setting width or height to a negative value is a protocol error.
The server should communicate this hint to an xdg_toplevel window with
the xdg_toplevel.configure_bounds event for example.
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="max_width" type="int" summary="maximum width"/>
<arg name="max_height" type="int" summary="maximum height"/>
</request>
</interface>
<interface name="river_decoration_v1" version="3">
<interface name="river_decoration_v1" version="4">
<description summary="a window decoration">
The rendering order of windows with decorations is follows:
@ -1068,8 +1151,8 @@
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="x" type="int" summary="x relative to top left window corner"/>
<arg name="y" type="int" summary="y relative to top left window corner"/>
</request>
<request name="sync_next_commit">
@ -1088,7 +1171,7 @@
</request>
</interface>
<interface name="river_shell_surface_v1" version="3">
<interface name="river_shell_surface_v1" version="4">
<description summary="a surface for window manager UI">
The window manager might use a shell surface to display a status bar,
background image, desktop notifications, launcher, desktop menu, or
@ -1116,7 +1199,7 @@
It is a protocol error to make this request more than once for a single
shell surface.
</description>
<arg name="id" type="new_id" interface="river_node_v1"/>
<arg name="id" type="new_id" interface="river_node_v1" summary="new node"/>
</request>
<request name="sync_next_commit">
@ -1135,7 +1218,7 @@
</request>
</interface>
<interface name="river_node_v1" version="3">
<interface name="river_node_v1" version="4">
<description summary="a node in the render list">
The render list is a list of nodes that determines the rendering order of
the compositor. Nodes may correspond to windows or shell surfaces. The
@ -1169,8 +1252,8 @@
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="x" type="int" summary="global x coordinate"/>
<arg name="y" type="int" summary="global y coordinate"/>
</request>
<request name="place_top">
@ -1203,7 +1286,8 @@
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="other" type="object" interface="river_node_v1"/>
<arg name="other" type="object" interface="river_node_v1"
summary="other node"/>
</request>
<request name="place_below">
@ -1216,11 +1300,12 @@
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="other" type="object" interface="river_node_v1"/>
<arg name="other" type="object" interface="river_node_v1"
summary="other node"/>
</request>
</interface>
<interface name="river_output_v1" version="3">
<interface name="river_output_v1" version="4">
<description summary="a logical output">
An area in the compositor's logical coordinate space that should be
treated as a single output for window management purposes. This area may
@ -1297,8 +1382,8 @@
cause the areas of multiple logical outputs to overlap when the
corresponding manage_start event is received.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="x" type="int" summary="global x coordinate"/>
<arg name="y" type="int" summary="global y coordinate"/>
</event>
<event name="dimensions">
@ -1317,21 +1402,63 @@
cause the areas of multiple logical outputs to overlap when the
corresponding manage_start event is received.
</description>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="width" type="int" summary="output width"/>
<arg name="height" type="int" summary="output height"/>
</event>
<enum name="error" since="4">
<entry name="invalid_presentation_mode" value="0" since="4"
summary="invalid presentation mode enum value"/>
</enum>
<enum name="presentation_mode" since="4">
<entry name="vsync" value="0">
<description summary="tearing-free presentation">
Output page-flips should be synchronized to the vertical blanking
period, eliminating tearing. This is the default presentation mode.
</description>
</entry>
<entry name="async" value="1">
<description summary="asynchronous presentation">
Output page-flips should not be synchronized to the vertical blanking
period, visual screen tearing may occur.
</description>
</entry>
</enum>
<request name="set_presentation_mode" since="4">
<description summary="set the preferred presentation mode">
Set the preferred presentation mode of the output. The compositor should
always respect the preference of the window manager if possible. If this
request is never made, the preferred presentation mode is vsync.
This request modifies rendering state and may only be made as part of a
render sequence, see the river_window_manager_v1 description.
</description>
<arg name="mode" type="uint" enum="presentation_mode"
summary="preferred presentation mode"/>
</request>
</interface>
<interface name="river_seat_v1" version="3">
<interface name="river_seat_v1" version="4">
<description summary="a window management seat">
This object represents a single user's collection of input devices. It
allows the window manager to route keyboard input to windows, get
high-level information about pointer input, define keyboard and pointer
bindings, etc.
high-level information about pointer input, define pointer bindings, etc.
TODO:
- touch input
- tablet input
For keyboard bindings, see the river-xkb-bindings-v1 protocol.
Since version 4: The cursor surface/shape set by the window manager on the
wl_pointer of this seat is used when no client has pointer focus, for
example during a pointer operation. Since the window manager is allowed to
set cursor surface/shape even when it does not have pointer focus, the
compositor must ignore the serial argument of wl_pointer.set_cursor and
wp_cursor_shape_device_v1.set_shape requests made by the window manager.
The most recent cursor surface/shape set by the window manager is
remembered by the compositor and restored whenever no client has pointer
focus. If the window manager never sets a cursor surface/shape, the
"default" shape is used.
</description>
<request name="destroy" type="destructor">
@ -1390,7 +1517,8 @@
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="window" type="object" interface="river_window_v1"/>
<arg name="window" type="object" interface="river_window_v1"
summary="window to focus"/>
</request>
<request name="focus_shell_surface">
@ -1401,7 +1529,8 @@
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="shell_surface" type="object" interface="river_shell_surface_v1"/>
<arg name="shell_surface" type="object" interface="river_shell_surface_v1"
summary="shell surface to focus"/>
</request>
<request name="clear_focus">
@ -1430,7 +1559,8 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="window" type="object" interface="river_window_v1"/>
<arg name="window" type="object" interface="river_window_v1"
summary="window entered"/>
</event>
<event name="pointer_leave">
@ -1461,7 +1591,8 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="window" type="object" interface="river_window_v1"/>
<arg name="window" type="object" interface="river_window_v1"
summary="window interacted with"/>
</event>
<event name="shell_surface_interaction">
@ -1483,7 +1614,8 @@
This event will be followed by a manage_start event after all other new
state has been sent by the server.
</description>
<arg name="shell_surface" type="object" interface="river_shell_surface_v1"/>
<arg name="shell_surface" type="object" interface="river_shell_surface_v1"
summary="shell surface interacted with"/>
</event>
<request name="op_start_pointer">
@ -1502,6 +1634,11 @@
This request is ignored if an operation is already in progress.
The compositor must ensure that no client has pointer focus from this
seat during the pointer operation. This means that the window manager
has control over the pointer's cursor surface/shape during the pointer
operation. See the river_seat_v1 description.
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
@ -1565,8 +1702,8 @@
<request name="get_pointer_binding">
<description summary="define a new pointer binding">
Define a pointer binding in terms of a pointer button, modifiers, and
other configurable properties.
Define a pointer binding in terms of a pointer button, keyboard
modifiers, and other configurable properties.
The button argument is a Linux input event code defined in the
linux/input-event-codes.h header file (e.g. BTN_RIGHT).
@ -1574,9 +1711,11 @@
The new pointer binding is not enabled until initial configuration is
completed and the enable request is made during a manage sequence.
</description>
<arg name="id" type="new_id" interface="river_pointer_binding_v1"/>
<arg name="id" type="new_id" interface="river_pointer_binding_v1"
summary="new pointer binding"/>
<arg name="button" type="uint" summary="a Linux input event code"/>
<arg name="modifiers" type="uint" enum="modifiers"/>
<arg name="modifiers" type="uint" enum="modifiers"
summary="keyboard modifiers"/>
</request>
<request name="set_xcursor_theme" since="2">
@ -1588,8 +1727,8 @@
Note: The window manager may also wish to set the XCURSOR_THEME and
XCURSOR_SIZE environment variable for programs it starts.
</description>
<arg name="name" type="string"/>
<arg name="size" type="uint"/>
<arg name="name" type="string" summary="xcursor theme name"/>
<arg name="size" type="uint" summary="cursor size"/>
</request>
<event name="pointer_position" since="2">
@ -1604,8 +1743,8 @@
sequence unless there is no change in x/y position since the last time this
event was sent.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="x" type="int" summary="global x coordinate"/>
<arg name="y" type="int" summary="global y coordinate"/>
</event>
<request name="pointer_warp" since="3">
@ -1619,12 +1758,12 @@
This request modifies window management state and may only be made as
part of a manage sequence, see the river_window_manager_v1 description.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="x" type="int" summary="global x coordinate"/>
<arg name="y" type="int" summary="global y coordinate"/>
</request>
</interface>
<interface name="river_pointer_binding_v1" version="3">
<interface name="river_pointer_binding_v1" version="4">
<description summary="configure a pointer binding, receive trigger events">
This object allows the window manager to configure a pointer binding and
receive events when the binding is triggered.