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

commit7346c3270438c4b2a09dd2cfdf6f37dfeba6d3c6
parent5856276ec5
authorLucas Galante <[email protected]>
date2026-07-03 10:33
Offset cce-cloud sub-menus by their parent status module position

 src/server/cursor.rs         |  8 +++----
 src/server/keyboard_group.rs |  2 +-
 src/server/layer_shell.rs    | 52 +++++++++++++++++++++++++++++++++++++++++++-
 src/server/status_server.rs  |  2 +-
 src/server/window_manager.rs |  2 +-
 5 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 1281d30..0f5f01f 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -604,7 +604,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
                     let wlr_layer_surface = (*layer_surface).wlr_layer_surface;
                     if !wlr_layer_surface.is_null() && !(*wlr_layer_surface).namespace.is_null() {
                         let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
-                        if ns == "cce-cloud" {
+                        if ns.starts_with("cce-cloud") {
                             is_overlay_window = true;
                         }
                     }
@@ -1396,7 +1396,7 @@ unsafe extern "C" fn handle_touch_down(listener: *mut ffi::wl_listener, data: *m
                     let wlr_layer_surface = (*layer_surface).wlr_layer_surface;
                     if !wlr_layer_surface.is_null() && !(*wlr_layer_surface).namespace.is_null() {
                         let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
-                        if ns == "cce-cloud" {
+                        if ns.starts_with("cce-cloud") {
                             is_overlay_window = true;
                         }
                     }
@@ -1465,7 +1465,7 @@ unsafe extern "C" fn handle_touch_motion(listener: *mut ffi::wl_listener, data:
                         let wlr_layer_surface = (*layer_surface).wlr_layer_surface;
                         if !wlr_layer_surface.is_null() && !(*wlr_layer_surface).namespace.is_null() {
                             let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
-                            if ns == "cce-cloud" {
+                            if ns.starts_with("cce-cloud") {
                                 is_overlay_window = true;
                             }
                         }
@@ -1518,7 +1518,7 @@ unsafe extern "C" fn handle_touch_up(listener: *mut ffi::wl_listener, data: *mut
                         let wlr_layer_surface = (*layer_surface).wlr_layer_surface;
                         if !wlr_layer_surface.is_null() && !(*wlr_layer_surface).namespace.is_null() {
                             let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
-                            if ns == "cce-cloud" {
+                            if ns.starts_with("cce-cloud") {
                                 is_overlay_window = true;
                             }
                         }
diff --git a/src/server/keyboard_group.rs b/src/server/keyboard_group.rs
index 7cd2784..6a55c66 100644
--- a/src/server/keyboard_group.rs
+++ b/src/server/keyboard_group.rs
@@ -452,7 +452,7 @@ unsafe extern "C" fn handle_group_key(listener: *mut ffi::wl_listener, data: *mu
                     let wlr_layer_surface = crate::ffi::wlr_layer_surface_v1_try_from_wlr_surface(focused_layer);
                     if !wlr_layer_surface.is_null() && !(*wlr_layer_surface).namespace.is_null() {
                         let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
-                        ns == "cce-cloud"
+                        ns.starts_with("cce-cloud")
                     } else {
                         false
                     }
diff --git a/src/server/layer_shell.rs b/src/server/layer_shell.rs
index 90e7dfa..da7c5d3 100644
--- a/src/server/layer_shell.rs
+++ b/src/server/layer_shell.rs
@@ -304,6 +304,7 @@ pub struct LayerSurface {
     pub unmap: ffi::wl_listener,
     pub commit: ffi::wl_listener,
     pub new_popup: ffi::wl_listener,
+    pub parent_offset_applied: bool,
 }
 
 impl LayerSurface {
@@ -336,6 +337,7 @@ impl LayerSurface {
             unmap: std::mem::zeroed(),
             commit: std::mem::zeroed(),
             new_popup: std::mem::zeroed(),
+            parent_offset_applied: false,
         }));
 
         let key = (*server).layer_shell.surfaces.put(layer_surface);
@@ -550,7 +552,7 @@ unsafe extern "C" fn handle_layer_surface_unmap(listener: *mut ffi::wl_listener,
                     let mut is_cce_cloud = false;
                     if !(*wlr_layer_surface).namespace.is_null() {
                         let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
-                        if ns == "cce-cloud" {
+                        if ns.starts_with("cce-cloud") {
                             is_cce_cloud = true;
                         }
                     }
@@ -637,6 +639,54 @@ unsafe extern "C" fn handle_layer_surface_commit(listener: *mut ffi::wl_listener
 
     let server = (*layer_surface).server;
 
+    // Position offset for cce-cloud sub-modules
+    if !(*layer_surface).parent_offset_applied {
+        if !(*wlr_layer_surface).namespace.is_null() {
+            let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
+            if ns.starts_with("cce-cloud:") {
+                let parent_app_id = &ns["cce-cloud:".len()..];
+                let mut parent_x = None;
+                let mut parent_y = None;
+                let mut parent_w = 0;
+                for &win_ptr in (*server).wm.windows.iter() {
+                    if win_ptr.is_null() || (*win_ptr).closed {
+                        continue;
+                    }
+                    if let Some(win_app_id) = (*win_ptr).get_app_id_string() {
+                        if win_app_id == parent_app_id {
+                            parent_x = Some((*win_ptr).rendering_requested.x);
+                            parent_y = Some((*win_ptr).rendering_requested.y);
+                            parent_w = (*win_ptr).box_geom.width;
+                            break;
+                        }
+                    }
+                }
+
+                if let (Some(px), Some(py)) = (parent_x, parent_y) {
+                    let wlr_box = (*output).sent.box_layout();
+                    let output_x = wlr_box.x;
+                    let output_y = wlr_box.y;
+                    let output_w = wlr_box.width;
+
+                    let relative_parent_x = px - output_x;
+                    let relative_parent_y = py - output_y;
+
+                    let anchor = (*wlr_layer_surface).current.anchor;
+                    let is_align_right = (anchor & ffi::zwlr_layer_surface_v1_anchor_ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) != 0;
+
+                    if is_align_right {
+                        (*wlr_layer_surface).current.margin.right = (output_w - relative_parent_x - parent_w) + (*wlr_layer_surface).current.margin.right;
+                    } else {
+                        (*wlr_layer_surface).current.margin.left = relative_parent_x + (*wlr_layer_surface).current.margin.left;
+                    }
+                    (*wlr_layer_surface).current.margin.top = relative_parent_y + (*wlr_layer_surface).current.margin.top;
+
+                    (*layer_surface).parent_offset_applied = true;
+                }
+            }
+        }
+    }
+
     // Check if layer was changed
     if (*wlr_layer_surface).current.committed & ffi::wlr_layer_surface_v1_state_field_WLR_LAYER_SURFACE_V1_STATE_LAYER != 0 {
         let tree = (*server).scene.layer_surface_tree((*wlr_layer_surface).current.layer);
diff --git a/src/server/status_server.rs b/src/server/status_server.rs
index a409618..1d4b886 100644
--- a/src/server/status_server.rs
+++ b/src/server/status_server.rs
@@ -252,7 +252,7 @@ pub unsafe fn build_status_update(wm: &crate::window_manager::WindowManager) ->
             let wlr_layer_surface = crate::ffi::wlr_layer_surface_v1_try_from_wlr_surface(focused_layer);
             if !wlr_layer_surface.is_null() && !(*wlr_layer_surface).namespace.is_null() {
                 let ns = std::ffi::CStr::from_ptr((*wlr_layer_surface).namespace).to_string_lossy();
-                if ns == "cce-cloud" {
+                if ns.starts_with("cce-cloud") {
                     is_cce_cloud = true;
                 }
             }
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 644a2fa..c5bd076 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -1003,7 +1003,7 @@ impl WindowManager {
         if app_id.as_deref() == Some("cce-notifier") || app_id.as_deref() == Some("cce-notification-daemon") || app_id.as_deref() == Some("clear-notification-daemon") {
             return crate::tiling::TilingMode::Popup;
         }
-        if app_id.as_deref() == Some("cce-cloud") {
+        if app_id.as_deref().map_or(false, |id| id.starts_with("cce-cloud")) {
             return crate::tiling::TilingMode::Overlay;
         }