Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
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));
}