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

commitdf057eb05e30a9d56ba1f8cdce08c29f3a1c5e2f
parent4087e40c4a
authorIsaac Freund <[email protected]>
date2025-01-08 15:13
Window: implement river_window_v1.set_app_id/title

Also allow sending a null app_id/title in the protocol since Xwayland
windows can do that.

 protocol/river-window-management-v1.xml | 12 ++++++++----
 river/Window.zig                        | 23 +++++++++++++++++------
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/protocol/river-window-management-v1.xml b/protocol/river-window-management-v1.xml
index 40b7f73..7a41e70 100644
--- a/protocol/river-window-management-v1.xml
+++ b/protocol/river-window-management-v1.xml
@@ -368,24 +368,28 @@
       <description summary="the window set an application ID">
         The window set an application ID.
 
-        This event may never be sent if the window never sets 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 is double-buffered state and will be followed by a
         river_window_manager_v1.update event.
       </description>
-      <arg name="app_id" type="string"/>
+      <arg name="app_id" type="string" allow-null="true"/>
     </event>
 
     <event name="title">
       <description summary="the window set a title">
         The window set a title.
 
-        This event may never be sent if the window never sets 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 is double-buffered state and will be followed by a
         river_window_manager_v1.update event.
       </description>
-      <arg name="title" type="string"/>
+      <arg name="title" type="string" allow-null="true"/>
     </event>
 
     <event name="parent">
diff --git a/river/Window.zig b/river/Window.zig
index 045a96d..cde2457 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -181,6 +181,8 @@ wm_pending: struct {
         fullscreen,
         exit,
     } = .no_request,
+    dirty_app_id: bool = false,
+    dirty_title: bool = false,
 } = .{},
 
 /// State sent to the window manager client in the latest update sequence.
@@ -420,6 +422,15 @@ pub fn sendDirty(window: *Window) void {
                 .exit => window_v1.sendExitFullscreenRequested(),
             }
             pending.fullscreen_requested = .no_request;
+
+            if (new or pending.dirty_app_id) {
+                window_v1.sendAppId(window.getAppId());
+                pending.dirty_app_id = false;
+            }
+            if (new or pending.dirty_title) {
+                window_v1.sendTitle(window.getTitle());
+                pending.dirty_title = false;
+            }
         },
     }
 }
@@ -778,12 +789,12 @@ pub fn unmap(window: *Window) void {
     server.wm.dirtyPending();
 }
 
-pub fn notifyTitle(window: *const Window) void {
-    // TODO
-    _ = window;
+pub fn notifyTitle(window: *Window) void {
+    window.wm_pending.dirty_title = true;
+    server.wm.dirtyPending();
 }
 
-pub fn notifyAppId(window: Window) void {
-    // TODO
-    _ = window;
+pub fn notifyAppId(window: *Window) void {
+    window.wm_pending.dirty_app_id = true;
+    server.wm.dirtyPending();
 }