tenseleyflow/hyprkvm / ac8c565

Browse files

fix: unify edge detection logic between RECOVERY and IPC Move

RECOVERY mode used monitor-proximity detection for Up/Down while
IPC Move used window-based detection, causing inconsistent behavior.
Now both use the same window-based detection for all directions.
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
ac8c565e37a1432591e98c4f4953f9047476efb4
Parents
35e3714
Tree
334db45

1 changed file

StatusFile+-
M hyprkvm-daemon/src/main.rs 21 31
hyprkvm-daemon/src/main.rsmodified
@@ -917,39 +917,29 @@ async fn run_daemon(config_path: &std::path::Path) -> anyhow::Result<()> {
917917
                                     }
918918
                                 };
919919
 
920
-                                // Check if any window is further in the requested direction on same monitor
921
-                                // For Up/Down: use monitor proximity instead of window detection (bars/panels cause false positives)
922
-                                let mon_logical_h = (focused_monitor.height as f32 / focused_monitor.scale).round() as i32;
923
-                                let has_window_in_direction = match direction {
924
-                                    Direction::Up => {
925
-                                        // Window is at top edge if its top is within 100px of monitor top
926
-                                        let near_top = win_y <= focused_monitor.y + 100;
927
-                                        !near_top
920
+                                // Check if any OTHER window on this monitor is further in that direction
921
+                                // Use window-based detection for all directions (consistent with IPC Move)
922
+                                let has_window_in_direction = clients.iter().any(|client| {
923
+                                    let mon = client.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32;
924
+                                    if mon != focused_monitor.id { return false; }
925
+
926
+                                    let cx = client.get("at").and_then(|a| a.get(0)).and_then(|x| x.as_i64()).unwrap_or(0) as i32;
927
+                                    let cy = client.get("at").and_then(|a| a.get(1)).and_then(|y| y.as_i64()).unwrap_or(0) as i32;
928
+                                    let cw = client.get("size").and_then(|s| s.get(0)).and_then(|w| w.as_i64()).unwrap_or(0) as i32;
929
+                                    let ch = client.get("size").and_then(|s| s.get(1)).and_then(|h| h.as_i64()).unwrap_or(0) as i32;
930
+
931
+                                    // Skip the active window itself
932
+                                    if cx == win_x && cy == win_y && cw == win_w && ch == win_h {
933
+                                        return false;
928934
                                     }
929
-                                    Direction::Down => {
930
-                                        // Window is at bottom edge if its bottom is within 100px of monitor bottom
931
-                                        let win_bottom = win_y + win_h;
932
-                                        let mon_bottom = focused_monitor.y + mon_logical_h;
933
-                                        let near_bottom = win_bottom >= mon_bottom - 100;
934
-                                        !near_bottom
935
-                                    }
936
-                                    Direction::Left | Direction::Right => {
937
-                                        // Window-based detection for horizontal directions
938
-                                        clients.iter().any(|client| {
939
-                                            let mon = client.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32;
940
-                                            if mon != focused_monitor.id { return false; }
941
-
942
-                                            let cx = client.get("at").and_then(|a| a.get(0)).and_then(|x| x.as_i64()).unwrap_or(0) as i32;
943
-                                            let cw = client.get("size").and_then(|s| s.get(0)).and_then(|w| w.as_i64()).unwrap_or(0) as i32;
944
-
945
-                                            match direction {
946
-                                                Direction::Left => cx + cw < win_x + 10,
947
-                                                Direction::Right => cx > win_x + win_w - 10,
948
-                                                _ => false,
949
-                                            }
950
-                                        })
935
+
936
+                                    match direction {
937
+                                        Direction::Left => cx + cw <= win_x + 10,
938
+                                        Direction::Right => cx >= win_x + win_w - 10,
939
+                                        Direction::Up => cy + ch <= win_y + 10,
940
+                                        Direction::Down => cy >= win_y + win_h - 10,
951941
                                     }
952
-                                };
942
+                                });
953943
 
954944
                                 info!("  RECOVERY edge_check: has_window_in_direction={} -> at_edge={}", has_window_in_direction, !has_window_in_direction);
955945
                                 !has_window_in_direction