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