tenseleyflow/hyprkvm / 6aeb5e6

Browse files

fix: use monitor proximity for Up/Down edge detection

Bars and panels at the top/bottom of monitors were causing false
positives in window-based edge detection. Now for Up/Down directions,
we check if the active window is within 100px of the monitor edge
instead of looking for windows above/below.
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
6aeb5e620fb1477413772e2fda0d4707893c76a7
Parents
3529085
Tree
e9b2f9c

1 changed file

StatusFile+-
M hyprkvm-daemon/src/main.rs 69 34
hyprkvm-daemon/src/main.rsmodified
@@ -916,22 +916,38 @@ async fn run_daemon(config_path: &std::path::Path) -> anyhow::Result<()> {
916916
                                 };
917917
 
918918
                                 // Check if any window is further in the requested direction on same monitor
919
-                                let has_window_in_direction = clients.iter().any(|client| {
920
-                                    let mon = client.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32;
921
-                                    if mon != focused_monitor.id { return false; }
922
-
923
-                                    let cx = client.get("at").and_then(|a| a.get(0)).and_then(|x| x.as_i64()).unwrap_or(0) as i32;
924
-                                    let cy = client.get("at").and_then(|a| a.get(1)).and_then(|y| y.as_i64()).unwrap_or(0) as i32;
925
-                                    let cw = client.get("size").and_then(|s| s.get(0)).and_then(|w| w.as_i64()).unwrap_or(0) as i32;
926
-                                    let ch = client.get("size").and_then(|s| s.get(1)).and_then(|h| h.as_i64()).unwrap_or(0) as i32;
927
-
928
-                                    match direction {
929
-                                        Direction::Left => cx + cw < win_x + 10,
930
-                                        Direction::Right => cx > win_x + win_w - 10,
931
-                                        Direction::Up => cy + ch < win_y + 10,
932
-                                        Direction::Down => cy > win_y + win_h - 10,
919
+                                // For Up/Down: use monitor proximity instead of window detection (bars/panels cause false positives)
920
+                                let mon_logical_h = (focused_monitor.height as f32 / focused_monitor.scale).round() as i32;
921
+                                let has_window_in_direction = match direction {
922
+                                    Direction::Up => {
923
+                                        // Window is at top edge if its top is within 100px of monitor top
924
+                                        let near_top = win_y <= focused_monitor.y + 100;
925
+                                        !near_top
933926
                                     }
934
-                                });
927
+                                    Direction::Down => {
928
+                                        // Window is at bottom edge if its bottom is within 100px of monitor bottom
929
+                                        let win_bottom = win_y + win_h;
930
+                                        let mon_bottom = focused_monitor.y + mon_logical_h;
931
+                                        let near_bottom = win_bottom >= mon_bottom - 100;
932
+                                        !near_bottom
933
+                                    }
934
+                                    Direction::Left | Direction::Right => {
935
+                                        // Window-based detection for horizontal directions
936
+                                        clients.iter().any(|client| {
937
+                                            let mon = client.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32;
938
+                                            if mon != focused_monitor.id { return false; }
939
+
940
+                                            let cx = client.get("at").and_then(|a| a.get(0)).and_then(|x| x.as_i64()).unwrap_or(0) as i32;
941
+                                            let cw = client.get("size").and_then(|s| s.get(0)).and_then(|w| w.as_i64()).unwrap_or(0) as i32;
942
+
943
+                                            match direction {
944
+                                                Direction::Left => cx + cw < win_x + 10,
945
+                                                Direction::Right => cx > win_x + win_w - 10,
946
+                                                _ => false,
947
+                                            }
948
+                                        })
949
+                                    }
950
+                                };
935951
 
936952
                                 info!("  RECOVERY edge_check: has_window_in_direction={} -> at_edge={}", has_window_in_direction, !has_window_in_direction);
937953
                                 !has_window_in_direction
@@ -1742,27 +1758,46 @@ async fn run_daemon(config_path: &std::path::Path) -> anyhow::Result<()> {
17421758
                                 }
17431759
                             };
17441760
 
