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

commite42a2d1a5a8a47682802d08239b7dcaf7a9db2b0
parentd982cfd299
authorLucas Galante <[email protected]>
date2026-08-05 10:17
feat: mechanism side of expanded status segments

Window::status_collapsed_len tracks each status segment's along-bar
length while it is at bar thickness (refreshed in the arrange snapshot
builder, which sees exactly the geometry the pass will use) and feeds
WindowSnapshot::status_collapsed_len. While a segment is thicker than
the bar (in-surface menu open) it is raised to the top of the scene so
the menu draws above the windows it overlaps.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/server/window.rs         |  6 ++++++
 src/server/window_manager.rs | 19 +++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/src/server/window.rs b/src/server/window.rs
index e202586..c513e09 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -405,6 +405,11 @@ pub struct Window {
     /// render-start snapshot (`rendering_sent`), which still holds the previous
     /// size and would snap the border back. Cleared once consumed.
     pub self_resized: bool,
+    /// Status segments: the along-bar length last seen while the segment was
+    /// at bar thickness. Feeds WindowSnapshot::status_collapsed_len so an
+    /// EXPANDED segment (surface grown into an in-surface menu) keeps its
+    /// frozen slot in the arrange pass.
+    pub status_collapsed_len: i32,
     /// Set by the commit listener, cleared by the window-manager stream
     /// timer after a capture: the damage gate for `stream_server` frames.
     /// Starts true so a fresh subscriber gets an immediate first frame.
@@ -612,6 +617,7 @@ impl Window {
             resize_start_h: 0,
             resize_edges: None,
             self_resized: false,
+            status_collapsed_len: 0,
             stream_dirty: true,
             commit: std::mem::zeroed(),
             was_fullscreen: false,
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 18374d5..848e7d0 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -1716,6 +1716,24 @@ impl WindowManager {
             } else {
                 None
             };
+            // Status segments: refresh the frozen collapsed slot length
+            // while at bar thickness; while EXPANDED (in-surface menu, the
+            // surface is thicker than the bar) keep the frozen value and
+            // raise the segment above its siblings and the windows the open
+            // menu now overlaps.
+            if (*win_ptr).get_app_id_string().map_or(false, |id| id.starts_with("cce-status")) {
+                let bg = (*win_ptr).box_geom;
+                let (len, thickness) = match (*win_ptr).status_edge {
+                    crate::policy::arrange::StatusEdge::Left
+                    | crate::policy::arrange::StatusEdge::Right => (bg.height, bg.width),
+                    _ => (bg.width, bg.height),
+                };
+                if thickness > 0 && thickness <= self.layout.bar_height {
+                    (*win_ptr).status_collapsed_len = len;
+                } else if thickness > self.layout.bar_height {
+                    ffi::wlr_scene_node_raise_to_top((*win_ptr).tree as *mut _);
+                }
+            }
             window_snaps.push(crate::policy::arrange::WindowSnapshot {
                 app_id: (*win_ptr).get_app_id_string(),
                 title: (*win_ptr).get_title_string(),
@@ -1723,6 +1741,7 @@ impl WindowManager {
                 minimized: (*win_ptr).minimized,
                 closing_or_init: matches!((*win_ptr).state, crate::window::WindowState::Closing | crate::window::WindowState::Init),
                 mode: self.get_mode_for_window(win_ptr),
+                status_collapsed_len: (*win_ptr).status_collapsed_len,
                 rule_ssd,
                 being_moved: self.is_window_being_moved(win_ptr),
                 status_edge: (*win_ptr).status_edge,