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

commitffd185aabff270a04754449c2a6b1c0e2e315084
parentc14f6e5346
authorLucas Galante <[email protected]>
date2026-06-16 08:41
Implement expose mode (as Grid layout toggle) and expose IPC command

 src/server/cursor.rs         | 14 ++++++++++++++
 src/server/window_manager.rs | 23 +++++++++++++++++++----
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 3c073b7..4ed923f 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -1045,6 +1045,8 @@ unsafe extern "C" fn handle_swipe_begin(listener: *mut ffi::wl_listener, data: *
     cursor.gesture_dy = 0.0;
     cursor.gesture_triggered = false;
 
+    log::info!("handle_swipe_begin: fingers={}", (*event).fingers);
+
     let server = seat.server;
     let pointer_gestures = (*server).input_manager.pointer_gestures;
     if !pointer_gestures.is_null() {
@@ -1071,6 +1073,15 @@ unsafe extern "C" fn handle_swipe_update(listener: *mut ffi::wl_listener, data:
     cursor.gesture_dx += (*event).dx;
     cursor.gesture_dy += (*event).dy;
 
+    log::info!(
+        "handle_swipe_update: fingers={}, dx={}, dy={}, accumulated_dx={}, accumulated_dy={}",
+        (*event).fingers,
+        (*event).dx,
+        (*event).dy,
+        cursor.gesture_dx,
+        cursor.gesture_dy
+    );
+
     let wlr_keyboard = ffi::river_wlr_seat_get_keyboard(seat.wlr_seat);
     let modifiers = if !wlr_keyboard.is_null() {
         ffi::wlr_keyboard_get_modifiers(wlr_keyboard)
@@ -1099,6 +1110,7 @@ unsafe extern "C" fn handle_swipe_update(listener: *mut ffi::wl_listener, data:
     }
 
     if matched_action != crate::config::Action::None {
+        log::info!("Swipe gesture matched action: {:?}", matched_action);
         cursor.gesture_triggered = true;
         (*seat.server).wm.execute_action(&matched_action, matched_command.as_deref());
 
@@ -1134,6 +1146,8 @@ unsafe extern "C" fn handle_swipe_end(listener: *mut ffi::wl_listener, data: *mu
     let seat = &mut *cursor.seat;
     seat.handle_activity();
 
+    log::info!("handle_swipe_end: cancelled={}", (*event).cancelled);
+
     if cursor.gesture_triggered {
         cursor.gesture_triggered = false;
         return;
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 3b94649..03b5747 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -70,6 +70,7 @@ pub struct WindowManager {
     pub output_scale: f32,
     pub input_rules: Vec<crate::config::InputDeviceConfigRule>,
     pub input_config: crate::config::InputConfig,
+    pub expose_active: bool,
 }
 
 impl WindowManager {
@@ -126,6 +127,7 @@ impl WindowManager {
         self.status_sender = None;
         self.input_rules = Vec::new();
         self.input_config = crate::config::InputConfig::default();
+        self.expose_active = false;
 
         ffi::wl_list_init(&mut self.sent.outputs);
         ffi::wl_list_init(&mut self.sent.seats);
@@ -554,10 +556,6 @@ impl WindowManager {
     }
 
     pub unsafe fn get_mode_for_window(&self, win: *mut Window) -> crate::tiling::TilingMode {
-        if (*win).mode_locked {
-            return (*win).tiling_mode;
-        }
-
         let app_id = (*win).get_app_id_string();
         if app_id.as_deref() == Some("cce-status-interface") {
             return crate::tiling::TilingMode::Fullscreen;
@@ -566,6 +564,14 @@ impl WindowManager {
             return crate::tiling::TilingMode::Popup;
         }
 
+        if self.expose_active {
+            return crate::tiling::TilingMode::Grid;
+        }
+
+        if (*win).mode_locked {
+            return (*win).tiling_mode;
+        }
+
         if (*win).has_parent {
             return crate::tiling::TilingMode::Floating;
         }
@@ -1461,6 +1467,11 @@ impl WindowManager {
                 self.layout.side_panel_position = "right".to_string();
                 self.dirty_windowing();
             }
+            Action::Expose => {
+                self.expose_active = !self.expose_active;
+                log::info!("Expose mode toggled: {}", self.expose_active);
+                self.dirty_windowing();
+            }
             _ => {}
         }
     }
@@ -1521,6 +1532,10 @@ impl WindowManager {
                 self.execute_action(&crate::config::Action::Close, None);
                 "ok\n".to_string()
             }
+            "expose" => {
+                self.execute_action(&crate::config::Action::Expose, None);
+                "ok\n".to_string()
+            }
             "minimize" => {
                 self.execute_action(&crate::config::Action::Minimize, None);
                 "ok\n".to_string()