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

commita44f72c7f5cb5bf40dc8e8e4c289ecae45f5def6
parentc0a2918d11
authorLucas Galante <[email protected]>
date2026-06-26 12:53
feat: refine overview input disabling to ensure release safety and keep status bar interactive

 src/server/cursor.rs         | 128 +++++++++++++++++++++++++++++++++----------
 src/server/keyboard_group.rs |   4 +-
 2 files changed, 101 insertions(+), 31 deletions(-)

diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 31416fc..b1e609d 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -458,30 +458,36 @@ impl Cursor {
             }
 
             let mut is_window = false;
-            if let SceneNodeDataVal::Window(window) = result.data {
-                if !(*window).is_status_bar() {
-                    is_window = true;
-                }
-                if (*window).tiling_mode != crate::tiling::TilingMode::Popup
-                    && (*window).tiling_mode != crate::tiling::TilingMode::Fullscreen
-                    && (*window).tiling_mode != crate::tiling::TilingMode::Status
-                    && (*server).wm.mode == crate::window_manager::WindowManagerMode::Normal
-                {
-                    match get_border_zone(window, lx, ly) {
-                        BorderZone::Resize(edges) => {
-                            ffi::wlr_seat_pointer_notify_clear_focus((*self.seat).wlr_seat);
-                            let cursor_name = get_resize_cursor_name(edges);
-                            self.set_xcursor(cursor_name.as_ptr() as *const _);
-                            return;
-                        }
-                        BorderZone::Move => {
-                            ffi::wlr_seat_pointer_notify_clear_focus((*self.seat).wlr_seat);
-                            self.set_xcursor(b"grab\0".as_ptr() as *const _);
-                            return;
+            match result.data {
+                SceneNodeDataVal::Window(window) => {
+                    if !(*window).is_status_bar() {
+                        is_window = true;
+                    }
+                    if (*window).tiling_mode != crate::tiling::TilingMode::Popup
+                        && (*window).tiling_mode != crate::tiling::TilingMode::Fullscreen
+                        && (*window).tiling_mode != crate::tiling::TilingMode::Status
+                        && (*server).wm.mode == crate::window_manager::WindowManagerMode::Normal
+                    {
+                        match get_border_zone(window, lx, ly) {
+                            BorderZone::Resize(edges) => {
+                                ffi::wlr_seat_pointer_notify_clear_focus((*self.seat).wlr_seat);
+                                let cursor_name = get_resize_cursor_name(edges);
+                                self.set_xcursor(cursor_name.as_ptr() as *const _);
+                                return;
+                            }
+                            BorderZone::Move => {
+                                ffi::wlr_seat_pointer_notify_clear_focus((*self.seat).wlr_seat);
+                                self.set_xcursor(b"grab\0".as_ptr() as *const _);
+                                return;
+                            }
+                            BorderZone::None => {}
                         }
-                        BorderZone::None => {}
                     }
                 }
+                SceneNodeDataVal::ShellSurface(_) | SceneNodeDataVal::OverrideRedirect(_) => {
+                    is_window = true;
+                }
+                _ => {}
             }
 
             if is_window && (*server).wm.mode == crate::window_manager::WindowManagerMode::Overview {
@@ -564,6 +570,25 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
     let event = data as *mut ffi::wlr_pointer_button_event;
     
     let seat = &mut *cursor.seat;
+    let lx = cursor.x();
+    let ly = cursor.y();
+    let server = seat.server;
+
+    let mut is_app_surface = false;
+    if let Some(result) = (*server).scene.at(lx, ly) {
+        match result.data {
+            SceneNodeDataVal::Window(window) => {
+                if !(*window).is_status_bar() {
+                    is_app_surface = true;
+                }
+            }
+            SceneNodeDataVal::ShellSurface(_) | SceneNodeDataVal::OverrideRedirect(_) => {
+                is_app_surface = true;
+            }
+            _ => {}
+        }
+    }
+    let should_block_button = (*(*seat).server).wm.mode == crate::window_manager::WindowManagerMode::Overview && is_app_surface;
     
     if (*event).state == ffi::wl_pointer_button_state_WL_POINTER_BUTTON_STATE_PRESSED {
         if cursor.pressed.contains_key(&(*event).button) {
@@ -573,9 +598,6 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
 
         // --- ZOOMED OUT CLICK HANDLING ---
         if (*event).button == 0x110 && (*(*seat).server).wm.mode == crate::window_manager::WindowManagerMode::Overview {
-            let lx = cursor.x();
-            let ly = cursor.y();
-            let server = seat.server;
             let mut clicked_win: *mut crate::window::Window = std::ptr::null_mut();
             if let Some(result) = (*server).scene.at(lx, ly) {
                 if let SceneNodeDataVal::Window(window) = result.data {
@@ -804,7 +826,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
 
         cursor.pressed.insert((*event).button, None);
 
-        if (*(*seat).server).wm.mode != crate::window_manager::WindowManagerMode::Overview {
+        if !should_block_button {
             ffi::wlr_seat_pointer_notify_button(
                 seat.wlr_seat,
                 (*event).time_msec,
@@ -916,7 +938,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
                 return;
             }
 
-            if (*(*seat).server).wm.mode != crate::window_manager::WindowManagerMode::Overview {
+            if !should_block_button {
                 ffi::wlr_seat_pointer_notify_button(
                     seat.wlr_seat,
                     (*event).time_msec,
@@ -1163,7 +1185,22 @@ unsafe extern "C" fn handle_touch_down(listener: *mut ffi::wl_listener, data: *m
             }
             _ => {}
         }
-        if !result.surface.is_null() && (*(*seat).server).wm.mode != crate::window_manager::WindowManagerMode::Overview {
+        
+        let mut is_app_surface = false;
+        match result.data {
+            SceneNodeDataVal::Window(window) => {
+                if !(*window).is_status_bar() {
+                    is_app_surface = true;
+                }
+            }
+            SceneNodeDataVal::ShellSurface(_) | SceneNodeDataVal::OverrideRedirect(_) => {
+                is_app_surface = true;
+            }
+            _ => {}
+        }
+        let should_block_touch = (*(*seat).server).wm.mode == crate::window_manager::WindowManagerMode::Overview && is_app_surface;
+
+        if !result.surface.is_null() && !should_block_touch {
             ffi::wlr_seat_touch_notify_down(
                 seat.wlr_seat,
                 result.surface,
@@ -1202,7 +1239,21 @@ unsafe extern "C" fn handle_touch_motion(listener: *mut ffi::wl_listener, data:
 
         let server = seat.server;
         if let Some(result) = (*server).scene.at(lx, ly) {
-            if (*(*seat).server).wm.mode != crate::window_manager::WindowManagerMode::Overview {
+            let mut is_app_surface = false;
+            match result.data {
+                SceneNodeDataVal::Window(window) => {
+                    if !(*window).is_status_bar() {
+                        is_app_surface = true;
+                    }
+                }
+                SceneNodeDataVal::ShellSurface(_) | SceneNodeDataVal::OverrideRedirect(_) => {
+                    is_app_surface = true;
+                }
+                _ => {}
+            }
+            let should_block_touch = (*(*seat).server).wm.mode == crate::window_manager::WindowManagerMode::Overview && is_app_surface;
+
+            if !should_block_touch {
                 ffi::wlr_seat_touch_notify_motion(
                     seat.wlr_seat,
                     (*event).time_msec,
@@ -1222,8 +1273,25 @@ unsafe extern "C" fn handle_touch_up(listener: *mut ffi::wl_listener, data: *mut
     let seat = &mut *cursor.seat;
     seat.handle_activity();
 
-    if cursor.touch_points.remove(&(*event).touch_id).is_some() {
-        if (*(*seat).server).wm.mode != crate::window_manager::WindowManagerMode::Overview {
+    if let Some((lx, ly)) = cursor.touch_points.remove(&(*event).touch_id) {
+        let server = seat.server;
+        let mut is_app_surface = false;
+        if let Some(result) = (*server).scene.at(lx, ly) {
+            match result.data {
+                SceneNodeDataVal::Window(window) => {
+                    if !(*window).is_status_bar() {
+                        is_app_surface = true;
+                    }
+                }
+                SceneNodeDataVal::ShellSurface(_) | SceneNodeDataVal::OverrideRedirect(_) => {
+                    is_app_surface = true;
+                }
+                _ => {}
+            }
+        }
+        let should_block_touch = (*(*seat).server).wm.mode == crate::window_manager::WindowManagerMode::Overview && is_app_surface;
+
+        if !should_block_touch {
             ffi::wlr_seat_touch_notify_up(
                 seat.wlr_seat,
                 (*event).time_msec,
diff --git a/src/server/keyboard_group.rs b/src/server/keyboard_group.rs
index ed67286..3c7e066 100644
--- a/src/server/keyboard_group.rs
+++ b/src/server/keyboard_group.rs
@@ -441,7 +441,9 @@ unsafe extern "C" fn handle_group_key(listener: *mut ffi::wl_listener, data: *mu
             }
         }
         KeyConsumer::Focus => {
-            if (*(*group.seat).server).wm.mode != crate::window_manager::WindowManagerMode::Overview {
+            if (*(*group.seat).server).wm.mode != crate::window_manager::WindowManagerMode::Overview
+                || (*event).state == ffi::wl_keyboard_key_state_WL_KEYBOARD_KEY_STATE_RELEASED
+            {
                 ffi::wlr_seat_set_keyboard((*group.seat).wlr_seat, &mut group.wlr_keyboard);
                 ffi::wlr_seat_keyboard_notify_key((*group.seat).wlr_seat, (*event).time_msec, (*event).keycode, (*event).state);
             }