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

commitdcfdff7a3cc6dee06845289ef3f88c43931c55db
parent3501633898
authorLucas Galante <[email protected]>
date2026-06-24 15:27
Fix window size restoration and matching on resume, and add modifiers status support

 src/server/keyboard.rs       |  5 +++++
 src/server/status_server.rs  | 17 +++++++++++++++++
 src/server/window.rs         | 21 +++++++++++++++++++++
 src/server/window_manager.rs | 13 ++++++++++++-
 4 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/src/server/keyboard.rs b/src/server/keyboard.rs
index 45b6317..025132c 100644
--- a/src/server/keyboard.rs
+++ b/src/server/keyboard.rs
@@ -247,5 +247,10 @@ unsafe extern "C" fn handle_modifiers(listener: *mut ffi::wl_listener, _data: *m
     if !keyboard.group.is_null() {
         let modifiers = ffi::river_wlr_keyboard_get_modifiers(keyboard.wlr_keyboard);
         (*keyboard.group).process_modifiers(*modifiers);
+        
+        let seat = (*keyboard.group).seat;
+        if !seat.is_null() && !(*seat).server.is_null() {
+            (*(*seat).server).wm.update_status();
+        }
     }
 }
diff --git a/src/server/status_server.rs b/src/server/status_server.rs
index ebc0207..1541db3 100644
--- a/src/server/status_server.rs
+++ b/src/server/status_server.rs
@@ -20,6 +20,8 @@ pub struct StatusUpdate {
     pub layout_text: String,
     /// Plain text for title module subscribers
     pub title_text: String,
+    /// Plain text for modifiers subscriber
+    pub modifiers_text: String,
 }
 
 /// Subscription types that the status bar script can request.
@@ -28,6 +30,7 @@ enum Subscription {
     Tags,
     Layout,
     Title,
+    Modifiers,
     Unknown,
 }
 
@@ -37,6 +40,7 @@ impl Subscription {
             "tags" => Subscription::Tags,
             "layout" => Subscription::Layout,
             "title" => Subscription::Title,
+            "modifiers" => Subscription::Modifiers,
             _ => Subscription::Unknown,
         }
     }
@@ -227,6 +231,7 @@ fn format_for_subscription(sub: Subscription, update: &StatusUpdate) -> String {
         Subscription::Tags => update.tags_json.clone(),
         Subscription::Layout => update.layout_text.clone(),
         Subscription::Title => update.title_text.clone(),
+        Subscription::Modifiers => update.modifiers_text.clone(),
         Subscription::Unknown => String::new(),
     }
 }
@@ -265,9 +270,21 @@ pub unsafe fn build_status_update(wm: &crate::window_manager::WindowManager) ->
         }
     };
 
+    let seat_ptr = wm.first_seat().unwrap_or(std::ptr::null_mut());
+    let mut super_pressed = false;
+    if !seat_ptr.is_null() {
+        let wlr_keyboard = crate::ffi::river_wlr_seat_get_keyboard((*seat_ptr).wlr_seat);
+        if !wlr_keyboard.is_null() {
+            let modifiers = crate::ffi::wlr_keyboard_get_modifiers(wlr_keyboard);
+            super_pressed = modifiers & 0x40 != 0;
+        }
+    }
+    let modifiers_text = if super_pressed { "super" } else { "none" }.to_string();
+
     StatusUpdate {
         tags_json,
         layout_text,
         title_text,
+        modifiers_text,
     }
 }
diff --git a/src/server/window.rs b/src/server/window.rs
index 4bfc7af..dd814b5 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -645,6 +645,27 @@ impl Window {
                 height: saved.height,
             };
             
+            self.rendering_scheduled.width = saved.width;
+            self.rendering_scheduled.height = saved.height;
+            self.rendering_sent.width = saved.width;
+            self.rendering_sent.height = saved.height;
+
+            match self.impl_type {
+                WindowImpl::Toplevel(toplevel) => {
+                    if !toplevel.is_null() {
+                        (*toplevel).geometry.width = saved.width as i32;
+                        (*toplevel).geometry.height = saved.height as i32;
+                    }
+                }
+                WindowImpl::Xwayland(xwindow) => {
+                    if !xwindow.is_null() && !(*xwindow).xsurface.is_null() {
+                        (*(*xwindow).xsurface).width = saved.width as u16;
+                        (*(*xwindow).xsurface).height = saved.height as u16;
+                    }
+                }
+                _ => {}
+            }
+
             self.restored = true;
         }
     }
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 01cff0c..ecbff8e 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -303,7 +303,18 @@ impl WindowManager {
         if let Some(pos) = self.restore_queue.iter().position(|w| w.app_id == app_id && w.title == title) {
             return Some(self.restore_queue.remove(pos));
         }
-        // Second pass: app_id only match
+        // Second pass: Fuzzy title match (e.g. prefix match, asterisk stripping)
+        if let Some(pos) = self.restore_queue.iter().position(|w| {
+            if w.app_id != app_id {
+                return false;
+            }
+            let t1 = title.trim_end_matches('*');
+            let t2 = w.title.trim_end_matches('*');
+            t1 == t2 || t1.starts_with(t2) || t2.starts_with(t1)
+        }) {
+            return Some(self.restore_queue.remove(pos));
+        }
+        // Third pass: app_id only match
         if let Some(pos) = self.restore_queue.iter().position(|w| w.app_id == app_id) {
             return Some(self.restore_queue.remove(pos));
         }