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

commit8c1adb53e6ac32421b0e05185a6602ecba683269
parentdff66b4971
authorLucas Galante <[email protected]>
date2026-06-16 18:31
feat: automatically enter floating mode on window move or resize

 src/server/config.rs         | 11 +++++++----
 src/server/cursor.rs         | 21 ++++++++++++---------
 src/server/tiling.rs         |  6 +++---
 src/server/window_manager.rs | 19 +++++++++++++++----
 4 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/src/server/config.rs b/src/server/config.rs
index bfbdbca..4b732f2 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -823,10 +823,13 @@ mod tests {
             assert_eq!(server.wm.input_config.dwtp, Some(true));
             assert_eq!(server.wm.input_config.trackpoint_accel_speed, Some(0.6));
             assert_eq!(server.wm.input_config.trackpoint_accel_profile, Some("flat".to_string()));
-            assert_eq!(server.wm.layout.low_color, "#1c2020");
-            assert_eq!(server.wm.layout.background_r, 0x1C1C1C1Cu32);
-            assert_eq!(server.wm.layout.background_g, 0x20202020u32);
-            assert_eq!(server.wm.layout.background_b, 0x20202020u32);
+            let parsed_color = parse_hex_color(&server.wm.layout.low_color);
+            let r = (parsed_color >> 16) & 0xFF;
+            let g = (parsed_color >> 8) & 0xFF;
+            let b = parsed_color & 0xFF;
+            assert_eq!(server.wm.layout.background_r, r * 0x01010101);
+            assert_eq!(server.wm.layout.background_g, g * 0x01010101);
+            assert_eq!(server.wm.layout.background_b, b * 0x01010101);
         }
     }
 }
diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 7af1589..3a1b302 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -458,8 +458,8 @@ impl Cursor {
             }
 
             if let SceneNodeDataVal::Window(window) = result.data {
-                if (*window).tiling_mode == crate::tiling::TilingMode::Floating
-                    || (*window).tiling_mode == crate::tiling::TilingMode::Cascade
+                if (*window).tiling_mode != crate::tiling::TilingMode::Popup
+                    && (*window).tiling_mode != crate::tiling::TilingMode::Fullscreen
                 {
                     match get_border_zone(window, lx, ly) {
                         BorderZone::Resize(edges) => {
@@ -587,7 +587,10 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
             }
             
             if !target_win.is_null() {
-                if (*target_win).tiling_mode == crate::tiling::TilingMode::Cascade {
+                if (*target_win).tiling_mode != crate::tiling::TilingMode::Floating
+                    && (*target_win).tiling_mode != crate::tiling::TilingMode::Popup
+                    && (*target_win).tiling_mode != crate::tiling::TilingMode::Fullscreen
+                {
                     (*target_win).tiling_mode = crate::tiling::TilingMode::Floating;
                     (*target_win).mode_locked = true;
                 }
@@ -647,14 +650,14 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
         }
 
         if !border_target_win.is_null() && (
-            (*border_target_win).tiling_mode == crate::tiling::TilingMode::Floating
-            || (*border_target_win).tiling_mode == crate::tiling::TilingMode::Cascade
+            (*border_target_win).tiling_mode != crate::tiling::TilingMode::Popup
+            && (*border_target_win).tiling_mode != crate::tiling::TilingMode::Fullscreen
         ) {
             let initial_mode = (*border_target_win).tiling_mode;
             match get_border_zone(border_target_win, lx, ly) {
                 BorderZone::Resize(edges) => {
                     if (*event).button == 0x110 { // BTN_LEFT
-                        if initial_mode == crate::tiling::TilingMode::Cascade {
+                        if initial_mode != crate::tiling::TilingMode::Floating {
                             (*border_target_win).tiling_mode = crate::tiling::TilingMode::Floating;
                             (*border_target_win).mode_locked = true;
                         }
@@ -686,7 +689,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
                 }
                 BorderZone::Move => {
                     if (*event).button == 0x110 { // BTN_LEFT
-                        if initial_mode == crate::tiling::TilingMode::Cascade {
+                        if initial_mode != crate::tiling::TilingMode::Floating {
                             (*border_target_win).tiling_mode = crate::tiling::TilingMode::Floating;
                             (*border_target_win).mode_locked = true;
                         }
@@ -1329,8 +1332,8 @@ pub unsafe fn get_border_zone(window: *mut crate::window::Window, lx: f64, ly: f
     if (*(*window).server).wm.expose_active {
         return BorderZone::None;
     }
-    if (*window).tiling_mode != crate::tiling::TilingMode::Floating
-        && (*window).tiling_mode != crate::tiling::TilingMode::Cascade
+    if (*window).tiling_mode == crate::tiling::TilingMode::Popup
+        || (*window).tiling_mode == crate::tiling::TilingMode::Fullscreen
     {
         return BorderZone::None;
     }
diff --git a/src/server/tiling.rs b/src/server/tiling.rs
index a82c104..c287093 100644
--- a/src/server/tiling.rs
+++ b/src/server/tiling.rs
@@ -41,12 +41,12 @@ pub fn tile_cascade(
     gap_right: i32,
     gap_bottom: i32,
     bw: i32,
+    dec_h: i32,
     cascade_offset: i32,
     bar_height: i32,
     n_cascade: i32,
     idx: i32,
 ) -> (i32, i32, i32, i32) {
-    let dec_h = std::cmp::max(bw, 16);
     let max_offsets = 5;
     let eff_cascade = n_cascade.min(max_offsets);
     let width = screen_w - gap_left - gap_right - bw * 2 - cascade_offset * (eff_cascade - 1);
@@ -69,6 +69,7 @@ pub fn tile_grid(
     gap_right: i32,
     gap_bottom: i32,
     bw: i32,
+    dec_h: i32,
     bar_height: i32,
     n_grid: i32,
     idx: i32,
@@ -77,7 +78,6 @@ pub fn tile_grid(
     let row = idx / cols;
     let col = idx % cols;
     let rows = (n_grid + cols - 1) / cols;
-    let dec_h = std::cmp::max(bw, 16);
     let width = (screen_w - gap_left - gap_right - (cols - 1) * gap) / cols - 2 * bw;
     let height = (screen_h - bar_height - gap_top - gap_bottom - (rows - 1) * gap) / rows - (dec_h + bw);
     let width = if width < 1 { 1 } else { width };
@@ -97,11 +97,11 @@ pub fn tile_expose(
     gap_right: i32,
     gap_bottom: i32,
     bw: i32,
+    dec_h: i32,
     bar_height: i32,
     n_expose: i32,
     idx: i32,
 ) -> (i32, i32, i32, i32) {
-    let dec_h = std::cmp::max(bw, 16);
     if n_expose == 1 {
         // Center the single window and scale to 70% of the screen
         let usable_h = screen_h - bar_height - gap_top - gap_bottom;
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 732f915..93ab940 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -820,29 +820,40 @@ impl WindowManager {
             let bar_height = self.layout.bar_height;
 
             for (idx, &win_ptr) in tiled_windows.iter().enumerate() {
+                let win_bw = if !(*win_ptr).wm_requested.ssd {
+                    0
+                } else {
+                    bw
+                };
+                let win_dec_h = if !(*win_ptr).wm_requested.ssd {
+                    0
+                } else {
+                    std::cmp::max(win_bw, 16)
+                };
+
                 let (x, y, w, h) = match current_layout {
                     crate::tiling::TilingMode::Cascade => {
                         crate::tiling::tile_cascade(
                             tiled_usable_w, usable_h, gap, gap_top, gap_left, gap_right, gap_bottom,
-                            bw, cascade_offset, bar_height, n_tiled, idx as i32
+                            win_bw, win_dec_h, cascade_offset, bar_height, n_tiled, idx as i32
                         )
                     }
                     crate::tiling::TilingMode::Grid => {
                         crate::tiling::tile_grid(
                             tiled_usable_w, usable_h, gap, gap_top, gap_left, gap_right, gap_bottom,
-                            bw, bar_height, n_tiled, idx as i32
+                            win_bw, win_dec_h, bar_height, n_tiled, idx as i32
                         )
                     }
                     crate::tiling::TilingMode::Expose => {
                         crate::tiling::tile_expose(
                             tiled_usable_w, usable_h, gap, gap_top, gap_left, gap_right, gap_bottom,
-                            bw, bar_height, n_tiled, idx as i32
+                            win_bw, win_dec_h, bar_height, n_tiled, idx as i32
                         )
                     }
                     crate::tiling::TilingMode::Fullscreen => {
                         crate::tiling::tile_fullscreen(
                             tiled_usable_w, usable_h, gap_top, gap_left, gap_right, gap_bottom,
-                            bw, bar_height
+                            win_bw, bar_height
                         )
                     }
                     _ => {