1745
-                            info!("  edge_check: active window at ({},{}) size {}x{}, {} clients on monitor",
1746
-                                  win_x, win_y, win_w, win_h,
1747
-                                  clients.iter().filter(|c| c.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32 == focused_monitor.id).count());
1748
-
1749
-                            // Check if any window is further in the requested direction on same monitor
1750
-                            let has_window_in_direction = clients.iter().any(|client| {
1751
-                                let mon = client.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32;
1752
-                                if mon != focused_monitor.id { return false; }
1761
+                            // Calculate monitor bounds in logical coordinates
1762
+                            let mon_logical_h = (focused_monitor.height as f32 / focused_monitor.scale).round() as i32;
17531763
 
1754
-                                let cx = client.get("at").and_then(|a| a.get(0)).and_then(|x| x.as_i64()).unwrap_or(0) as i32;
1755
-                                let cy = client.get("at").and_then(|a| a.get(1)).and_then(|y| y.as_i64()).unwrap_or(0) as i32;
1756
-                                let cw = client.get("size").and_then(|s| s.get(0)).and_then(|w| w.as_i64()).unwrap_or(0) as i32;
1757
-                                let ch = client.get("size").and_then(|s| s.get(1)).and_then(|h| h.as_i64()).unwrap_or(0) as i32;
1758
-
1759
-                                match direction {
1760
-                                    Direction::Left => cx + cw < win_x + 10, // Window is to the left
1761
-                                    Direction::Right => cx > win_x + win_w - 10, // Window is to the right
1762
-                                    Direction::Up => cy + ch < win_y + 10,
1763
-                                    Direction::Down => cy > win_y + win_h - 10,
1764
+                            info!("  edge_check: active window at ({},{}) size {}x{}, {} clients on monitor, mon_y={}, mon_h={}",
1765
+                                  win_x, win_y, win_w, win_h,
1766
+                                  clients.iter().filter(|c| c.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32 == focused_monitor.id).count(),
1767
+                                  focused_monitor.y, mon_logical_h);
1768
+
1769
+                            // For Up/Down: check if window is near monitor edge (accounts for bars/panels)
1770
+                            // For Left/Right: check if any window is further in that direction
1771
+                            let has_window_in_direction = match direction {
1772
+                                Direction::Up => {
1773
+                                    // Window is at top edge if its top is within 100px of monitor top (allows for bars)
1774
+                                    let near_top = win_y <= focused_monitor.y + 100;
1775
+                                    !near_top // has_window_in_direction = !near_top, so at_edge = near_top
17641776
                                 }
1765
-                            });
1777
+                                Direction::Down => {
1778
+                                    // Window is at bottom edge if its bottom is within 100px of monitor bottom
1779
+                                    let win_bottom = win_y + win_h;
1780
+                                    let mon_bottom = focused_monitor.y + mon_logical_h;
1781
+                                    let near_bottom = win_bottom >= mon_bottom - 100;
1782
+                                    !near_bottom // has_window_in_direction = !near_bottom, so at_edge = near_bottom
1783
+                                }
1784
+                                Direction::Left | Direction::Right => {
1785
+                                    // For Left/Right, use window-based detection
1786
+                                    clients.iter().any(|client| {
1787
+                                        let mon = client.get("monitor").and_then(|m| m.as_i64()).unwrap_or(-1) as i32;
1788
+                                        if mon != focused_monitor.id { return false; }
1789
+
1790
+                                        let cx = client.get("at").and_then(|a| a.get(0)).and_then(|x| x.as_i64()).unwrap_or(0) as i32;
1791
+                                        let cw = client.get("size").and_then(|s| s.get(0)).and_then(|w| w.as_i64()).unwrap_or(0) as i32;
1792
+
1793
+                                        match direction {
1794
+                                            Direction::Left => cx + cw < win_x + 10,
1795
+                                            Direction::Right => cx > win_x + win_w - 10,
1796
+                                            _ => false,
1797
+                                        }
1798
+                                    })
1799
+                                }
1800
+                            };
17661801
 
17671802
                             info!("  edge_check: has_window_in_direction={} -> at_edge={}", has_window_in_direction, !has_window_in_direction);
17681803
                             !has_window_in_direction