Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Fix use-after-free and structure casting crashes during device destruction
protocol/river-input-management-v1.xml | 244 +++
protocol/river-layer-shell-v1.xml | 191 ++
protocol/river-libinput-config-v1.xml | 901 ++++++++++
protocol/river-window-management-v1.xml | 1859 ++++++++++++++++++++
protocol/river-xkb-bindings-v1.xml | 314 ++++
protocol/river-xkb-config-v1.xml | 287 +++
protocol/upstream/virtual-keyboard-unstable-v1.xml | 114 ++
protocol/upstream/wlr-layer-shell-unstable-v1.xml | 408 +++++
.../wlr-output-power-management-unstable-v1.xml | 129 ++
src/input_device.rs | 12 +-
src/seat.rs | 2 +-
11 files changed, 4454 insertions(+), 7 deletions(-)
diff --git a/protocol/river-input-management-v1.xml b/protocol/river-input-management-v1.xml
new file mode 100644
index 0000000..e0f5498
--- /dev/null
+++ b/protocol/river-input-management-v1.xml
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="river_input_management_v1">
+ <copyright>
+ SPDX-FileCopyrightText: © 2025 Isaac Freund
+ SPDX-License-Identifier: MIT
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="manage seats and input devices">
+ This protocol supports creating/destroying seats, assigning input devices to
+ seats, and configuring input devices (e.g. setting keyboard repeat rate).
+
+ 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.
+ </description>
+
+ <interface name="river_input_manager_v1" version="2">
+ <description summary="input manager global interface">
+ Input manager global interface.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_destroy" value="0"/>
+ </enum>
+
+ <request name="stop">
+ <description summary="stop sending events">
+ This request indicates that the client no longer wishes to receive
+ events on this object.
+
+ The Wayland protocol is asynchronous, which means the server may send
+ further events until the stop request is processed. The client must wait
+ for a river_input_manager_v1.finished event before destroying this
+ object.
+ </description>
+ </request>
+
+ <event name="finished">
+ <description summary="the server has finished with the input manager">
+ This event indicates that the server will send no further events on this
+ object. The client should destroy the object. See
+ river_input_manager_v1.destroy for more information.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the river_input_manager_v1 object">
+ This request should be called after the finished event has been received
+ to complete destruction of the object.
+
+ It is a protocol error to make this request before the finished event
+ has been received.
+
+ If a client wishes to destroy this object it should send a
+ river_input_manager_v1.stop request and wait for a
+ river_input_manager_v1.finished event. Once the finished event is
+ received it is safe to destroy this object and any other objects created
+ through this interface.
+ </description>
+ </request>
+
+ <request name="create_seat">
+ <description summary="create a new seat">
+ Create a new seat with the given name. Has no effect if a seat with the
+ given name already exists.
+
+ The default seat with name "default" always exists and does not need to
+ be explicitly created.
+ </description>
+ <arg name="name" type="string"/>
+ </request>
+
+ <request name="destroy_seat">
+ <description summary="destroy a seat">
+ Destroy the seat with the given name. Has no effect if a seat with the
+ given name does not exist.
+
+ The default seat with name "default" cannot be destroyed and attempting
+ to destroy it will have no effect.
+
+ Any input devices assigned to the destroyed seat at the time of
+ destruction are assigned to the default seat.
+ </description>
+ <arg name="name" type="string"/>
+ </request>
+
+ <event name="input_device">
+ <description summary="new input device">
+ A new input device has been created.
+ </description>
+ <arg name="id" type="new_id" interface="river_input_device_v1"/>
+ </event>
+ </interface>
+
+ <interface name="river_input_device_v1" version="2">
+ <description summary="an input device">
+ An input device represents a physical keyboard, mouse, touchscreen, or
+ drawing tablet tool. It is assigned to exactly one seat at a time.
+ By default, all input devices are assigned to the default seat.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_repeat_info" value="0"/>
+ <entry name="invalid_scroll_factor" value="1"/>
+ <entry name="invalid_map_to_rectangle" value="2"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the input device object">
+ This request indicates that the client will no longer use the input
+ device object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <event name="removed">
+ <description summary="the input device is removed">
+ This event indicates that the input device has been removed.
+
+ The server will send no further events on this object and ignore any
+ request (other than river_input_device_v1.destroy) made after this event is
+ sent. The client should destroy this object with the
+ river_input_device_v1.destroy request to free up resources.
+ </description>
+ </event>
+
+ <enum name="type">
+ <entry name="keyboard" value="0"/>
+ <entry name="pointer" value="1"/>
+ <entry name="touch" value="2"/>
+ <entry name="tablet" value="3"/>
+ </enum>
+
+ <event name="type">
+ <description summary="the type of the input device">
+ The type of the input device. This event is sent once when the
+ river_input_device_v1 object is created. The device type cannot
+ change during the lifetime of the object.
+ </description>
+ <arg name="type" type="uint" enum="type"/>
+ </event>
+
+ <event name="name">
+ <description summary="the name of the input device">
+ The name of the input device. This event is sent once when the
+ river_input_device_v1 object is created. The device name cannot
+ change during the lifetime of the object.
+ </description>
+ <arg name="name" type="string"/>
+ </event>
+
+ <request name="assign_to_seat">
+ <description summary="assign the input device to a seat">
+ Assign the input device to a seat. All input devices not explicitly
+ assigned to a seat are considered assigned to the default seat.
+
+ Has no effect if a seat with the given name does not exist.
+ </description>
+ <arg name="name" type="string" summary="name of the seat"/>
+ </request>
+
+ <request name="set_repeat_info">
+ <description summary="set keyboard repeat rate and delay">
+ Set repeat rate and delay for a keyboard input device. Has no effect if
+ the device is not a keyboard.
+
+ Negative values for either rate or delay are illegal. A rate of zero
+ will disable any repeating (regardless of the value of delay).
+ </description>
+ <arg name="rate" type="int" summary="rate in key repeats per second"/>
+ <arg name="delay" type="int" summary="delay in milliseconds"/>
+ </request>
+
+ <request name="set_scroll_factor">
+ <description summary="set scroll factor">
+ Set the scroll factor for a pointer input device. Has no effect if the
+ device is not a pointer.
+
+ For example, a factor of 0.5 will make scrolling twice as slow while a
+ factor of 3.0 will make scrolling 3 times as fast.
+
+ Setting a scroll factor less than 0 is a protocol error.
+ </description>
+ <arg name="factor" type="fixed"/>
+ </request>
+
+ <request name="map_to_output">
+ <description summary="map input device to the given output">
+ Map the input device to the given output. Has no effect if the device is
+ not a pointer, touch, or tablet device.
+
+ If mapped to both an output and a rectangle, the rectangle has priority.
+
+ Passing null clears an existing mapping.
+ </description>
+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
+ </request>
+
+ <request name="map_to_rectangle">
+ <description summary="map input device to the given rectangle">
+ Map the input device to the given rectangle in the global compositor
+ coordinate space. Has no effect if the device is not a pointer, touch,
+ or tablet device.
+
+ If mapped to both an output and a rectangle, the rectangle has priority.
+
+ Width and height must be greater than or equal to 0.
+
+ Passing 0 for width or height clears an existing mapping.
+ </description>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <event name="done" since="2">
+ <description summary="all information has been sent">
+ This event is sent after all information about the input device has
+ been sent.
+
+ This allows changes to one or more river_input_device_v1 properties to
+ be seen as atomic, even if they happen via multiple events.
+ </description>
+ </event>
+ </interface>
+</protocol>
diff --git a/protocol/river-layer-shell-v1.xml b/protocol/river-layer-shell-v1.xml
new file mode 100644
index 0000000..0167e9d
--- /dev/null
+++ b/protocol/river-layer-shell-v1.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="river_layer_shell_v1">
+ <copyright>
+ SPDX-FileCopyrightText: © 2025 Isaac Freund
+ SPDX-License-Identifier: MIT
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="optional layer shell support">
+ This protocol allows the river-window-management-v1 window manager to
+ support the wlr-layer-shell-unstable-v1 protocol.
+
+ 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.
+ </description>
+
+ <interface name="river_layer_shell_v1" version="1">
+ <description summary="river layer shell global interface">
+ This global interface should only be advertised to the client if the
+ river_window_manager_v1 global is also advertised. Binding this interface
+ indicates that the window manager supports layer shell.
+
+ If the window manager does not bind this interface, the compositor should
+ not allow clients to map layer surfaces. This can be achieved by
+ closing layer surfaces immediately.
+ </description>
+
+ <enum name="error">
+ <entry name="object_already_created" value="0"
+ summary="the layer_shell_output/seat object was already created."/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the river_layer_shell_v1 object">
+ This request indicates that the client will no longer use the
+ river_layer_shell_v1 object.
+ </description>
+ </request>
+
+ <request name="get_output">
+ <description summary="get layer shell output state">
+ It is a protocol error to make this request more than once for a given
+ river_output_v1 object.
+ </description>
+ <arg name="id" type="new_id" interface="river_layer_shell_output_v1"/>
+ <arg name="output" type="object" interface="river_output_v1"/>
+ </request>
+
+ <request name="get_seat">
+ <description summary="get layer shell seat state">
+ It is a protocol error to make this request more than once for a given
+ river_seat_v1 object.
+ </description>
+ <arg name="id" type="new_id" interface="river_layer_shell_seat_v1"/>
+ <arg name="seat" type="object" interface="river_seat_v1"/>
+ </request>
+ </interface>
+
+ <interface name="river_layer_shell_output_v1" version="1">
+ <description summary="layer shell output state">
+ The lifetime of this object is tied to the corresponding river_output_v1.
+ This object is made inert when the river_output_v1.removed event is sent
+ and should be destroyed.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the object">
+ This request indicates that the client will no longer use the
+ river_layer_shell_output_v1 object and that it may be safely destroyed.
+
+ This request should be made after the river_output_v1.removed event is
+ received to complete destruction of the output.
+ </description>
+ </request>
+
+ <event name="non_exclusive_area">
+ <description summary="area left after subtracting exclusive zones">
+ This event indicates the area of the output remaining after subtracting
+ the exclusive zones of layer surfaces. Exclusive zones are a hint, the
+ window manager is free to ignore this area hint if it wishes.
+
+ The x and y values are in the global coordinate space, not relative to
+ the position of the output.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ <arg name="x" type="int" summary="global x coordinate"/>
+ <arg name="y" type="int" summary="global y coordinate"/>
+ <arg name="width" type="int" summary="area width"/>
+ <arg name="height" type="int" summary="area height"/>
+ </event>
+
+ <request name="set_default">
+ <description summary="Set default output for layer surfaces">
+ Mark this output as the default for new layer surfaces which do not
+ request a specific output themselves. This request overrides any
+ previous set_default request on any river_layer_shell_output_v1 object.
+
+ If no set_default request is made or if the default output is destroyed,
+ the default output is undefined until the next set_default request.
+
+ 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>
+ </request>
+ </interface>
+
+ <interface name="river_layer_shell_seat_v1" version="1">
+ <description summary="layer shell seat state">
+ The lifetime of this object is tied to the corresponding river_seat_v1.
+ This object is made inert when the river_seat_v1.removed event is sent and
+ should be destroyed.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the object">
+ This request indicates that the client will no longer use the
+ river_layer_shell_seat_v1 object and that it may be safely destroyed.
+
+ This request should be made after the river_seat_v1.removed event is
+ received to complete destruction of the seat.
+ </description>
+ </request>
+
+ <event name="focus_exclusive">
+ <description summary="layer shell surface has exclusive focus">
+ A layer shell surface will be given exclusive keyboard focus at the end
+ of the manage sequence in which this event is sent. The window manager
+ may want to update window decorations or similar to indicate that no
+ window is focused.
+
+ Until the focus_non_exclusive or focus_none event is sent, all window
+ manager requests to change focus are ignored.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="focus_non_exclusive">
+ <description summary="layer shell surface wants non-exclusive focus">
+ A layer shell surface will be given non-exclusive keyboard focus at the
+ end of the manage sequence in which this event is sent. The window
+ manager may want to update window decorations or similar to indicate
+ that no window is focused.
+
+ The window manager continues to control focus and may choose to focus a
+ different window/shell surface at any time. If the window manager sets
+ focus during the same manage sequence in which this event is sent, the
+ layer surface will not be focused.
+
+ If the layer surface with non-exclusive focus is closed or the window
+ manager chooses to move focus away from the layer surface, a focus_none
+ event will be sent in the next manage sequence.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="focus_none">
+ <description summary="no layer shell surface has focus">
+ No layer shell surface will have keyboard focus at the end of the manage
+ sequence in which this event is sent. The window manager may want to
+ return focus to whichever window last had focus, for example.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+ </interface>
+</protocol>
diff --git a/protocol/river-libinput-config-v1.xml b/protocol/river-libinput-config-v1.xml
new file mode 100644
index 0000000..46fad57
--- /dev/null
+++ b/protocol/river-libinput-config-v1.xml
@@ -0,0 +1,901 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="river_libinput_config_v1">
+ <copyright>
+ SPDX-FileCopyrightText: © 2025 Isaac Freund
+ SPDX-License-Identifier: MIT
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="configure libinput devices">
+ This protocol exposes libinput device configuration APIs. The libinput
+ documentation should be referred to for detailed information on libinput's
+ behavior.
+
+ Note that the compositor will not be able to expose libinput devices through
+ this protocol when it does not have access to the hardware, for example when
+ running nested in another Wayland compositor or X11 session.
+
+ This protocol is designed so that (hopefully) any backwards compatible
+ change to libinput's API can be matched with a backwards compatible change
+ to this protocol.
+
+ Note: the libinput API uses floating point types (float and double in C)
+ which are not (yet?) natively supported by the Wayland protocol. However,
+ the Wayland protocol does support sending arbitrary bytes through the array
+ argument type. This protocol uses e.g. type="array" summary="double" to
+ indicate a native-endian IEEE-754 64-bit double value.
+
+ 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.
+ </description>
+
+ <interface name="river_libinput_config_v1" version="2">
+ <description summary="libinput config global interface">
+ Global interface for configuring libinput devices. This global should
+ only be advertised if river_input_manager_v1 is advertised as well.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_arg" value="0"
+ summary="invalid enum value or similar"/>
+ <entry name="invalid_destroy" value="1"/>
+ </enum>
+
+ <request name="stop">
+ <description summary="stop sending events">
+ This request indicates that the client no longer wishes to receive
+ events on this object.
+
+ The Wayland protocol is asynchronous, which means the server may send
+ further events until the stop request is processed. The client must wait
+ for a river_libinput_config_v1.finished event before destroying this
+ object.
+ </description>
+ </request>
+
+ <event name="finished">
+ <description summary="the server has finished with the object">
+ This event indicates that the server will send no further events on this
+ object. The client should destroy the object. See
+ river_libinput_config_v1.destroy for more information.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the river_libinput_config_v1 object">
+ This request should be called after the finished event has been received
+ to complete destruction of the object.
+
+ It is a protocol error to make this request before the finished event
+ has been received.
+
+ If a client wishes to destroy this object it should send a
+ river_libinput_config_v1.stop request and wait for a
+ river_libinput_config_v1.finished event. Once the finished event is
+ received it is safe to destroy this object and any other objects created
+ through this interface.
+ </description>
+ </request>
+
+ <event name="libinput_device">
+ <description summary="new libinput device">
+ A new libinput device has been created. Not every river_input_device_v1
+ is necessarily a libinput device as well.
+ </description>
+ <arg name="id" type="new_id" interface="river_libinput_device_v1"/>
+ </event>
+
+ <request name="create_accel_config">
+ <description summary="create a acceleration config">
+ Create a acceleration config which can be applied
+ with river_libinput_device_v1.apply_accel_config.
+ </description>
+ <arg name="id" type="new_id"
+ interface="river_libinput_accel_config_v1"/>
+ <arg name="profile" type="uint"
+ enum="river_libinput_device_v1.accel_profile"/>
+ </request>
+ </interface>
+
+ <interface name="river_libinput_device_v1" version="2">
+ <description summary="a libinput device">
+ In general, *_support events will be sent exactly once directly after the
+ river_libinput_device_v1 is created. *_default events will be sent after
+ *_support events if the config option is supported, and *_current events
+ willl be sent after the *_default events and again whenever the config
+ option is changed.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_arg" value="0"
+ summary="invalid enum value or similar"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the libinput device object">
+ This request indicates that the client will no longer use the input
+ device object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <event name="removed">
+ <description summary="the libinput device is removed">
+ This event indicates that the libinput device has been removed.
+
+ The server will send no further events on this object and ignore any
+ request (other than river_libinput_device_v1.destroy) made after this
+ event is sent. The client should destroy this object with the
+ river_libinput_device_v1.destroy request to free up resources.
+ </description>
+ </event>
+
+ <event name="input_device">
+ <description summary="corresponding river input device">
+ The river_input_device_v1 corresponding to this libinput device.
+ This event will always be the first event sent on the
+ river_libinput_device_v1 object, and it will be sent exactly once.
+ </description>
+ <arg name="device" type="object" interface="river_input_device_v1"/>
+ </event>
+
+ <enum name="send_events_modes" bitfield="true">
+ <entry name="enabled" value="0"/>
+ <entry name="disabled" value="1"/>
+ <entry name="disabled_on_external_mouse" value="2"/>
+ </enum>
+
+ <event name="send_events_support">
+ <description summary="supported send events modes">
+ Supported send events modes.
+ </description>
+ <arg name="modes" type="uint" enum="send_events_modes"/>
+ </event>
+
+ <event name="send_events_default">
+ <description summary="default send events mode">
+ Default send events mode.
+ </description>
+ <arg name="mode" type="uint" enum="send_events_modes"/>
+ </event>
+
+ <event name="send_events_current">
+ <description summary="current send events mode">
+ Current send events mode.
+ </description>
+ <arg name="mode" type="uint" enum="send_events_modes"/>
+ </event>
+
+ <request name="set_send_events">
+ <description summary="set send events mode">
+ Set the send events mode for the device.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="mode" type="uint" enum="send_events_modes"/>
+ </request>
+
+ <enum name="tap_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="tap_support">
+ <description summary="tap-to-click/drag support">
+ The number of fingers supported for tap-to-click/drag.
+ If finger_count is 0, tap-to-click and drag are unsupported.
+ </description>
+ <arg name="finger_count" type="int"/>
+ </event>
+
+ <event name="tap_default">
+ <description summary="default tap-to-click state">
+ Default tap-to-click state.
+ </description>
+ <arg name="state" type="uint" enum="tap_state"/>
+ </event>
+
+ <event name="tap_current">
+ <description summary="current tap-to-click state">
+ Current tap-to-click state.
+ </description>
+ <arg name="state" type="uint" enum="tap_state"/>
+ </event>
+
+ <request name="set_tap">
+ <description summary="enable/disable tap-to-click">
+ Configure tap-to-click on this device, with a default mapping of
+ 1, 2, 3 finger tap mapping to left, right, middle click, respectively.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="tap_state"/>
+ </request>
+
+ <enum name="tap_button_map">
+ <entry name="lrm" value="0"
+ summary="1/2/3 finger tap maps to left/right/middle"/>
+ <entry name="lmr" value="1"
+ summary="1/2/3 finger tap maps to left/middle/right"/>
+ </enum>
+
+ <event name="tap_button_map_default">
+ <description summary="default tap-to-click button map">
+ Default tap-to-click button map.
+ </description>
+ <arg name="button_map" type="uint" enum="tap_button_map"/>
+ </event>
+
+ <event name="tap_button_map_current">
+ <description summary="current tap-to-click button map">
+ Current tap-to-click button map.
+ </description>
+ <arg name="button_map" type="uint" enum="tap_button_map"/>
+ </event>
+
+ <request name="set_tap_button_map">
+ <description summary="set tap-to-click button map">
+ Set the finger number to button number mapping for tap-to-click. The
+ default mapping on most devices is to have a 1, 2 and 3 finger tap to
+ map to the left, right and middle button, respectively.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="button_map" type="uint" enum="tap_button_map"/>
+ </request>
+
+ <enum name="drag_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="drag_default">
+ <description summary="default tap-and-drag state">
+ Default tap-and-drag state.
+ </description>
+ <arg name="state" type="uint" enum="drag_state"/>
+ </event>
+
+ <event name="drag_current">
+ <description summary="current tap-and-drag state">
+ Current tap-and-drag state.
+ </description>
+ <arg name="state" type="uint" enum="drag_state"/>
+ </event>
+
+ <request name="set_drag">
+ <description summary="set tap-and-drag state">
+ Configure tap-and-drag functionality on the device.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="drag_state"/>
+ </request>
+
+ <enum name="drag_lock_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled_timeout" value="1"/>
+ <entry name="enabled_sticky" value="2"/>
+ </enum>
+
+ <event name="drag_lock_default">
+ <description summary="default drag lock state">
+ Default drag lock state.
+ </description>
+ <arg name="state" type="uint" enum="drag_lock_state"/>
+ </event>
+
+ <event name="drag_lock_current">
+ <description summary="current drag lock state">
+ Current drag lock state.
+ </description>
+ <arg name="state" type="uint" enum="drag_lock_state"/>
+ </event>
+
+ <request name="set_drag_lock">
+ <description summary="set drag lock state">
+ Configure drag-lock during tapping on this device. When enabled, a
+ finger may be lifted and put back on the touchpad and the drag process
+ continues. A timeout for lifting the finger is optional. When disabled,
+ lifting the finger during a tap-and-drag will immediately stop the drag.
+ See the libinput documentation for more details.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="drag_lock_state"/>
+ </request>
+
+ <event name="three_finger_drag_support">
+ <description summary="three finger drag support">
+ The number of fingers supported for three/four finger drag.
+ If finger_count is less than 3, three finger drag is unsupported.
+ </description>
+ <arg name="finger_count" type="int"/>
+ </event>
+
+ <enum name="three_finger_drag_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled_3fg" value="1"/>
+ <entry name="enabled_4fg" value="2"/>
+ </enum>
+
+ <event name="three_finger_drag_default">
+ <description summary="default three finger drag state">
+ Default three finger drag state.
+ </description>
+ <arg name="state" type="uint" enum="three_finger_drag_state"/>
+ </event>
+
+ <event name="three_finger_drag_current">
+ <description summary="current three finger drag state">
+ Current three finger drag state.
+ </description>
+ <arg name="state" type="uint" enum="three_finger_drag_state"/>
+ </event>
+
+ <request name="set_three_finger_drag">
+ <description summary="set three finger drag state">
+ Configure three finger drag functionality for the device.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="three_finger_drag_state"/>
+ </request>
+
+ <event name="calibration_matrix_support">
+ <description summary="support for a calibration matrix">
+ A calibration matrix is supported if the supported argument is non-zero.
+ </description>
+ <arg name="supported" type="int" summary="boolean"/>
+ </event>
+
+ <event name="calibration_matrix_default">
+ <description summary="default calibration matrix">
+ Default calibration matrix.
+ </description>
+ <arg name="matrix" type="array" summary="array of 6 floats"/>
+ </event>
+
+ <event name="calibration_matrix_current">
+ <description summary="current calibration matrix">
+ Current calibration matrix.
+ </description>
+ <arg name="matrix" type="array" summary="array of 6 floats"/>
+ </event>
+
+ <request name="set_calibration_matrix">
+ <description summary="set calibration matrix">
+ Set calibration matrix.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="matrix" type="array" summary="array of 6 floats"/>
+ </request>
+
+ <enum name="accel_profile">
+ <entry name="none" value="0"/>
+ <entry name="flat" value="1"/>
+ <entry name="adaptive" value="2"/>
+ <entry name="custom" value="4"/>
+ </enum>
+
+ <enum name="accel_profiles" bitfield="true">
+ <entry name="none" value="0"/>
+ <entry name="flat" value="1"/>
+ <entry name="adaptive" value="2"/>
+ <entry name="custom" value="4"/>
+ </enum>
+
+ <event name="accel_profiles_support">
+ <description summary="supported acceleration profiles">
+ Supported acceleration profiles.
+ </description>
+ <arg name="profiles" type="uint" enum="accel_profiles"/>
+ </event>
+
+ <event name="accel_profile_default">
+ <description summary="default acceleration profile">
+ Default acceleration profile.
+ </description>
+ <arg name="profile" type="uint" enum="accel_profile"/>
+ </event>
+
+ <event name="accel_profile_current">
+ <description summary="current acceleration profile">
+ Current acceleration profile.
+ </description>
+ <arg name="profile" type="uint" enum="accel_profile"/>
+ </event>
+
+ <request name="set_accel_profile">
+ <description summary="set acceleration profile">
+ Set the acceleration profile.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="profile" type="uint" enum="accel_profile"/>
+ </request>
+
+ <event name="accel_speed_default">
+ <description summary="default acceleration speed">
+ Default acceleration speed.
+ </description>
+ <arg name="speed" type="array" summary="double"/>
+ </event>
+
+ <event name="accel_speed_current">
+ <description summary="current acceleration speed">
+ Current acceleration speed.
+ </description>
+ <arg name="speed" type="array" summary="double"/>
+ </event>
+
+ <request name="set_accel_speed">
+ <description summary="set acceleration speed">
+ Set the acceleration speed within a range of [-1, 1], where 0 is
+ the default acceleration for this device, -1 is the slowest acceleration
+ and 1 is the maximum acceleration available on this device.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="speed" type="array" summary="double"/>
+ </request>
+
+ <request name="apply_accel_config">
+ <description summary="apply acceleration config">
+ Apply a pointer accleration config.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="config" type="object" interface="river_libinput_accel_config_v1"/>
+ </request>
+
+ <event name="natural_scroll_support">
+ <description summary="support for natural scroll">
+ Natural scroll is supported if the supported argument is non-zero.
+ </description>
+ <arg name="supported" type="int" summary="boolean"/>
+ </event>
+
+ <enum name="natural_scroll_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="natural_scroll_default">
+ <description summary="default natural scroll">
+ Default natural scroll.
+ </description>
+ <arg name="state" type="uint" enum="natural_scroll_state"/>
+ </event>
+
+ <event name="natural_scroll_current">
+ <description summary="current natural scroll state">
+ Current natural scroll.
+ </description>
+ <arg name="state" type="uint" enum="natural_scroll_state"/>
+ </event>
+
+ <request name="set_natural_scroll">
+ <description summary="set natural scroll state">
+ Set natural scroll state.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="natural_scroll_state"/>
+ </request>
+
+ <event name="left_handed_support">
+ <description summary="support for left-handed mode">
+ Left-handed mode is supported if the supported argument is non-zero.
+ </description>
+ <arg name="supported" type="int" summary="boolean"/>
+ </event>
+
+ <enum name="left_handed_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="left_handed_default">
+ <description summary="default left-handed mode">
+ Default left-handed mode.
+ </description>
+ <arg name="state" type="uint" enum="left_handed_state"/>
+ </event>
+
+ <event name="left_handed_current">
+ <description summary="current left-handed mode state">
+ Current left-handed mode.
+ </description>
+ <arg name="state" type="uint" enum="left_handed_state"/>
+ </event>
+
+ <request name="set_left_handed">
+ <description summary="set left-handed mode state">
+ Set left-handed mode state.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="left_handed_state"/>
+ </request>
+
+ <enum name="click_method">
+ <entry name="none" value="0"/>
+ <entry name="button_areas" value="1"/>
+ <entry name="clickfinger" value="2"/>
+ </enum>
+
+ <enum name="click_methods" bitfield="true">
+ <entry name="none" value="0"/>
+ <entry name="button_areas" value="1"/>
+ <entry name="clickfinger" value="2"/>
+ </enum>
+
+ <event name="click_method_support">
+ <description summary="supported click methods">
+ The click methods supported by the device.
+ </description>
+ <arg name="methods" type="uint" enum="click_methods"/>
+ </event>
+
+ <event name="click_method_default">
+ <description summary="default click method">
+ Default click method.
+ </description>
+ <arg name="method" type="uint" enum="click_method"/>
+ </event>
+
+ <event name="click_method_current">
+ <description summary="current click method">
+ Current click method.
+ </description>
+ <arg name="method" type="uint" enum="click_method"/>
+ </event>
+
+ <request name="set_click_method">
+ <description summary="set click method">
+ Set click method.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="method" type="uint" enum="click_method"/>
+ </request>
+
+ <enum name="clickfinger_button_map">
+ <entry name="lrm" value="0"/>
+ <entry name="lmr" value="1"/>
+ </enum>
+
+ <event name="clickfinger_button_map_default">
+ <description summary="default clickfinger button map">
+ Default clickfinger button map.
+ Supported if click_methods.clickfinger is supported.
+ </description>
+ <arg name="button_map" type="uint" enum="clickfinger_button_map"/>
+ </event>
+
+ <event name="clickfinger_button_map_current">
+ <description summary="current clickfinger button map">
+ Current clickfinger button map.
+ Supported if click_methods.clickfinger is supported.
+ </description>
+ <arg name="button_map" type="uint" enum="clickfinger_button_map"/>
+ </event>
+
+ <request name="set_clickfinger_button_map">
+ <description summary="set clickfinger button map">
+ Set clickfinger button map.
+ Supported if click_methods.clickfinger is supported.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="button_map" type="uint" enum="clickfinger_button_map"/>
+ </request>
+
+ <event name="middle_emulation_support">
+ <description summary="support for middle mouse button emulation">
+ Middle mouse button emulation is supported if the supported argument is
+ non-zero.
+ </description>
+ <arg name="supported" type="int" summary="boolean"/>
+ </event>
+
+ <enum name="middle_emulation_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="middle_emulation_default">
+ <description summary="default middle mouse button emulation">
+ Default middle mouse button emulation.
+ </description>
+ <arg name="state" type="uint" enum="middle_emulation_state"/>
+ </event>
+
+ <event name="middle_emulation_current">
+ <description summary="current middle mouse button emulation state">
+ Current middle mouse button emulation.
+ </description>
+ <arg name="state" type="uint" enum="middle_emulation_state"/>
+ </event>
+
+ <request name="set_middle_emulation">
+ <description summary="set middle mouse button emulation state">
+ Set middle mouse button emulation state.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="middle_emulation_state"/>
+ </request>
+
+ <enum name="scroll_method">
+ <entry name="no_scroll" value="0"/>
+ <entry name="two_finger" value="1"/>
+ <entry name="edge" value="2"/>
+ <entry name="on_button_down" value="4"/>
+ </enum>
+
+ <enum name="scroll_methods" bitfield="true">
+ <entry name="no_scroll" value="0"/>
+ <entry name="two_finger" value="1"/>
+ <entry name="edge" value="2"/>
+ <entry name="on_button_down" value="4"/>
+ </enum>
+
+ <event name="scroll_method_support">
+ <description summary="supported scroll methods">
+ The scroll methods supported by the device.
+ </description>
+ <arg name="methods" type="uint" enum="scroll_methods"/>
+ </event>
+
+ <event name="scroll_method_default">
+ <description summary="default scroll method">
+ Default scroll method.
+ </description>
+ <arg name="method" type="uint" enum="scroll_method"/>
+ </event>
+
+ <event name="scroll_method_current">
+ <description summary="current scroll method">
+ Current scroll method.
+ </description>
+ <arg name="method" type="uint" enum="scroll_method"/>
+ </event>
+
+ <request name="set_scroll_method">
+ <description summary="set scroll method">
+ Set scroll method.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="method" type="uint" enum="scroll_method"/>
+ </request>
+
+ <event name="scroll_button_default">
+ <description summary="default scroll button">
+ Default scroll button.
+ Supported if scroll_methods.on_button_down is supported.
+ </description>
+ <arg name="button" type="uint"/>
+ </event>
+
+ <event name="scroll_button_current">
+ <description summary="current scroll button">
+ Current scroll button.
+ Supported if scroll_methods.on_button_down is supported.
+ </description>
+ <arg name="button" type="uint"/>
+ </event>
+
+ <request name="set_scroll_button">
+ <description summary="set scroll button">
+ Set scroll button.
+ Supported if scroll_methods.on_button_down is supported.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="button" type="uint"/>
+ </request>
+
+ <enum name="scroll_button_lock_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="scroll_button_lock_default">
+ <description summary="default scroll button lock state">
+ Default scroll button lock state.
+ Supported if scroll_methods.on_button_down is supported.
+ </description>
+ <arg name="state" type="uint" enum="scroll_button_lock_state"/>
+ </event>
+
+ <event name="scroll_button_lock_current">
+ <description summary="current scroll button lock state">
+ Current scroll button lock state.
+ Supported if scroll_methods.on_button_down is supported.
+ </description>
+ <arg name="state" type="uint" enum="scroll_button_lock_state"/>
+ </event>
+
+ <request name="set_scroll_button_lock">
+ <description summary="set scroll button lock state">
+ Set scroll button lock state.
+ Supported if scroll_methods.on_button_down is supported.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="scroll_button_lock_state"/>
+ </request>
+
+ <event name="dwt_support">
+ <description summary="support for disable-while-typing">
+ Disable-while-typing is supported if the supported argument is
+ non-zero.
+ </description>
+ <arg name="supported" type="int" summary="boolean"/>
+ </event>
+
+ <enum name="dwt_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="dwt_default">
+ <description summary="default disable-while-typing state">
+ Default disable-while-typing state.
+ </description>
+ <arg name="state" type="uint" enum="dwt_state"/>
+ </event>
+
+ <event name="dwt_current">
+ <description summary="current disable-while-typing state">
+ Current disable-while-typing state.
+ </description>
+ <arg name="state" type="uint" enum="dwt_state"/>
+ </event>
+
+ <request name="set_dwt">
+ <description summary="set disable-while-typing state">
+ Set disable-while-typing state.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="dwt_state"/>
+ </request>
+
+ <event name="dwtp_support">
+ <description summary="support for disable-while-trackpointing">
+ Disable-while-trackpointing is supported if the supported argument is
+ non-zero.
+ </description>
+ <arg name="supported" type="int" summary="boolean"/>
+ </event>
+
+ <enum name="dwtp_state">
+ <entry name="disabled" value="0"/>
+ <entry name="enabled" value="1"/>
+ </enum>
+
+ <event name="dwtp_default">
+ <description summary="default disable-while-trackpointing state">
+ Default disable-while-trackpointing state.
+ </description>
+ <arg name="state" type="uint" enum="dwtp_state"/>
+ </event>
+
+ <event name="dwtp_current">
+ <description summary="current disable-while-trackpointing state">
+ Current disable-while-trackpointing state.
+ </description>
+ <arg name="state" type="uint" enum="dwtp_state"/>
+ </event>
+
+ <request name="set_dwtp">
+ <description summary="set disable-while-trackpointing state">
+ Set disable-while-trackpointing state.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="state" type="uint" enum="dwtp_state"/>
+ </request>
+
+ <event name="rotation_support">
+ <description summary="support for rotation">
+ Rotation is supported if the supported argument is non-zero.
+ </description>
+ <arg name="supported" type="int" summary="boolean"/>
+ </event>
+
+ <event name="rotation_default">
+ <description summary="default rotation angle">
+ Default rotation angle.
+ </description>
+ <arg name="angle" type="uint"/>
+ </event>
+
+ <event name="rotation_current">
+ <description summary="current rotation angle">
+ Current rotation angle.
+ </description>
+ <arg name="angle" type="uint"/>
+ </event>
+
+ <request name="set_rotation">
+ <description summary="set rotation angle">
+ Set rotation angle in degrees clockwise off the logical neutral
+ position. Angle must be in the range [0-360).
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="angle" type="uint"/>
+ </request>
+
+ <event name="done" since="2">
+ <description summary="all information has been sent">
+ This event is sent after all information about the libinput device has
+ been sent.
+
+ This allows changes to one or more river_libinput_device_v1 properties
+ to be seen as atomic, even if they happen via multiple events.
+ </description>
+ </event>
+ </interface>
+
+ <interface name="river_libinput_accel_config_v1" version="1">
+ <description summary="acceleration config">
+ The result returned by libinput on setting configuration for a device.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_arg" value="0"
+ summary="invalid enum value or similar"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the accel object">
+ This request indicates that the client will no longer use the accel
+ config object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <enum name="accel_type">
+ <entry name="fallback" value="0"/>
+ <entry name="motion" value="1"/>
+ <entry name="scroll" value="2"/>
+ </enum>
+
+ <request name="set_points">
+ <description summary="define custom acceleration function">
+ Defines the acceleration function for a given movement type
+ in an acceleration configuration with custom accel profile.
+ </description>
+ <arg name="result" type="new_id" interface="river_libinput_result_v1"/>
+ <arg name="type" type="uint" enum="accel_type"/>
+ <arg name="step" type="array" summary="double"/>
+ <arg name="points" type="array" summary="array of doubles"/>
+ </request>
+ </interface>
+
+ <interface name="river_libinput_result_v1" version="1">
+ <description summary="config application result">
+ The result returned by libinput on setting configuration for a device.
+ </description>
+
+ <event name="success" type="destructor">
+ <description summary="config success">
+ The configuration was successfully applied to the device.
+ </description>
+ </event>
+
+ <event name="unsupported" type="destructor">
+ <description summary="config unsupported">
+ The configuration is unsupported by the device and was ignored.
+ </description>
+ </event>
+
+ <event name="invalid" type="destructor">
+ <description summary="config invalid">
+ The configuration is invalid and was ignored.
+ </description>
+ </event>
+ </interface>
+</protocol>
diff --git a/protocol/river-window-management-v1.xml b/protocol/river-window-management-v1.xml
new file mode 100644
index 0000000..f835971
--- /dev/null
+++ b/protocol/river-window-management-v1.xml
@@ -0,0 +1,1859 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="river_window_management_v1">
+ <copyright>
+ SPDX-FileCopyrightText: © 2024 Isaac Freund
+ SPDX-License-Identifier: MIT
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="frame-perfect window management">
+ This protocol allows a single "window manager" client to determine the
+ window management policy of the compositor. State is globally
+ double-buffered allowing for frame perfect state changes involving multiple
+ windows.
+
+ 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.
+ </description>
+
+ <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
+ compositor should use the unavailable event if necessary to enforce this.
+
+ There are two disjoint categories of state managed by this protocol:
+
+ Window management state influences the communication between the
+ compositor and individual windows (e.g. xdg_toplevels). Window management
+ state includes window dimensions, fullscreen state, keyboard focus,
+ keyboard bindings, and more.
+
+ Rendering state only affects the rendered output of the compositor and
+ does not influence communication between the compositor and individual
+ windows. Rendering state includes the position and rendering order of
+ windows, shell surfaces, decoration surfaces, borders, and more.
+
+ Window management state may only be modified by the window manager as part
+ of a manage sequence. A manage sequence is started with the manage_start
+ event and ended with the manage_finish request. It is a protocol error to
+ modify window management state outside of a manage sequence.
+
+ A manage sequence is always followed by at least one render sequence. A
+ render sequence is started with the render_start event and ended with the
+ render_finish request.
+
+ Rendering state may be modified by the window manager during a manage
+ sequence or a render sequence. Regardless of when the rendering state is
+ modified, it is applied with the next render_finish request. It is a
+ protocol error to modify rendering state outside of a manage or render
+ sequence.
+
+ The server will start a manage sequence by sending new state and the
+ manage_start event as soon as possible whenever there is a change in state
+ that must be communicated with the window manager.
+
+ If the window manager client needs to ensure a manage sequence is started
+ due to a state change the compositor is not aware of, it may send the
+ manage_dirty request.
+
+ The server will start a render sequence by sending new state and the
+ render_start event as soon as possible whenever there is a change in
+ window dimensions that must be communicated with the window manager.
+ Multiple render sequences may be made consecutively without a manage
+ sequence in between, for example if a window independently changes its own
+ dimensions.
+
+ To summarize, the main loop of this protocol is as follows:
+
+ 1. The server sends events indicating all changes since the last
+ manage sequence followed by the manage_start event.
+
+ 2. The client sends requests modifying window management state or
+ rendering state (as defined above) followed by the manage_finish
+ request.
+
+ 3. The server sends new state to windows and waits for responses.
+
+ 4. The server sends new window dimensions to the client followed by the
+ render_start event.
+
+ 5. The client sends requests modifying rendering state (as defined above)
+ followed by the render_finish request.
+
+ 6. If window dimensions change, loop back to step 4.
+ If state that requires a manage sequence changes or if the client makes
+ a manage_dirty request, loop back to step 1.
+
+ For the purposes of frame perfection, the server may delay rendering new
+ state committed by the windows in step 3 until after step 5 is finished.
+
+ It is a protocol error for the client to make a manage_finish or
+ render_finish request that violates this ordering.
+ </description>
+
+ <enum name="error">
+ <entry name="sequence_order" value="0"
+ summary="request violates manage/render sequence ordering"/>
+ <entry name="role" value="1"
+ summary="given wl_surface already has a role"/>
+ <entry name="unresponsive" value="2"
+ summary="window manager unresponsive"/>
+ </enum>
+
+ <event name="unavailable">
+ <description summary="window management unavailable">
+ This event indicates that window management is not available to the
+ client, perhaps due to another window management client already running.
+ The circumstances causing this event to be sent are compositor policy.
+
+ If sent, this event is guaranteed to be the first and only event sent by
+ the server.
+
+ The server will send no further events on this object. The client should
+ destroy this object and all objects created through this interface.
+ </description>
+ </event>
+
+ <request name="stop">
+ <description summary="stop sending events">
+ This request indicates that the client no longer wishes to receive
+ events on this object.
+
+ The Wayland protocol is asynchronous, which means the server may send
+ further events until the stop request is processed. The client must wait
+ for a river_window_manager_v1.finished event before destroying this
+ object.
+ </description>
+ </request>
+
+ <event name="finished">
+ <description summary="the server has finished with the window manager">
+ This event indicates that the server will send no further events on this
+ object. The client should destroy the object. See
+ river_window_manager_v1.destroy for more information.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the river_window_manager_v1 object">
+ This request should be called after the finished event has been received
+ to complete destruction of the object.
+
+ If a client wishes to destroy this object it should send a
+ river_window_manager_v1.stop request and wait for a
+ river_window_manager_v1.finished event. Once the finished event is
+ received it is safe to destroy this object and any other objects created
+ through this interface.
+ </description>
+ </request>
+
+ <event name="manage_start">
+ <description summary="start a manage sequence">
+ This event indicates that the server has sent events indicating all
+ state changes since the last manage sequence.
+
+ In response to this event, the client should make requests modifying
+ window management state as it chooses. Then, the client must make the
+ manage_finish request.
+
+ See the description of the river_window_manager_v1 interface for a
+ complete overview of the manage/render sequence loop.
+ </description>
+ </event>
+
+ <request name="manage_finish">
+ <description summary="finish a manage sequence">
+ This request indicates that the client has made all changes to window
+ management state it wishes to include in the current manage sequence and
+ that the server should atomically send these state changes to the
+ windows and continue with the manage sequence.
+
+ After sending this request, it is a protocol error for the client to
+ make further changes to window management state until the next
+ manage_start event is received.
+
+ See the description of the river_window_manager_v1 interface for a
+ complete overview of the manage/render sequence loop.
+ </description>
+ </request>
+
+ <request name="manage_dirty">
+ <description summary="ensure a manage sequence is started">
+ This request ensures a manage sequence is started and that a
+ manage_start event is sent by the server. If this request is made during
+ an ongoing manage sequence, a new manage sequence will be started as
+ soon as the current one is completed.
+
+ The client may want to use this request due to an internal state change
+ that the compositor is not aware of (e.g. a dbus event) which should
+ affect window management or rendering state.
+ </description>
+ </request>
+
+ <event name="render_start">
+ <description summary="start a render sequence">
+ This event indicates that the server has sent all
+ river_window_v1.dimensions events necessary.
+
+ In response to this event, the client should make requests modifying
+ rendering state as it chooses. Then, the client must make the
+ render_finish request.
+
+ See the description of the river_window_manager_v1 interface for a
+ complete overview of the manage/render sequence loop.
+ </description>
+ </event>
+
+ <request name="render_finish">
+ <description summary="finish a render sequence">
+ This request indicates that the client has made all changes to rendering
+ state it wishes to include in the current manage sequence and that the
+ server should atomically apply and display these state changes to the
+ user.
+
+ After sending this request, it is a protocol error for the client to
+ make further changes to rendering state until the next manage_start or
+ render_start event is received, whichever comes first.
+
+ See the description of the river_window_manager_v1 interface for a
+ complete overview of the manage/render sequence loop.
+ </description>
+ </request>
+
+ <event name="session_locked">
+ <description summary="the session has been locked">
+ This event indicates that the session has been locked.
+
+ The window manager may wish to restrict which key bindings are available
+ while locked or otherwise use this information.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="session_unlocked">
+ <description summary="the session has been unlocked">
+ This event indicates that the session has been unlocked.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="window">
+ <description summary="new window">
+ A new window has been created.
+
+ 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" summary="new window"/>
+ </event>
+
+ <event name="output">
+ <description summary="new output">
+ A new logical output has been created, perhaps due to a new physical
+ monitor being plugged in or perhaps due to a change in configuration.
+
+ This event will be followed by river_output_v1.position and dimensions
+ 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" summary="new output"/>
+ </event>
+
+ <event name="seat">
+ <description summary="new seat">
+ A new seat has been created.
+
+ 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" summary="new seat"/>
+ </event>
+
+ <request name="get_shell_surface">
+ <description summary="assign the river_shell_surface_v1 surface role">
+ Create a new shell surface for window manager UI and assign the
+ river_shell_surface_v1 role to the surface.
+
+ 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"
+ 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="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
+ 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">
+ <entry name="node_exists" value="0"
+ summary="window already has a node object"/>
+ <entry name="invalid_dimensions" value="1"
+ summary="proposed dimensions out of bounds"/>
+ <entry name="invalid_border" value="2"
+ summary="invalid arg to set_borders"/>
+ <entry name="invalid_clip_box" value="3"
+ summary="invalid arg to set_clip_box"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the window object">
+ This request indicates that the client will no longer use the window
+ object and that it may be safely destroyed.
+
+ This request should be made after the river_window_v1.closed event or
+ river_window_manager_v1.finished is received to complete destruction of
+ the window.
+ </description>
+ </request>
+
+ <event name="closed">
+ <description summary="the window has been closed">
+ The window has been closed by the server, perhaps due to an
+ xdg_toplevel.close request or similar.
+
+ The server will send no further events on this object and ignore any
+ request other than river_window_v1.destroy made after this event is
+ sent. The client should destroy this object with the
+ river_window_v1.destroy request to free up resources.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <request name="close">
+ <description summary="request that the window be closed">
+ Request that the window be closed. The window may ignore this request or
+ only close after some delay, perhaps opening a dialog asking the user to
+ save their work or similar.
+
+ The server will send a river_window_v1.closed event if/when the window
+ has been closed.
+
+ 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>
+ </request>
+
+ <request name="get_node">
+ <description summary="get the window's render list node">
+ Get the node in the render list corresponding to the window.
+
+ 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" summary="new node"/>
+ </request>
+
+ <event name="dimensions_hint">
+ <description summary="the window's preferred min/max dimensions">
+ This event informs the window manager of the window's preferred min/max
+ dimensions. These preferences are a hint, and the window manager is free
+ to propose dimensions outside of these bounds.
+
+ All min/max width/height values must be strictly greater than or equal
+ to 0. A value of 0 indicates that the window has no preference for that
+ value.
+
+ The min_width/min_height must be strictly less than or equal to the
+ max_width/max_height.
+
+ 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" 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">
+ <description summary="window dimensions">
+ This event indicates the dimensions of the window in the compositor's
+ logical coordinate space. The width and height must be strictly greater
+ than zero.
+
+ 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
+ decoration surfaces.
+
+ This event is sent as part of a render sequence before the render_start
+ event.
+
+ 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" summary="window content width"/>
+ <arg name="height" type="int" summary="window content height"/>
+ </event>
+
+ <request name="propose_dimensions">
+ <description summary="propose window dimensions">
+ This request proposes dimensions for the window in the compositor's
+ logical coordinate space.
+
+ The width and height must be greater than or equal to zero. If the width
+ or height is zero the window will be allowed to decide its own
+ dimensions.
+
+ The window may not take the exact dimensions proposed. The actual
+ dimensions taken by the window will be sent in a subsequent
+ river_window_v1.dimensions event. For example, a terminal emulator may
+ only allow dimensions that are multiple of the cell size.
+
+ 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 proposed
+ dimensions. In this case, the server will send the dimensions event in a
+ 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
+ decoration surfaces.
+
+ 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" summary="proposed content width"/>
+ <arg name="height" type="int" summary="proposed content height"/>
+ </request>
+
+ <request name="hide">
+ <description summary="request that the window be hidden">
+ Request that the window be hidden. Has no effect if the window is
+ already hidden. Hides any window borders and decorations as well.
+
+ Newly created windows are considered shown unless explicitly hidden with
+ the hide request.
+
+ This request modifies rendering state and may only be made as part of a
+ render sequence, see the river_window_manager_v1 description.
+ </description>
+ </request>
+
+ <request name="show">
+ <description summary="request that the window be shown">
+ Request that the window be shown. Has no effect if the window is not
+ hidden. Does not guarantee that the window is visible as it may be
+ completely obscured by other windows placed above it for example.
+
+ Newly created windows are considered shown unless explicitly hidden with
+ the hide request.
+
+ This request modifies rendering state and may only be made as part of a
+ render sequence, see the river_window_manager_v1 description.
+ </description>
+ </request>
+
+ <event name="app_id">
+ <description summary="the window set an application ID">
+ The window set an application ID.
+
+ The app_id argument will be null if the window has never set an
+ application ID or if the window cleared its application ID. (Xwayland
+ windows may do this for example, though xdg-toplevels may not.)
+
+ 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"
+ summary="window application ID"/>
+ </event>
+
+ <event name="title">
+ <description summary="the window set a title">
+ The window set a title.
+
+ The title argument will be null if the window has never set a title or
+ if the window cleared its title. (Xwayland windows may do this for
+ example, though xdg-toplevels may not.)
+
+ 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" summary="window title"/>
+ </event>
+
+ <event name="parent">
+ <description summary="the window set a parent">
+ The window set a parent window. If this event is never received or if
+ the parent argument is null then the window has no parent.
+
+ A surface with a parent set might be a dialog, file picker, or similar
+ for the parent window.
+
+ Child windows should generally be rendered directly above their parent.
+
+ The compositor must guarantee that there are no loops in the window
+ tree: a parent must not be the descendant of one of its children.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ <arg name="parent" type="object" allow-null="true"
+ interface="river_window_v1" summary="parent window, if any"/>
+ </event>
+
+ <enum name="decoration_hint">
+ <entry name="only_supports_csd" value="0"
+ summary="only supports client side decoration"/>
+ <entry name="prefers_csd" value="1"
+ summary="client side decoration preferred, both CSD and SSD supported"/>
+ <entry name="prefers_ssd" value="2"
+ summary="server side decoration preferred, both CSD and SSD supported"/>
+ <entry name="no_preference" value="3"
+ summary="no preference, both CSD and SSD supported"/>
+ </enum>
+
+ <event name="decoration_hint">
+ <description summary="supported/preferred decoration style">
+ Information from the window about the supported and preferred client
+ side/server side decoration options.
+
+ This event may be sent multiple times over the lifetime of the window if
+ the window changes its preferences.
+
+ 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" summary="decoration hint"/>
+ </event>
+
+ <request name="use_csd">
+ <description summary="tell the client to use CSD">
+ Tell the client to use client side decoration and draw its own title
+ bar, borders, etc.
+
+ This is the default if neither this request nor the use_ssd request is
+ ever made.
+
+ 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>
+ </request>
+
+ <request name="use_ssd">
+ <description summary="tell the client to use SSD">
+ Tell the client to use server side decoration and not draw any client
+ side decorations.
+
+ This request will have no effect if the client only supports client side
+ decoration, see the decoration_hint event.
+
+ 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>
+ </request>
+
+ <enum name="edges" bitfield="true">
+ <entry name="none" value="0"/>
+ <entry name="top" value="1"/>
+ <entry name="bottom" value="2"/>
+ <entry name="left" value="4"/>
+ <entry name="right" value="8"/>
+ </enum>
+
+ <request name="set_borders">
+ <description summary="set window borders">
+ This request decorates the window with borders drawn by the compositor
+ on the specified edges of the window. Borders are drawn above the window
+ content.
+
+ Corners are drawn only between borders on adjacent edges. If e.g. the
+ left edge has a border and the top edge does not, the border drawn on
+ the left edge will not extend vertically beyond the top edge of the
+ window.
+
+ Borders are not drawn while the window is fullscreen.
+
+ The color is defined by four 32-bit RGBA values. Unless specified in
+ another protocol extension, the RGBA values use pre-multiplied alpha.
+
+ The valid range for the RGBA values is from 0x00000000 to 0xffffffff.
+ These values are interpreted as a percentage:
+ - 0x00000000 means 0% of the given color component
+ - 0xffffffff means 100% of the given color component
+
+ Setting the edges to none or the width to 0 disables the borders.
+ Setting a negative width is a protocol error.
+
+ This request completely overrides all previous set_borders requests.
+ Only the most recent set_borders request has an effect.
+
+ Note that the position/dimensions of a river_window_v1 refer to the
+ position/dimensions of the window content and are unaffected by the
+ presence of borders or decoration surfaces.
+
+ 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" 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">
+ <description summary="set window tiled state">
+ Inform the window that it is part of a tiled layout and adjacent to
+ other elements in the tiled layout on the given edges.
+
+ The window should use this information to change the style of its client
+ side decorations and avoid drawing e.g. drop shadows outside of the
+ window dimensions on the tiled edges.
+
+ Setting the edges argument to none informs the window that it is not
+ part of a tiled layout. If this request is never made, the window is
+ informed that it is not part of a tiled layout.
+
+ 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" summary="tiled edges"/>
+ </request>
+
+ <request name="get_decoration_above">
+ <description summary="create a decoration above the window in z-order">
+ Create a decoration surface and assign the river_decoration_v1 role to
+ the surface. The created decoration is placed above the window in
+ rendering order, see the description of river_decoration_v1.
+
+ 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"
+ summary="new decoration surface"/>
+ <arg name="surface" type="object" interface="wl_surface"
+ summary="base surface"/>
+ </request>
+
+ <request name="get_decoration_below">
+ <description summary="create a decoration below the window in z-order">
+ Create a decoration surface and assign the river_decoration_v1 role to
+ the surface. The created decoration is placed below the window in
+ rendering order, see the description of river_decoration_v1.
+
+ 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"
+ summary="new decoration surface"/>
+ <arg name="surface" type="object" interface="wl_surface"
+ summary="base surface"/>
+ </request>
+
+ <event name="pointer_move_requested">
+ <description summary="window requested interactive pointer move">
+ This event informs the window manager that the window has requested to
+ be interactively moved using the pointer. The seat argument indicates the
+ seat for the move.
+
+ The xdg-shell protocol for example allows windows to request that an
+ interactive move be started, perhaps when a client-side rendered
+ titlebar is dragged.
+
+ The window manager may use the river_seat_v1.op_start_pointer request to
+ interactively move the window or ignore this event entirely.
+
+ 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"
+ summary="requested seat"/>
+ </event>
+
+ <event name="pointer_resize_requested">
+ <description summary="window requested interactive pointer resize">
+ This event informs the window manager that the window has requested to
+ be interactively resized using the pointer. The seat argument indicates
+ the seat for the resize.
+
+ The edges argument indicates which edges the window has requested to be
+ resized from. The edges argument will never be none and will never have
+ both top and bottom or both left and right edges set.
+
+ The xdg-shell protocol for example allows windows to request that an
+ interactive resize be started, perhaps when the corner of client-side
+ rendered decorations is dragged.
+
+ The window manager may use the river_seat_v1.op_start_pointer request to
+ interactively resize the window or ignore this event entirely.
+
+ 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"
+ summary="requested seat"/>
+ <arg name="edges" type="uint" enum="edges"
+ summary="requested edges"/>
+ </event>
+
+ <request name="inform_resize_start">
+ <description summary="inform the window it is being resized">
+ Inform the window that it is being resized. The window manager should
+ use this request to inform windows that are the target of an interactive
+ resize for example.
+
+ The window manager remains responsible for handling the position and
+ dimensions of the window while it is resizing.
+
+ 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>
+ </request>
+
+ <request name="inform_resize_end">
+ <description summary="inform the window it no longer being resized">
+ Inform the window that it is no longer being resized. The window manager
+ should use this request to inform windows that are the target of an
+ interactive resize that the interactive resize has ended 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>
+ </request>
+
+ <enum name="capabilities" bitfield="true">
+ <entry name="window_menu" value="1"/>
+ <entry name="maximize" value="2"/>
+ <entry name="fullscreen" value="4"/>
+ <entry name="minimize" value="8"/>
+ </enum>
+
+ <request name="set_capabilities">
+ <description summary="inform window of supported capabilities">
+ This request informs the window of the capabilities supported by the
+ window manager. If the window manager, for example, ignores requests to
+ be maximized from the window it should not tell the window that it
+ supports the maximize capability.
+
+ The window might use this information to, for example, only show a
+ maximize button if the window manager supports the maximize capability.
+
+ The window manager client should use this request to set capabilities
+ for all new windows. If this request is never made, the compositor will
+ inform windows that all capabilities are supported.
+
+ 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"
+ summary="supported capabilities"/>
+ </request>
+
+ <event name="show_window_menu_requested">
+ <description summary="window requested that the window menu be shown">
+ The xdg-shell protocol for example allows windows to request that a
+ window menu be shown, for example when the user right clicks on client
+ side window decorations.
+
+ A window menu might include options to maximize or minimize the window.
+
+ The window manager is free to ignore this request and decide what the
+ window menu contains if it does choose to show one.
+
+ The x and y arguments indicate where the window requested that the
+ window menu be shown.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ <arg name="x" type="int" summary="x offset from top left corner"/>
+ <arg name="y" type="int" summary="y offset from top left corner"/>
+ </event>
+
+ <event name="maximize_requested">
+ <description summary="the window requested to be maximized">
+ The xdg-shell protocol for example allows windows to request to be
+ maximized.
+
+ The window manager is free to honor this request using
+ river_window_v1.inform_maximized or ignore it.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="unmaximize_requested">
+ <description summary="the window requested to be unmaximized">
+ The xdg-shell protocol for example allows windows to request to be
+ unmaximized.
+
+ The window manager is free to honor this request using
+ river_window_v1.inform_unmaximized or ignore it.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <request name="inform_maximized">
+ <description summary="inform the window that it is maximized">
+ Inform the window that it is maximized. The window might use this
+ information to adapt the style of its client-side window decorations for
+ example.
+
+ The window manager remains responsible for handling the position and
+ dimensions of the window while it is maximized.
+
+ 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>
+ </request>
+
+ <request name="inform_unmaximized">
+ <description summary="inform the window that it is unmaximized">
+ Inform the window that it is unmaximized. The window might use this
+ information to adapt the style of its client-side window decorations 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>
+ </request>
+
+ <event name="fullscreen_requested">
+ <description summary="the window requested to be fullscreen">
+ The xdg-shell protocol for example allows windows to request that they
+ be made fullscreen and allows them to provide an optional output hint.
+
+ If the output argument is null, the window has no preference and the
+ window manager should choose an output.
+
+ The window manager is free to honor this request using
+ river_window_v1.fullscreen or ignore it.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ <arg name="output" type="object" allow-null="true"
+ interface="river_output_v1" summary="fullscreen output requested"/>
+ </event>
+
+ <event name="exit_fullscreen_requested">
+ <description summary="the window requested to exit fullscreen">
+ The xdg-shell protocol for example allows windows to request to exit
+ fullscreen.
+
+ The window manager is free to honor this request using
+ river_window_v1.exit_fullscreen or ignore it.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <request name="inform_fullscreen">
+ <description summary="inform the window that it is fullscreen">
+ Inform the window that it is fullscreen. The window might use this
+ information to adapt the style of its client-side window decorations for
+ example.
+
+ This request does not affect the size/position of the window or cause it
+ to become the only window rendered, see the river_window_v1.fullscreen
+ and exit_fullscreen requests for that.
+
+ 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>
+ </request>
+
+ <request name="inform_not_fullscreen">
+ <description summary="inform the window that it is not fullscreen">
+ Inform the window that it is not fullscreen. The window might use this
+ information to adapt the style of its client-side window decorations for
+ example.
+
+ This request does not affect the size/position of the window or cause it
+ to become the only window rendered, see the river_window_v1.fullscreen
+ and exit_fullscreen requests for that.
+
+ 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>
+ </request>
+
+ <request name="fullscreen">
+ <description summary="make the window fullscreen">
+ Make the window fullscreen on the given output. If multiple windows are
+ fullscreen on the same output at the same time only the "top" window in
+ rendering order shall be displayed.
+
+ All river_shell_surface_v1 objects above the top fullscreen window in
+ the rendering order will continue to be rendered.
+
+ The compositor will handle the position and dimensions of the window
+ while it is fullscreen. The set_position and propose_dimensions requests
+ 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
+ the window is fullscreen.
+
+ If the output on which a window is currently fullscreen is removed, the
+ windowing state is modified as if there were an exit_fullscreen request
+ made in the same manage sequence as the river_output_v1.removed event.
+
+ This request does not inform the window that it is fullscreen, see the
+ river_window_v1.inform_fullscreen and inform_not_fullscreen requests.
+
+ 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"
+ summary="fullscreen output"/>
+ </request>
+
+ <request name="exit_fullscreen">
+ <description summary="make the window not fullscreen">
+ Make the window not fullscreen.
+
+ The position and dimensions are undefined after this request is made
+ until a manage sequence in which the window manager makes the
+ propose_dimensions and set_position requests is completed.
+
+ The window manager should make propose_dimensions and set_position
+ requests in the same manage sequence as the exit_fullscreen request for
+ frame perfection.
+
+ This request does not inform the window that it is fullscreen, see the
+ river_window_v1.inform_fullscreen and inform_not_fullscreen requests.
+
+ 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>
+ </request>
+
+ <event name="minimize_requested">
+ <description summary="the window requested to be minimized">
+ The xdg-shell protocol for example allows windows to request to be
+ minimized.
+
+ The window manager is free to ignore this request, hide the window, or
+ do whatever else it chooses.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <request name="set_clip_box" since="2">
+ <description summary="clip the window to a given box">
+ Clip the window, including borders and decoration surfaces, to the box
+ specified by the x, y, width, and height arguments. The x/y position of
+ the box is relative to the top left corner of the window.
+
+ The width and height arguments must be greater than or equal to 0.
+
+ Setting a clip box with 0 width or height disables clipping.
+
+ The clip box is ignored while the window is fullscreen.
+
+ Both set_clip_box and set_content_clip_box may be enabled simultaneously.
+
+ 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" 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">
+ <description summary="unreliable PID of the window's creator">
+ This event gives an unreliable PID of the process that created the
+ window. Obtaining this information is inherently racy due to PID reuse.
+ Therefore, this PID must not be used for anything security sensitive.
+
+ Note also that a single process may create multiple windows, so there is
+ not necessarily a 1-to-1 mapping from PID to window. Multiple windows
+ may have the same PID.
+
+ This event is sent once when the river_window_v1 is created and never
+ sent again.
+ </description>
+ <arg name="unreliable_pid" type="int" summary="unreliable PID"/>
+ </event>
+
+ <request name="set_content_clip_box" since="3">
+ <description summary="clip the window content to a given box">
+ Clip the content of the window, excluding borders and decoration
+ surfaces, to the box specified by the x, y, width, and height arguments.
+ The x/y position of the box is relative to the top left corner of the
+ window.
+
+ Borders drawn by the compositor (see set_borders) are placed around the
+ intersection of the window content (as defined by the dimensions event)
+ and the content clip box when content clipping is enabled.
+
+ The width and height arguments must be greater than or equal to 0.
+
+ Setting a box with 0 width or height disables content clipping.
+
+ The content clip box is ignored while the window is fullscreen.
+
+ Both set_clip_box and set_content_clip_box may be enabled simultaneously.
+
+ 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" 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="4">
+ <description summary="a window decoration">
+ The rendering order of windows with decorations is follows:
+
+ 1. Decorations created with get_decoration_below at the bottom
+ 2. Window content
+ 3. Borders configured with river_window_v1.set_borders
+ 4. Decorations created with get_decoration_above at the top
+
+ The relative ordering of decoration surfaces above/below a window is
+ undefined by this protocol and left up to the compositor.
+ </description>
+
+ <enum name="error">
+ <entry name="no_commit" value="0"
+ summary="failed to commit the surface before the window manager commit"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the decoration object">
+ This request indicates that the client will no longer use the decoration
+ object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <request name="set_offset">
+ <description summary="set offset from the window's top left corner">
+ This request sets the offset of the decoration surface from the top left
+ corner of the window.
+
+ If this request is never sent, the x and y offsets are undefined by this
+ protocol and left up to the compositor.
+
+ 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" 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">
+ <description summary="sync next commit with other rendering state">
+ Synchronize application of the next wl_surface.commit request on the
+ decoration surface with rest of the state atomically applied with the
+ next river_window_manager_v1.render_finish request.
+
+ The client must make a wl_surface.commit request on the decoration
+ surface after this request and before the render_finish request, failure
+ to do so is a protocol error.
+
+ This request modifies rendering state and may only be made as part of a
+ render sequence, see the river_window_manager_v1 description.
+ </description>
+ </request>
+ </interface>
+
+ <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
+ whatever else it wants.
+ </description>
+
+ <enum name="error">
+ <entry name="node_exists" value="0"
+ summary="shell surface already has a node object"/>
+ <entry name="no_commit" value="1"
+ summary="failed to commit the surface before the window manager commit"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the shell surface object">
+ This request indicates that the client will no longer use the shell
+ surface object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <request name="get_node">
+ <description summary="get the shell surface's render list node">
+ Get the node in the render list corresponding to the shell surface.
+
+ 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" summary="new node"/>
+ </request>
+
+ <request name="sync_next_commit">
+ <description summary="sync next surface commit to window manager commit">
+ Synchronize application of the next wl_surface.commit request on the
+ shell surface with rest of the rendering state atomically applied with
+ the next river_window_manager_v1.render_finish request.
+
+ The client must make a wl_surface.commit request on the shell surface
+ after this request and before the render_finish request, failure to do
+ so is a protocol error.
+
+ This request modifies rendering state and may only be made as part of a
+ render sequence, see the river_window_manager_v1 description.
+ </description>
+ </request>
+ </interface>
+
+ <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
+ relative ordering of nodes may be changed with the place_above and
+ place_below requests, changing the rendering order.
+
+ The initial position of a node in the render list is undefined, the window
+ manager client must use the place_above or place_below request to
+ guarantee a specific rendering order.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the decoration object">
+ This request indicates that the client will no longer use the node
+ object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <request name="set_position">
+ <description summary="set absolute position of the node">
+ Set the absolute position of the node in the compositor's logical
+ coordinate space. The x and y coordinates may be positive or negative.
+
+ Note that the position of a river_window_v1 refers to the position of
+ the window content and is unaffected by the presence of borders or
+ decoration surfaces.
+
+ If this request is never sent, the position of the node is undefined by
+ this protocol and left up to the compositor.
+
+ 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" summary="global x coordinate"/>
+ <arg name="y" type="int" summary="global y coordinate"/>
+ </request>
+
+ <request name="place_top">
+ <description summary="place node above all other nodes">
+ This request places the node above all other nodes in the compositor's
+ render list.
+
+ This request modifies rendering state and may only be made as part of a
+ render sequence, see the river_window_manager_v1 description.
+ </description>
+ </request>
+
+ <request name="place_bottom">
+ <description summary="place node below all other nodes">
+ This request places the node below all other nodes in the compositor's
+ render list.
+
+ This request modifies rendering state and may only be made as part of a
+ render sequence, see the river_window_manager_v1 description.
+ </description>
+ </request>
+
+ <request name="place_above">
+ <description summary="place node above another node">
+ This request places the node directly above another node in the
+ compositor's render list.
+
+ Attempting to place a node above itself has no effect.
+
+ 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"
+ summary="other node"/>
+ </request>
+
+ <request name="place_below">
+ <description summary="place node below another node">
+ This request places the node directly below another node in the
+ compositor's render list.
+
+ Attempting to place a node below itself has no effect.
+
+ 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"
+ summary="other node"/>
+ </request>
+ </interface>
+
+ <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
+ correspond to a single physical output or multiple physical outputs in the
+ case of mirroring or tiled monitors depending on the hardware and
+ compositor configuration.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the output object">
+ This request indicates that the client will no longer use the output
+ object and that it may be safely destroyed.
+
+ This request should be made after the river_output_v1.removed event is
+ received to complete destruction of the output.
+ </description>
+ </request>
+
+ <event name="removed">
+ <description summary="the output is removed">
+ This event indicates that the logical output is no longer conceptually
+ part of window management space.
+
+ The server will send no further events on this object and ignore any
+ request (other than river_output_v1.destroy) made after this event is
+ sent. The client should destroy this object with the
+ river_output_v1.destroy request to free up resources.
+
+ This event may be sent because a corresponding physical output has been
+ physically unplugged or because some output configuration has changed.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="wl_output">
+ <description summary="corresponding wl_output">
+ The wl_output object corresponding to the river_output_v1. The argument
+ is the global name of the wl_output advertised with wl_registry.global.
+
+ It is guaranteed that the corresponding wl_output is advertised before
+ this event is sent.
+
+ This event is sent exactly once. The wl_output associated with a
+ river_output_v1 cannot change. It is guaranteed that there is a 1-to-1
+ mapping between wl_output and river_output_v1 objects.
+
+ The global_remove event for the corresponding wl_output may be sent
+ before the river_output_v1.removed event. This is due to the fact that
+ river_output_v1 state changes are synced to the river window management
+ manage sequence while changes to globals are not.
+
+ Rationale: The window manager may need information provided by the
+ wl_output interface such as the name/description. It also may need the
+ wl_output object to start screencopy for example.
+ </description>
+ <arg name="name" type="uint" summary="name of the wl_output global"/>
+ </event>
+
+ <event name="position">
+ <description summary="output position">
+ This event indicates the position of the output in the compositor's
+ logical coordinate space. The x and y coordinates may be positive or
+ negative.
+
+ This event is sent once when the river_output_v1 is created and again
+ whenever the position changes.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+
+ The server must guarantee that the position and dimensions events do not
+ cause the areas of multiple logical outputs to overlap when the
+ corresponding manage_start event is received.
+ </description>
+ <arg name="x" type="int" summary="global x coordinate"/>
+ <arg name="y" type="int" summary="global y coordinate"/>
+ </event>
+
+ <event name="dimensions">
+ <description summary="output dimensions">
+ This event indicates the dimensions of the output in the compositor's
+ logical coordinate space. The width and height will always be strictly
+ greater than zero.
+
+ This event is sent once when the river_output_v1 is created and again
+ whenever the dimensions change.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+
+ The server must guarantee that the position and dimensions events do not
+ cause the areas of multiple logical outputs to overlap when the
+ corresponding manage_start event is received.
+ </description>
+ <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="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 pointer bindings, etc.
+
+ 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">
+ <description summary="destroy the seat object">
+ This request indicates that the client will no longer use the seat
+ object and that it may be safely destroyed.
+
+ This request should be made after the river_seat_v1.removed event is
+ received to complete destruction of the seat.
+ </description>
+ </request>
+
+ <event name="removed">
+ <description summary="the seat is removed">
+ This event indicates that seat is no longer in use and should be
+ destroyed.
+
+ The server will send no further events on this object and ignore any
+ request (other than river_seat_v1.destroy) made after this event is
+ sent. The client should destroy this object with the
+ river_seat_v1.destroy request to free up resources.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="wl_seat">
+ <description summary="corresponding wl_seat">
+ The wl_seat object corresponding to the river_seat_v1. The argument is
+ the global name of the wl_seat advertised with wl_registry.global.
+
+ It is guaranteed that the corresponding wl_seat is advertised before
+ this event is sent.
+
+ This event is sent exactly once. The wl_seat associated with a
+ river_seat_v1 cannot change. It is guaranteed that there is a 1-to-1
+ mapping between wl_seat and river_seat_v1 objects.
+
+ The global_remove event for the corresponding wl_seat may be sent before
+ the river_seat_v1.removed event. This is due to the fact that
+ river_seat_v1 state changes are synced to the river window management
+ manage sequence while changes to globals are not.
+
+ Rationale: The window manager may want to trigger window management
+ state changes based on normal input events received by its shell
+ surfaces for example.
+ </description>
+ <arg name="name" type="uint" summary="name of the wl_seat global"/>
+ </event>
+
+ <request name="focus_window">
+ <description summary="give keyboard focus to a window">
+ Request that the compositor send keyboard input to the given window.
+
+ 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"
+ summary="window to focus"/>
+ </request>
+
+ <request name="focus_shell_surface">
+ <description summary="give keyboard focus to a shell_surface">
+ Request that the compositor send keyboard input to the given shell
+ surface.
+
+ 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"
+ summary="shell surface to focus"/>
+ </request>
+
+ <request name="clear_focus">
+ <description summary="clear keyboard focus">
+ Request that the compositor not send keyboard input to any client.
+
+ 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>
+ </request>
+
+ <event name="pointer_enter">
+ <description summary="pointer entered a window">
+ The seat's pointer entered the given window's area.
+
+ The area of a window is defined to include the area defined by the
+ window dimensions, borders configured using river_window_v1.set_borders,
+ and the input regions of decoration surfaces. In particular, it does not
+ include input regions of surfaces belonging to the window that extend
+ outside the window dimensions.
+
+ The pointer of a seat may only enter a single window at a time. When the
+ pointer moves between windows, the pointer_leave event for the old
+ window must be sent before the pointer_enter event for the new window.
+
+ 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"
+ summary="window entered"/>
+ </event>
+
+ <event name="pointer_leave">
+ <description summary="pointer left the entered window">
+ The seat's pointer left the window for which pointer_enter was most
+ recently sent. See pointer_enter for details.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <event name="window_interaction">
+ <description summary="a window has been interacted with">
+ A window has been interacted with beyond the pointer merely passing over
+ it. This event might be sent due to a pointer button press or due to a
+ touch/tablet tool interaction with the window.
+
+ There are no guarantees regarding how this event is sent in relation to
+ the pointer_enter and pointer_leave events as the interaction may use
+ touch or tablet tool input.
+
+ Rationale: this event gives window managers necessary information to
+ determine when to send keyboard focus, raise a window that already has
+ keyboard focus, etc. Rather than expose all pointer, touch, and tablet
+ events to window managers, a policy over mechanism approach is taken.
+
+ 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"
+ summary="window interacted with"/>
+ </event>
+
+ <event name="shell_surface_interaction">
+ <description summary="a shell surface has been interacted with">
+ A shell surface has been interacted with beyond the pointer merely
+ passing over it. This event might be sent due to a pointer button press
+ or due to a touch/tablet tool interaction with the shell_surface.
+
+ There are no guarantees regarding how this event is sent in relation to
+ the pointer_enter and pointer_leave events as the interaction may use
+ touch or tablet tool input.
+
+ Rationale: While the shell surface does receive all wl_pointer,
+ wl_touch, etc. input events for the surface directly, these events do
+ not necessarily trigger a manage sequence and therefore do not allow the
+ window manager to update focus or perform other actions in response to
+ the input in a race-free way.
+
+ 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"
+ summary="shell surface interacted with"/>
+ </event>
+
+ <request name="op_start_pointer">
+ <description summary="start an interactive pointer operation">
+ Start an interactive pointer operation. During the operation, op_delta
+ events will be sent based on pointer input.
+
+ When all pointer buttons are released, the op_release event is sent.
+
+ The pointer operation continues until the op_end request is made during
+ a manage sequence and that manage sequence is finished.
+
+ The window manager may use this operation to implement interactive
+ move/resize of windows by setting the position of windows and proposing
+ dimensions based off of the op_delta events.
+
+ 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>
+ </request>
+
+ <event name="op_delta">
+ <description summary="total cumulative motion since op start">
+ This event indicates the total change in position since the start of the
+ operation of the pointer/touch point/etc.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ <arg name="dx" type="int" summary="total change in x"/>
+ <arg name="dy" type="int" summary="total change in y"/>
+ </event>
+
+ <event name="op_release">
+ <description summary="operation input has been released">
+ The input driving the current interactive operation has been released.
+ For a pointer op for example, all pointer buttons have been released.
+
+ Depending on the op type, op_delta events may continue to be sent until
+ the op is ended with the op_end request.
+
+ This event is sent at most once during an interactive operation.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <request name="op_end">
+ <description summary="end an interactive operation">
+ End an interactive operation.
+
+ This request is ignored if there is no operation in progress.
+
+ 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>
+ </request>
+
+ <enum name="modifiers" bitfield="true">
+ <description summary="a set of keyboard modifiers">
+ This enum is used to describe the keyboard modifiers that must be held
+ down to trigger a key binding or pointer binding.
+
+ Note that river and wlroots use the values 2 and 16 for capslock and
+ numlock internally. It doesn't make sense to use locked modifiers for
+ bindings however so these values are not included in this enum.
+ </description>
+ <entry name="none" value="0"/>
+ <entry name="shift" value="1"/>
+ <entry name="ctrl" value="4"/>
+ <entry name="mod1" value="8" summary="commonly called alt"/>
+ <entry name="mod3" value="32"/>
+ <entry name="mod4" value="64" summary="commonly called super or logo"/>
+ <entry name="mod5" value="128"/>
+ </enum>
+
+ <request name="get_pointer_binding">
+ <description summary="define a new pointer binding">
+ 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).
+
+ 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"
+ summary="new pointer binding"/>
+ <arg name="button" type="uint" summary="a Linux input event code"/>
+ <arg name="modifiers" type="uint" enum="modifiers"
+ summary="keyboard modifiers"/>
+ </request>
+
+ <request name="set_xcursor_theme" since="2">
+ <description summary="set the xcursor theme for the seat">
+ Set the XCursor theme for the seat. This theme is used for cursors
+ rendered by the compositor, but not necessarily for cursors rendered by
+ clients.
+
+ 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" summary="xcursor theme name"/>
+ <arg name="size" type="uint" summary="cursor size"/>
+ </request>
+
+ <event name="pointer_position" since="2">
+ <description summary="The current position of the pointer">
+ The current position of the pointer in the compositor's logical
+ coordinate space.
+
+ This state is special in that a change in pointer position alone must
+ not cause the compositor to start a manage sequence.
+
+ Assuming the seat has a pointer, this event must be sent in every manage
+ sequence unless there is no change in x/y position since the last time this
+ event was sent.
+ </description>
+ <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">
+ <description summary="warp the pointer to a given position">
+ Warp the pointer to the given position in the compositor's logical
+ coordinate space.
+
+ If the given position is outside the bounds of all outputs, the pointer
+ will be warped to the closest point inside an output instead.
+
+ 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" summary="global x coordinate"/>
+ <arg name="y" type="int" summary="global y coordinate"/>
+ </request>
+ </interface>
+
+ <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.
+
+ The new pointer binding is not enabled until the enable request is made
+ during a manage sequence.
+
+ Normally, all pointer button events are sent to the surface with pointer
+ focus by the compositor. Pointer button events that trigger a pointer
+ binding are not sent to the surface with pointer focus.
+
+ If multiple pointer bindings would be triggered by a single physical
+ pointer event on the compositor side, it is compositor policy which
+ pointer binding(s) will receive press/release events or if all of the
+ matched pointer bindings receive press/release events.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the pointer binding object">
+ This request indicates that the client will no longer use the pointer
+ binding object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <request name="enable">
+ <description summary="enable the pointer binding">
+ This request should be made after all initial configuration has been
+ completed and the window manager wishes the pointer binding to be able
+ to be triggered.
+
+ 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>
+ </request>
+
+ <request name="disable">
+ <description summary="disable the pointer binding">
+ This request may be used to temporarily disable the pointer binding. It
+ may be later re-enabled with the enable request.
+
+ 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>
+ </request>
+
+ <event name="pressed">
+ <description summary="the bound pointer button has been pressed">
+ This event indicates that the pointer button triggering the binding has
+ been pressed.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+
+ The compositor should wait for the manage sequence to complete before
+ processing further input events. This allows the window manager client
+ to, for example, modify key bindings and keyboard focus without racing
+ against future input events. The window manager should of course respond
+ as soon as possible as the capacity of the compositor to buffer incoming
+ input events is finite.
+ </description>
+ </event>
+
+ <event name="released">
+ <description summary="the bound pointer button has been released">
+ This event indicates that the pointer button triggering the binding has
+ been released.
+
+ Releasing the modifiers for the binding without releasing the pointer
+ button does not trigger the release event. This event is sent when the
+ pointer button is released, even if the modifiers have changed since the
+ pressed event.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+
+ The compositor should wait for the manage sequence to complete before
+ processing further input events. This allows the window manager client
+ to, for example, modify key bindings and keyboard focus without racing
+ against future input events. The window manager should of course respond
+ as soon as possible as the capacity of the compositor to buffer incoming
+ input events is finite.
+ </description>
+ </event>
+ </interface>
+</protocol>
diff --git a/protocol/river-xkb-bindings-v1.xml b/protocol/river-xkb-bindings-v1.xml
new file mode 100644
index 0000000..55fb72f
--- /dev/null
+++ b/protocol/river-xkb-bindings-v1.xml
@@ -0,0 +1,314 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="river_xkb_bindings_v1">
+ <copyright>
+ SPDX-FileCopyrightText: © 2025 Isaac Freund
+ SPDX-License-Identifier: MIT
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="xkbcommon-based key bindings">
+ This protocol allows the river-window-management-v1 window manager to
+ define key bindings in terms of xkbcommon keysyms and other configurable
+ properties.
+
+ 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.
+ </description>
+
+ <interface name="river_xkb_bindings_v1" version="3">
+ <description summary="xkbcommon bindings global interface">
+ This global interface should only be advertised to the client if the
+ river_window_manager_v1 global is also advertised.
+ </description>
+
+ <enum name="error" since="2">
+ <entry name="object_already_created" value="0" since="2"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the river_xkb_bindings_v1 object">
+ This request indicates that the client will no longer use the
+ river_xkb_bindings_v1 object.
+ </description>
+ </request>
+
+ <request name="get_xkb_binding">
+ <description summary="define a new xkbcommon key binding">
+ Define a key binding for the given seat in terms of an xkbcommon keysym
+ and other configurable properties.
+
+ The new key binding is not enabled until initial configuration is
+ completed and the enable request is made during a manage sequence.
+ </description>
+ <arg name="seat" type="object" interface="river_seat_v1"/>
+ <arg name="id" type="new_id" interface="river_xkb_binding_v1"/>
+ <arg name="keysym" type="uint" summary="an xkbcommon keysym"/>
+ <arg name="modifiers" type="uint" enum="river_seat_v1.modifiers"/>
+ </request>
+
+ <request name="get_seat" since="2">
+ <description summary="manage seat-specific state">
+ Create an object to manage seat-specific xkb bindings state.
+
+ It is a protocol error to make this request more than once for a given
+ river_seat_v1 object.
+ </description>
+ <arg name="id" type="new_id" interface="river_xkb_bindings_seat_v1"/>
+ <arg name="seat" type="object" interface="river_seat_v1"/>
+ </request>
+ </interface>
+
+ <interface name="river_xkb_binding_v1" version="3">
+ <description summary="configure a xkb key binding, receive trigger events">
+ This object allows the window manager to configure a xkbcommon key binding
+ and receive events when the key binding is triggered.
+
+ The new key binding is not enabled until the enable request is made during
+ a manage sequence.
+
+ Normally, all key events are sent to the surface with keyboard focus by
+ the compositor. Key events that trigger a key binding are not sent to the
+ surface with keyboard focus.
+
+ If multiple key bindings would be triggered by a single physical key event
+ on the compositor side, it is compositor policy which key binding(s) will
+ receive press/release events or if all of the matched key bindings receive
+ press/release events.
+
+ Key bindings might be matched by the same physical key event due to shared
+ keysym and modifiers. The layout override feature may also cause the same
+ physical key event to trigger two key bindings with different keysyms and
+ different layout overrides configured.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xkb binding object">
+ This request indicates that the client will no longer use the xkb key
+ binding object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <request name="set_layout_override">
+ <description summary="override currently active xkb layout">
+ Specify an xkb layout that should be used to translate key events for
+ the purpose of triggering this key binding irrespective of the currently
+ active xkb layout.
+
+ The layout argument is a 0-indexed xkbcommon layout number for the
+ keyboard that generated the key event.
+
+ If this request is never made, the currently active xkb layout of the
+ keyboard that generated the key event will be used.
+
+ 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="layout" type="uint" summary="0-indexed xkbcommon layout"/>
+ </request>
+
+ <request name="enable">
+ <description summary="enable the key binding">
+ This request should be made after all initial configuration has been
+ completed and the window manager wishes the key binding to be able to be
+ triggered.
+
+ 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>
+ </request>
+
+ <request name="disable">
+ <description summary="disable the key binding">
+ This request may be used to temporarily disable the key binding. It may
+ be later re-enabled with the enable request.
+
+ 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>
+ </request>
+
+ <event name="pressed">
+ <description summary="the key triggering the binding has been pressed">
+ This event indicates that the physical key triggering the binding has
+ been pressed.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+
+ The compositor should wait for the manage sequence to complete before
+ processing further input events. This allows the window manager client
+ to, for example, modify key bindings and keyboard focus without racing
+ against future input events. The window manager should of course respond
+ as soon as possible as the capacity of the compositor to buffer incoming
+ input events is finite.
+ </description>
+ </event>
+
+ <event name="released">
+ <description summary="the key triggering the binding has been released">
+ This event indicates that the physical key triggering the binding has
+ been released.
+
+ Releasing the modifiers for the binding without releasing the "main"
+ physical key that produces the bound keysym does not trigger the release
+ event. This event is sent when the "main" key is released, even if the
+ modifiers have changed since the pressed event.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+
+ The compositor should wait for the manage sequence to complete before
+ processing further input events. This allows the window manager client
+ to, for example, modify key bindings and keyboard focus without racing
+ against future input events. The window manager should of course respond
+ as soon as possible as the capacity of the compositor to buffer incoming
+ input events is finite.
+ </description>
+ </event>
+
+ <event name="stop_repeat" since="2">
+ <description summary="repeating should be stopped">
+ This event indicates that repeating should be stopped for the binding if
+ the window manager has been repeating some action since the pressed
+ event.
+
+ This event is generally sent when some other (possibly unbound) key is
+ pressed after the pressed event is sent and before the released event
+ is sent for this binding.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+ </interface>
+
+ <interface name="river_xkb_bindings_seat_v1" version="3">
+ <description summary="xkb bindings seat">
+ This object manages xkb bindings state associated with a specific seat.
+ </description>
+
+ <request name="destroy" type="destructor" since="2">
+ <description summary="destroy the object">
+ This request indicates that the client will no longer use the object and
+ that it may be safely destroyed.
+ </description>
+ </request>
+
+ <request name="ensure_next_key_eaten" since="2">
+ <description summary="ensure the next key press event is eaten">
+ Ensure that the next non-modifier key press and corresponding release
+ events for this seat are not sent to the currently focused surface.
+
+ If the next non-modifier key press triggers a binding, the
+ pressed/released events are sent to the river_xkb_binding_v1 object as
+ usual.
+
+ If the next non-modifier key press does not trigger a binding, the
+ ate_unbound_key event is sent instead.
+
+ Rationale: the window manager may wish to implement "chorded"
+ keybindings where triggering a binding activates a "submap" with a
+ different set of keybindings. Without a way to eat the next key
+ press event, there is no good way for the window manager to know that it
+ should error out and exit the submap when a key not bound in the submap
+ is pressed.
+
+ 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>
+ </request>
+
+ <request name="cancel_ensure_next_key_eaten" since="2">
+ <description summary="cancel an ensure_next_key_eaten request">
+ This requests cancels the effect of the latest ensure_next_key_eaten
+ request if no key has been eaten due to the request yet. This request
+ has no effect if a key has already been eaten or no
+ ensure_next_key_eaten was made.
+
+ Rationale: the window manager may wish cancel an uncompleted "chorded"
+ keybinding after a timeout of a few seconds. Note that since this
+ timeout use-case requires the window manager to trigger a manage sequence
+ with the river_window_manager_v1.manage_dirty request it is possible that
+ the ate_unbound_key key event may be sent before the window manager has
+ a chance to make the cancel_ensure_next_key_eaten request.
+
+ 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>
+ </request>
+
+ <event name="ate_unbound_key" since="2">
+ <description summary="an unbound key press event was eaten">
+ An unbound key press event was eaten due to the ensure_next_key_eaten
+ request.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+ </description>
+ </event>
+
+ <request name="modifiers_watch" since="3">
+ <description summary="watch for change in active modifiers">
+ Request that the server send the modifiers_update event whenever a state
+ change occurs for at least one of the modifiers specified by the
+ modifiers argument.
+
+ The window manager should make this request with the modifiers argument
+ set to 0 when it no longer wishes to take action based on a change in
+ modifiers.
+
+ 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="modifiers" type="uint" enum="river_seat_v1.modifiers"/>
+ </request>
+
+ <event name="modifiers_update" since="3">
+ <description summary="active modifiers for the seat changed">
+ The set of currently active modifiers for the seat changed. This event
+ is only sent when there is a change in state for modifiers marked as
+ watched using the modifiers_watch request.
+
+ The old and new arguments convey the set of modifiers active before and
+ after the change. All modifiers are included in the old and new
+ arguments, including modifiers that are not watched.
+
+ Since this event is only sent when there is a change in state for
+ watched modifiers, it follows that at least one watched modifier is
+ active in old but inactive in new or vice-versa.
+
+ This event will be followed by a manage_start event after all other new
+ state has been sent by the server.
+
+ The compositor should wait for the manage sequence to complete before
+ processing further input events. This allows the window manager client
+ to, for example, modify key bindings and keyboard focus without racing
+ against future input events. The window manager should of course respond
+ as soon as possible as the capacity of the compositor to buffer incoming
+ input events is finite.
+ </description>
+ <arg name="old" type="uint" enum="river_seat_v1.modifiers"
+ summary="previously active modifiers"/>
+ <arg name="new" type="uint" enum="river_seat_v1.modifiers"
+ summary="currently active modifiers"/>
+ </event>
+ </interface>
+</protocol>
diff --git a/protocol/river-xkb-config-v1.xml b/protocol/river-xkb-config-v1.xml
new file mode 100644
index 0000000..f73ec67
--- /dev/null
+++ b/protocol/river-xkb-config-v1.xml
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="river_xkb_config_v1">
+ <copyright>
+ SPDX-FileCopyrightText: © 2026 Isaac Freund
+ SPDX-License-Identifier: MIT
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="configure xkbcommon keyboards">
+ This protocol allow a client to set the xkbcommon keymap of individual
+ keyboard input devices. It also allows switching between the layouts of a
+ keymap and toggling capslock/numlock state.
+
+ 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.
+ </description>
+
+ <interface name="river_xkb_config_v1" version="2">
+ <description summary="xkb config global interface">
+ Global interface for configuring xkb devices.
+
+ This global should only be advertised if river_input_manager_v1 is
+ advertised as well.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_destroy" value="0"/>
+ <entry name="invalid_format" value="1"/>
+ </enum>
+
+ <request name="stop">
+ <description summary="stop sending events">
+ This request indicates that the client no longer wishes to receive
+ events on this object.
+
+ The Wayland protocol is asynchronous, which means the server may send
+ further events until the stop request is processed. The client must wait
+ for a river_xkb_config_v1.finished event before destroying this object.
+ </description>
+ </request>
+
+ <event name="finished">
+ <description summary="the server has finished with the object">
+ This event indicates that the server will send no further events on this
+ object. The client should destroy the object. See
+ river_xkb_config_v1.destroy for more information.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the river_xkb_config_v1 object">
+ This request should be called after the finished event has been received
+ to complete destruction of the object.
+
+ It is a protocol error to make this request before the finished event
+ has been received.
+
+ If a client wishes to destroy this object it should send a
+ river_xkb_config_v1.stop request and wait for a
+ river_xkb_config_v1.finished event. Once the finished event is received
+ it is safe to destroy this object and any other objects created through
+ this interface.
+ </description>
+ </request>
+
+ <enum name="keymap_format">
+ <entry name="text_v1" value="1" summary="XKB_KEYMAP_FORMAT_TEXT_V1"/>
+ <entry name="text_v2" value="2" summary="XKB_KEYMAP_FORMAT_TEXT_V2"/>
+ </enum>
+
+ <request name="create_keymap">
+ <description summary="create a keymap object">
+ The server must be able to mmap the fd with MAP_PRIVATE.
+ The server will fstat the fd to obtain the size of the keymap.
+ The client must not modify the contents of the fd after making this request.
+ The client should seal the fd with fcntl.
+ </description>
+ <arg name="id" type="new_id" interface="river_xkb_keymap_v1"/>
+ <arg name="fd" type="fd"/>
+ <arg name="format" type="uint" enum="keymap_format"/>
+ </request>
+
+ <event name="xkb_keyboard">
+ <description summary="new xkb keyboard">
+ A new xkbcommon keyboard has been created. Not every
+ river_input_device_v1 is necessarily an xkbcommon keyboard as well.
+ </description>
+ <arg name="id" type="new_id" interface="river_xkb_keyboard_v1"/>
+ </event>
+ </interface>
+
+ <interface name="river_xkb_keymap_v1" version="2">
+ <description summary="xkbcommon keymap">
+ This object is the result of attempting to create an xkbcommon keymap.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the keymap object">
+ This request indicates that the client will no longer use the keymap
+ object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <event name="success">
+ <description summary="keymap creation succeeded">
+ The keymap object was successfully created and may be used with the
+ river_xkb_keyboard_v1.set_keymap request.
+ </description>
+ </event>
+
+ <event name="failure">
+ <description summary="keymap creation failed">
+ The compositor failed to create a keymap from the given parameters.
+
+ It is a protocol error to use this keymap object with
+ river_xkb_keyboard_v1.set_keymap.
+ </description>
+ <arg name="error_msg" type="string"/>
+ </event>
+ </interface>
+
+ <interface name="river_xkb_keyboard_v1" version="2">
+ <description summary="xkbcommon keyboard device">
+ This object represent a physical keyboard which has its configuration and
+ state managed by xkbcommon.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_keymap" value="0"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xkb keyboard object">
+ This request indicates that the client will no longer use the keyboard
+ object and that it may be safely destroyed.
+ </description>
+ </request>
+
+ <event name="removed">
+ <description summary="the xkb keyboard is removed">
+ This event indicates that the xkb keyboard has been removed.
+
+ The server will send no further events on this object and ignore any
+ request (other than river_xkb_keyboard_v1.destroy) made after this event
+ is sent. The client should destroy this object with the
+ river_xkb_keyboard_v1.destroy request to free up resources.
+ </description>
+ </event>
+
+ <event name="input_device">
+ <description summary="corresponding river input device">
+ The river_input_device_v1 corresponding to this xkb keyboard. This event
+ will always be the first event sent on the river_xkb_keyboard_v1 object,
+ and it will be sent exactly once.
+ </description>
+ <arg name="device" type="object" interface="river_input_device_v1"/>
+ </event>
+
+ <request name="set_keymap">
+ <description summary="set the keymap">
+ Set the keymap for the keyboard.
+
+ Setting a keymap will reset all layout/modifier state.
+
+ It is a protocol error to pass a keymap object for which the
+ river_xkb_keymap_v1.success event was not received.
+ </description>
+ <arg name="keymap" type="object" interface="river_xkb_keymap_v1"/>
+ </request>
+
+ <request name="set_layout_by_index">
+ <description summary="set the active layout by index">
+ Set the active layout for the keyboard's keymap. Has no effect if the
+ layout index is out of bounds for the current keymap.
+ </description>
+ <arg name="index" type="int"/>
+ </request>
+
+ <request name="set_layout_by_name">
+ <description summary="set the active layout by name">
+ Set the active layout for the keyboard's keymap. Has no effect if there
+ is no layout with the give name for the keyboard's keymap.
+ </description>
+ <arg name="name" type="string"/>
+ </request>
+
+ <event name="layout">
+ <description summary="currently active layout">
+ The currently active layout index and name. The name arg may be null if
+ the active layout does not have a name.
+
+ This event is sent once when the river_xkb_keyboard_v1 is created and
+ again whenever the layout changes.
+ </description>
+ <arg name="index" type="uint"/>
+ <arg name="name" type="string" allow-null="true"/>
+ </event>
+
+ <request name="capslock_enable">
+ <description summary="enable capslock">
+ Enable capslock for the keyboard.
+ </description>
+ </request>
+
+ <request name="capslock_disable">
+ <description summary="disable capslock">
+ Disable capslock for the keyboard.
+ </description>
+ </request>
+
+ <event name="capslock_enabled">
+ <description summary="capslock is currently enabled">
+ Capslock is currently enabled for the keyboard.
+
+ This event is sent once when the river_xkb_keyboard_v1 is created and
+ again whenever the capslock state changes.
+ </description>
+ </event>
+
+ <event name="capslock_disabled">
+ <description summary="capslock is currently disabled">
+ Capslock is currently disabled for the keyboard.
+
+ This event is sent once when the river_xkb_keyboard_v1 is created and
+ again whenever the capslock state changes.
+ </description>
+ </event>
+
+ <request name="numlock_enable">
+ <description summary="enable numlock">
+ Enable numlock for the keyboard.
+ </description>
+ </request>
+
+ <request name="numlock_disable">
+ <description summary="disable numlock">
+ Disable numlock for the keyboard.
+ </description>
+ </request>
+
+ <event name="numlock_enabled">
+ <description summary="numlock is currently enabled">
+ Numlock is currently enabled for the keyboard.
+
+ This event is sent once when the river_xkb_keyboard_v1 is created and
+ again whenever the numlock state changes.
+ </description>
+ </event>
+
+ <event name="numlock_disabled">
+ <description summary="numlock is currently disabled">
+ Numlock is currently disabled for the keyboard.
+
+ This event is sent once when the river_xkb_keyboard_v1 is created and
+ again whenever the numlock state changes.
+ </description>
+ </event>
+
+ <event name="done" since="2">
+ <description summary="all information has been sent">
+ This event is sent after all information about the keyboard has been
+ sent.
+
+ This allows changes to one or more river_xkb_keyboard_v1 properties to
+ be seen as atomic, even if they happen via multiple events.
+ </description>
+ </event>
+ </interface>
+</protocol>
diff --git a/protocol/upstream/virtual-keyboard-unstable-v1.xml b/protocol/upstream/virtual-keyboard-unstable-v1.xml
new file mode 100644
index 0000000..1ac03fe
--- /dev/null
+++ b/protocol/upstream/virtual-keyboard-unstable-v1.xml
@@ -0,0 +1,114 @@
+<!-- SPDX-License-Identifier: MIT -->
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="virtual_keyboard_unstable_v1">
+ <copyright>
+ Copyright © 2008-2011 Kristian Høgsberg
+ Copyright © 2010-2013 Intel Corporation
+ Copyright © 2012-2013 Collabora, Ltd.
+ Copyright © 2018 Purism SPC
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="zwp_virtual_keyboard_v1" version="1">
+ <description summary="virtual keyboard">
+ The virtual keyboard provides an application with requests which emulate
+ the behaviour of a physical keyboard.
+
+ This interface can be used by clients on its own to provide raw input
+ events, or it can accompany the input method protocol.
+ </description>
+
+ <request name="keymap">
+ <description summary="keyboard mapping">
+ Provide a file descriptor to the compositor which can be
+ memory-mapped to provide a keyboard mapping description.
+
+ Format carries a value from the keymap_format enumeration.
+ </description>
+ <arg name="format" type="uint" summary="keymap format"/>
+ <arg name="fd" type="fd" summary="keymap file descriptor"/>
+ <arg name="size" type="uint" summary="keymap size, in bytes"/>
+ </request>
+
+ <enum name="error">
+ <entry name="no_keymap" value="0" summary="No keymap was set"/>
+ </enum>
+
+ <request name="key">
+ <description summary="key event">
+ A key was pressed or released.
+ The time argument is a timestamp with millisecond granularity, with an
+ undefined base. All requests regarding a single object must share the
+ same clock.
+
+ Keymap must be set before issuing this request.
+
+ State carries a value from the key_state enumeration.
+ </description>
+ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
+ <arg name="key" type="uint" summary="key that produced the event"/>
+ <arg name="state" type="uint" summary="physical state of the key"/>
+ </request>
+
+ <request name="modifiers">
+ <description summary="modifier and group state">
+ Notifies the compositor that the modifier and/or group state has
+ changed, and it should update state.
+
+ The client should use wl_keyboard.modifiers event to synchronize its
+ internal state with seat state.
+
+ Keymap must be set before issuing this request.
+ </description>
+ <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
+ <arg name="mods_latched" type="uint" summary="latched modifiers"/>
+ <arg name="mods_locked" type="uint" summary="locked modifiers"/>
+ <arg name="group" type="uint" summary="keyboard layout"/>
+ </request>
+
+ <request name="destroy" type="destructor" since="1">
+ <description summary="destroy the virtual keyboard keyboard object"/>
+ </request>
+ </interface>
+
+ <interface name="zwp_virtual_keyboard_manager_v1" version="1">
+ <description summary="virtual keyboard manager">
+ A virtual keyboard manager allows an application to provide keyboard
+ input events as if they came from a physical keyboard.
+ </description>
+
+ <enum name="error">
+ <entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
+ </enum>
+
+ <request name="create_virtual_keyboard">
+ <description summary="Create a new virtual keyboard">
+ Creates a new virtual keyboard associated to a seat.
+
+ If the compositor enables a keyboard to perform arbitrary actions, it
+ should present an error when an untrusted client requests a new
+ keyboard.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ <arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
+ </request>
+ </interface>
+</protocol>
diff --git a/protocol/upstream/wlr-layer-shell-unstable-v1.xml b/protocol/upstream/wlr-layer-shell-unstable-v1.xml
new file mode 100644
index 0000000..450970e
--- /dev/null
+++ b/protocol/upstream/wlr-layer-shell-unstable-v1.xml
@@ -0,0 +1,408 @@
+<!-- SPDX-License-Identifier: MIT -->
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="wlr_layer_shell_unstable_v1">
+ <copyright>
+ Copyright © 2017 Drew DeVault
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <interface name="zwlr_layer_shell_v1" version="5">
+ <description summary="create surfaces that are layers of the desktop">
+ Clients can use this interface to assign the surface_layer role to
+ wl_surfaces. Such surfaces are assigned to a "layer" of the output and
+ rendered with a defined z-depth respective to each other. They may also be
+ anchored to the edges and corners of a screen and specify input handling
+ semantics. This interface should be suitable for the implementation of
+ many desktop shell components, and a broad number of other applications
+ that interact with the desktop.
+ </description>
+
+ <request name="get_layer_surface">
+ <description summary="create a layer_surface from a surface">
+ Create a layer surface for an existing surface. This assigns the role of
+ layer_surface, or raises a protocol error if another role is already
+ assigned.
+
+ Creating a layer surface from a wl_surface which has a buffer attached
+ or committed is a client error, and any attempts by a client to attach
+ or manipulate a buffer prior to the first layer_surface.configure call
+ must also be treated as errors.
+
+ After creating a layer_surface object and setting it up, the client
+ must perform an initial commit without any buffer attached.
+ The compositor will reply with a layer_surface.configure event.
+ The client must acknowledge it and is then allowed to attach a buffer
+ to map the surface.
+
+ You may pass NULL for output to allow the compositor to decide which
+ output to use. Generally this will be the one that the user most
+ recently interacted with.
+
+ Clients can specify a namespace that defines the purpose of the layer
+ surface.
+ </description>
+ <arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
+ <arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
+ <arg name="namespace" type="string" summary="namespace for the layer surface"/>
+ </request>
+
+ <enum name="error">
+ <entry name="role" value="0" summary="wl_surface has another role"/>
+ <entry name="invalid_layer" value="1" summary="layer value is invalid"/>
+ <entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
+ </enum>
+
+ <enum name="layer">
+ <description summary="available layers for surfaces">
+ These values indicate which layers a surface can be rendered in. They
+ are ordered by z depth, bottom-most first. Traditional shell surfaces
+ will typically be rendered between the bottom and top layers.
+ Fullscreen shell surfaces are typically rendered at the top layer.
+ Multiple surfaces can share a single layer, and ordering within a
+ single layer is undefined.
+ </description>
+
+ <entry name="background" value="0"/>
+ <entry name="bottom" value="1"/>
+ <entry name="top" value="2"/>
+ <entry name="overlay" value="3"/>
+ </enum>
+
+ <!-- Version 3 additions -->
+
+ <request name="destroy" type="destructor" since="3">
+ <description summary="destroy the layer_shell object">
+ This request indicates that the client will not use the layer_shell
+ object any more. Objects that have been created through this instance
+ are not affected.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwlr_layer_surface_v1" version="5">
+ <description summary="layer metadata interface">
+ An interface that may be implemented by a wl_surface, for surfaces that
+ are designed to be rendered as a layer of a stacked desktop-like
+ environment.
+
+ Layer surface state (layer, size, anchor, exclusive zone,
+ margin, interactivity) is double-buffered, and will be applied at the
+ time wl_surface.commit of the corresponding wl_surface is called.
+
+ Attaching a null buffer to a layer surface unmaps it.
+
+ Unmapping a layer_surface means that the surface cannot be shown by the
+ compositor until it is explicitly mapped again. The layer_surface
+ returns to the state it had right after layer_shell.get_layer_surface.
+ The client can re-map the surface by performing a commit without any
+ buffer attached, waiting for a configure event and handling it as usual.
+ </description>
+
+ <request name="set_size">
+ <description summary="sets the size of the surface">
+ Sets the size of the surface in surface-local coordinates. The
+ compositor will display the surface centered with respect to its
+ anchors.
+
+ If you pass 0 for either value, the compositor will assign it and
+ inform you of the assignment in the configure event. You must set your
+ anchor to opposite edges in the dimensions you omit; not doing so is a
+ protocol error. Both values are 0 by default.
+
+ Size is double-buffered, see wl_surface.commit.
+ </description>
+ <arg name="width" type="uint"/>
+ <arg name="height" type="uint"/>
+ </request>
+
+ <request name="set_anchor">
+ <description summary="configures the anchor point of the surface">
+ Requests that the compositor anchor the surface to the specified edges
+ and corners. If two orthogonal edges are specified (e.g. 'top' and
+ 'left'), then the anchor point will be the intersection of the edges
+ (e.g. the top left corner of the output); otherwise the anchor point
+ will be centered on that edge, or in the center if none is specified.
+
+ Anchor is double-buffered, see wl_surface.commit.
+ </description>
+ <arg name="anchor" type="uint" enum="anchor"/>
+ </request>
+
+ <request name="set_exclusive_zone">
+ <description summary="configures the exclusive geometry of this surface">
+ Requests that the compositor avoids occluding an area with other
+ surfaces. The compositor's use of this information is
+ implementation-dependent - do not assume that this region will not
+ actually be occluded.
+
+ A positive value is only meaningful if the surface is anchored to one
+ edge or an edge and both perpendicular edges. If the surface is not
+ anchored, anchored to only two perpendicular edges (a corner), anchored
+ to only two parallel edges or anchored to all edges, a positive value
+ will be treated the same as zero.
+
+ A positive zone is the distance from the edge in surface-local
+ coordinates to consider exclusive.
+
+ Surfaces that do not wish to have an exclusive zone may instead specify
+ how they should interact with surfaces that do. If set to zero, the
+ surface indicates that it would like to be moved to avoid occluding
+ surfaces with a positive exclusive zone. If set to -1, the surface
+ indicates that it would not like to be moved to accommodate for other
+ surfaces, and the compositor should extend it all the way to the edges
+ it is anchored to.
+
+ For example, a panel might set its exclusive zone to 10, so that
+ maximized shell surfaces are not shown on top of it. A notification
+ might set its exclusive zone to 0, so that it is moved to avoid
+ occluding the panel, but shell surfaces are shown underneath it. A
+ wallpaper or lock screen might set their exclusive zone to -1, so that
+ they stretch below or over the panel.
+
+ The default value is 0.
+
+ Exclusive zone is double-buffered, see wl_surface.commit.
+ </description>
+ <arg name="zone" type="int"/>
+ </request>
+
+ <request name="set_margin">
+ <description summary="sets a margin from the anchor point">
+ Requests that the surface be placed some distance away from the anchor
+ point on the output, in surface-local coordinates. Setting this value
+ for edges you are not anchored to has no effect.
+
+ The exclusive zone includes the margin.
+
+ Margin is double-buffered, see wl_surface.commit.
+ </description>
+ <arg name="top" type="int"/>
+ <arg name="right" type="int"/>
+ <arg name="bottom" type="int"/>
+ <arg name="left" type="int"/>
+ </request>
+
+ <enum name="keyboard_interactivity">
+ <description summary="types of keyboard interaction possible for a layer shell surface">
+ Types of keyboard interaction possible for layer shell surfaces. The
+ rationale for this is twofold: (1) some applications are not interested
+ in keyboard events and not allowing them to be focused can improve the
+ desktop experience; (2) some applications will want to take exclusive
+ keyboard focus.
+ </description>
+
+ <entry name="none" value="0">
+ <description summary="no keyboard focus is possible">
+ This value indicates that this surface is not interested in keyboard
+ events and the compositor should never assign it the keyboard focus.
+
+ This is the default value, set for newly created layer shell surfaces.
+
+ This is useful for e.g. desktop widgets that display information or
+ only have interaction with non-keyboard input devices.
+ </description>
+ </entry>
+ <entry name="exclusive" value="1">
+ <description summary="request exclusive keyboard focus">
+ Request exclusive keyboard focus if this surface is above the shell surface layer.
+
+ For the top and overlay layers, the seat will always give
+ exclusive keyboard focus to the top-most layer which has keyboard
+ interactivity set to exclusive. If this layer contains multiple
+ surfaces with keyboard interactivity set to exclusive, the compositor
+ determines the one receiving keyboard events in an implementation-
+ defined manner. In this case, no guarantee is made when this surface
+ will receive keyboard focus (if ever).
+
+ For the bottom and background layers, the compositor is allowed to use
+ normal focus semantics.
+
+ This setting is mainly intended for applications that need to ensure
+ they receive all keyboard events, such as a lock screen or a password
+ prompt.
+ </description>
+ </entry>
+ <entry name="on_demand" value="2" since="4">
+ <description summary="request regular keyboard focus semantics">
+ This requests the compositor to allow this surface to be focused and
+ unfocused by the user in an implementation-defined manner. The user
+ should be able to unfocus this surface even regardless of the layer
+ it is on.
+
+ Typically, the compositor will want to use its normal mechanism to
+ manage keyboard focus between layer shell surfaces with this setting
+ and regular toplevels on the desktop layer (e.g. click to focus).
+ Nevertheless, it is possible for a compositor to require a special
+ interaction to focus or unfocus layer shell surfaces (e.g. requiring
+ a click even if focus follows the mouse normally, or providing a
+ keybinding to switch focus between layers).
+
+ This setting is mainly intended for desktop shell components (e.g.
+ panels) that allow keyboard interaction. Using this option can allow
+ implementing a desktop shell that can be fully usable without the
+ mouse.
+ </description>
+ </entry>
+ </enum>
+
+ <request name="set_keyboard_interactivity">
+ <description summary="requests keyboard events">
+ Set how keyboard events are delivered to this surface. By default,
+ layer shell surfaces do not receive keyboard events; this request can
+ be used to change this.
+
+ This setting is inherited by child surfaces set by the get_popup
+ request.
+
+ Layer surfaces receive pointer, touch, and tablet events normally. If
+ you do not want to receive them, set the input region on your surface
+ to an empty region.
+
+ Keyboard interactivity is double-buffered, see wl_surface.commit.
+ </description>
+ <arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
+ </request>
+
+ <request name="get_popup">
+ <description summary="assign this layer_surface as an xdg_popup parent">
+ This assigns an xdg_popup's parent to this layer_surface. This popup
+ should have been created via xdg_surface::get_popup with the parent set
+ to NULL, and this request must be invoked before committing the popup's
+ initial state.
+
+ See the documentation of xdg_popup for more details about what an
+ xdg_popup is and how it is used.
+ </description>
+ <arg name="popup" type="object" interface="xdg_popup"/>
+ </request>
+
+ <request name="ack_configure">
+ <description summary="ack a configure event">
+ When a configure event is received, if a client commits the
+ surface in response to the configure event, then the client
+ must make an ack_configure request sometime before the commit
+ request, passing along the serial of the configure event.
+
+ If the client receives multiple configure events before it
+ can respond to one, it only has to ack the last configure event.
+
+ A client is not required to commit immediately after sending
+ an ack_configure request - it may even ack_configure several times
+ before its next surface commit.
+
+ A client may send multiple ack_configure requests before committing, but
+ only the last request sent before a commit indicates which configure
+ event the client really is responding to.
+ </description>
+ <arg name="serial" type="uint" summary="the serial from the configure event"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the layer_surface">
+ This request destroys the layer surface.
+ </description>
+ </request>
+
+ <event name="configure">
+ <description summary="suggest a surface change">
+ The configure event asks the client to resize its surface.
+
+ Clients should arrange their surface for the new states, and then send
+ an ack_configure request with the serial sent in this configure event at
+ some point before committing the new surface.
+
+ The client is free to dismiss all but the last configure event it
+ received.
+
+ The width and height arguments specify the size of the window in
+ surface-local coordinates.
+
+ The size is a hint, in the sense that the client is free to ignore it if
+ it doesn't resize, pick a smaller size (to satisfy aspect ratio or
+ resize in steps of NxM pixels). If the client picks a smaller size and
+ is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
+ surface will be centered on this axis.
+
+ If the width or height arguments are zero, it means the client should
+ decide its own window dimension.
+ </description>
+ <arg name="serial" type="uint"/>
+ <arg name="width" type="uint"/>
+ <arg name="height" type="uint"/>
+ </event>
+
+ <event name="closed">
+ <description summary="surface should be closed">
+ The closed event is sent by the compositor when the surface will no
+ longer be shown. The output may have been destroyed or the user may
+ have asked for it to be removed. Further changes to the surface will be
+ ignored. The client should destroy the resource after receiving this
+ event, and create a new surface if they so choose.
+ </description>
+ </event>
+
+ <enum name="error">
+ <entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
+ <entry name="invalid_size" value="1" summary="size is invalid"/>
+ <entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
+ <entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
+ <entry name="invalid_exclusive_edge" value="4" summary="exclusive edge is invalid given the surface anchors"/>
+ </enum>
+
+ <enum name="anchor" bitfield="true">
+ <entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
+ <entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
+ <entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
+ <entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
+ </enum>
+
+ <!-- Version 2 additions -->
+
+ <request name="set_layer" since="2">
+ <description summary="change the layer of the surface">
+ Change the layer that the surface is rendered on.
+
+ Layer is double-buffered, see wl_surface.commit.
+ </description>
+ <arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
+ </request>
+
+ <!-- Version 5 additions -->
+
+ <request name="set_exclusive_edge" since="5">
+ <description summary="set the edge the exclusive zone will be applied to">
+ Requests an edge for the exclusive zone to apply. The exclusive
+ edge will be automatically deduced from anchor points when possible,
+ but when the surface is anchored to a corner, it will be necessary
+ to set it explicitly to disambiguate, as it is not possible to deduce
+ which one of the two corner edges should be used.
+
+ The edge must be one the surface is anchored to, otherwise the
+ invalid_exclusive_edge protocol error will be raised.
+ </description>
+ <arg name="edge" type="uint" enum="anchor"/>
+ </request>
+ </interface>
+</protocol>
diff --git a/protocol/upstream/wlr-output-power-management-unstable-v1.xml b/protocol/upstream/wlr-output-power-management-unstable-v1.xml
new file mode 100644
index 0000000..9416579
--- /dev/null
+++ b/protocol/upstream/wlr-output-power-management-unstable-v1.xml
@@ -0,0 +1,129 @@
+<!-- SPDX-License-Identifier: MIT -->
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="wlr_output_power_management_unstable_v1">
+ <copyright>
+ Copyright © 2019 Purism SPC
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="Control power management modes of outputs">
+ This protocol allows clients to control power management modes
+ of outputs that are currently part of the compositor space. The
+ intent is to allow special clients like desktop shells to power
+ down outputs when the system is idle.
+
+ To modify outputs not currently part of the compositor space see
+ wlr-output-management.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+ </description>
+
+ <interface name="zwlr_output_power_manager_v1" version="1">
+ <description summary="manager to create per-output power management">
+ This interface is a manager that allows creating per-output power
+ management mode controls.
+ </description>
+
+ <request name="get_output_power">
+ <description summary="get a power management for an output">
+ Create an output power management mode control that can be used to
+ adjust the power management mode for a given output.
+ </description>
+ <arg name="id" type="new_id" interface="zwlr_output_power_v1"/>
+ <arg name="output" type="object" interface="wl_output"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the manager">
+ All objects created by the manager will still remain valid, until their
+ appropriate destroy request has been called.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwlr_output_power_v1" version="1">
+ <description summary="adjust power management mode for an output">
+ This object offers requests to set the power management mode of
+ an output.
+ </description>
+
+ <enum name="mode">
+ <entry name="off" value="0"
+ summary="Output is turned off."/>
+ <entry name="on" value="1"
+ summary="Output is turned on, no power saving"/>
+ </enum>
+
+ <enum name="error">
+ <entry name="invalid_mode" value="1" summary="nonexistent power save mode"/>
+ </enum>
+
+ <request name="set_mode">
+ <description summary="Set an outputs power save mode">
+ Set an output's power save mode to the given mode. The mode change
+ is effective immediately. If the output does not support the given
+ mode a failed event is sent.
+ </description>
+ <arg name="mode" type="uint" enum="mode" summary="the power save mode to set"/>
+ </request>
+
+ <event name="mode">
+ <description summary="Report a power management mode change">
+ Report the power management mode change of an output.
+
+ The mode event is sent after an output changed its power
+ management mode. The reason can be a client using set_mode or the
+ compositor deciding to change an output's mode.
+ This event is also sent immediately when the object is created
+ so the client is informed about the current power management mode.
+ </description>
+ <arg name="mode" type="uint" enum="mode"
+ summary="the output's new power management mode"/>
+ </event>
+
+ <event name="failed">
+ <description summary="object no longer valid">
+ This event indicates that the output power management mode control
+ is no longer valid. This can happen for a number of reasons,
+ including:
+ - The output doesn't support power management
+ - Another client already has exclusive power management mode control
+ for this output
+ - The output disappeared
+
+ Upon receiving this event, the client should destroy this object.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy this power management">
+ Destroys the output power management mode control object.
+ </description>
+ </request>
+ </interface>
+</protocol>
diff --git a/src/input_device.rs b/src/input_device.rs
index 72037fb..bc8e8eb 100644
--- a/src/input_device.rs
+++ b/src/input_device.rs
@@ -257,6 +257,12 @@ unsafe extern "C" fn handle_device_destroy(listener: *mut ffi::wl_listener, _dat
ffi::river_wlr_input_device_get_type(device.wlr_device)
);
+ // Detach from seat if attached
+ if !device.seat.is_null() {
+ (*device.seat).detach_device(device);
+ (*device.seat).update_capabilities();
+ }
+
// Free objects and set inert
let objects_head = &mut device.objects as *mut ffi::wl_list as *mut WlList;
let mut curr = (*objects_head).next;
@@ -298,12 +304,6 @@ unsafe extern "C" fn handle_device_destroy(listener: *mut ffi::wl_listener, _dat
// Remove from InputManager::devices
wl_list_remove(&mut device.link as *mut ffi::wl_list as *mut WlList);
- // Detach from seat if attached
- if !device.seat.is_null() {
- (*device.seat).detach_device(device);
- (*device.seat).update_capabilities();
- }
-
// Free wrapper memory
let _boxed = Box::from_raw(device_ptr);
}
diff --git a/src/seat.rs b/src/seat.rs
index f80d945..7f07f71 100644
--- a/src/seat.rs
+++ b/src/seat.rs
@@ -259,7 +259,7 @@ impl Seat {
let dev_type = ffi::river_wlr_input_device_get_type((*device).wlr_device);
if dev_type == ffi::wlr_input_device_type_WLR_INPUT_DEVICE_KEYBOARD {
- let keyboard = ffi::river_wlr_input_device_get_data((*device).wlr_device) as *mut crate::keyboard::Keyboard;
+ let keyboard = (*device).destroy_data as *mut crate::keyboard::Keyboard;
if !keyboard.is_null() {
if !(*keyboard).group.is_null() {
let keys: Vec<u32> = (*keyboard).pressed.iter().cloned().collect();