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

commit65e10dc5dba0f07df554d8c8a7a83cf194d0cb09
parentaea9f3a2e4
authorIsaac Freund <[email protected]>
date2025-07-02 13:21
rwm: add river_seat_v1.wl_seat

 protocol/river-window-management-v1.xml | 24 ++++++++++++++++++++++++
 river/Seat.zig                          | 11 +++++++++++
 rivercompat/Seat.zig                    |  1 +
 3 files changed, 36 insertions(+)

diff --git a/protocol/river-window-management-v1.xml b/protocol/river-window-management-v1.xml
index 86130ac..81dec2d 100644
--- a/protocol/river-window-management-v1.xml
+++ b/protocol/river-window-management-v1.xml
@@ -1235,6 +1235,30 @@
       </description>
     </event>
 
+    <event name="wl_seat">
+      <description summary="corresponding wl_seat">
+        The wl_seat object corresponding to the river_seat_v1.
+
+        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.
+
+        Note that this event will only be sent after the client binds the
+        wl_seat global. It is guaranteed that the corresponding wl_seat is
+        advertised before the river_window_manager_v1.seat event is sent.
+
+        The global_remove event for the corresponding wl_seat may be sent before
+        the river_seat_v1.remove event. This is due to the fact that
+        river_seat_v1 state changes are synced to the river window management
+        update sequence while changes to globals are not.
+
+        Rationale: The window manager may want to trigger windowing state
+        changes based on normal input events received by its shell surfaces for
+        example.
+      </description>
+      <arg name="wl_seat" type="object" interface="wl_seat"/>
+    </event>
+
     <request name="focus_window">
       <description summary="give keyboard focus to a window">
         Request that the compositor send keyboard input to the given window.
diff --git a/river/Seat.zig b/river/Seat.zig
index 61b4883..99ee892 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -314,6 +314,17 @@ pub fn updateWindowingStart(seat: *Seat) void {
         };
         errdefer comptime unreachable;
 
+        if (new) {
+            // TODO(wlroots): send on bind if wl_seat global not yet bound:
+            // https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5099
+            const client = seat_v1.getClient();
+            if (seat.wlr_seat.clientForWlClient(client)) |seat_client| {
+                if (seat_client.resources.first()) |wl_seat| {
+                    seat_v1.sendWlSeat(wl_seat);
+                }
+            }
+        }
+
         if (new) {
             if (seat.windowing_scheduled.window) |window| {
                 if (window.object) |window_v1| {
diff --git a/rivercompat/Seat.zig b/rivercompat/Seat.zig
index 1f6bb1f..dbca16c 100644
--- a/rivercompat/Seat.zig
+++ b/rivercompat/Seat.zig
@@ -72,6 +72,7 @@ fn handleEvent(seat_v1: *river.SeatV1, event: river.SeatV1.Event, seat: *Seat) v
             seat_v1.destroy();
             gpa.destroy(seat);
         },
+        .wl_seat => {},
         .pointer_enter => |args| {
             const window_v1 = args.window orelse return;
             const window: *Window = @ptrCast(@alignCast(window_v1.getUserData()));