diff options
| author | srdusr <[email protected]> | 2024-07-11 14:17:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-07-11 14:17:00 +0200 |
| commit | 86b557a6c0baa4146b30712d8b7633f1b9b46d43 (patch) | |
| tree | 96ab749c728ac11c2851ea361c6fda63990e588f /crates/core/src/manager/hittest.rs | |
| parent | 68b645b43e19330474ff106ce5c88dab520d7417 (diff) | |
| download | srdwm-86b557a6c0baa4146b30712d8b7633f1b9b46d43.tar.gz srdwm-86b557a6c0baa4146b30712d8b7633f1b9b46d43.zip | |
Split crates/core/src/manager.rs (2048 lines) into manager/
Pure reorganization, no behavior change - verified by diffing the
function-name set before/after (identical 130 functions) plus a full
cargo test pass. WindowManager's struct/field definitions, Default,
new(), and the three trivial constructors (add_rule/register_layout/
available_layouts) stay in mod.rs; the rest of the single ~950-line
impl block is split into one file per the section comments the file
already had (monitors, windows, focus, winops, hittest, dragresize,
workspaces, layout). Three methods called across section boundaries
(monitor_for, windows_on_workspace, cycle_focus) went from private to
pub(super) - Rust's privacy model doesn't let sibling submodules see
each other's private items, only a defining module's own descendants.
The ~1000-line test module moves to manager/tests.rs unsplit: its
helpers (wm_with_monitor, two_monitors, monitor_with_dock) are shared
across tests for every section, so splitting further would mean
duplicating them or adding another shared-support file for little
benefit.
Diffstat (limited to 'crates/core/src/manager/hittest.rs')
| -rw-r--r-- | crates/core/src/manager/hittest.rs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/crates/core/src/manager/hittest.rs b/crates/core/src/manager/hittest.rs new file mode 100644 index 0000000..918acb5 --- /dev/null +++ b/crates/core/src/manager/hittest.rs @@ -0,0 +1,51 @@ +//! Pointer hit-testing against a window's titlebar/border/content. +//! Split out of the original single `manager.rs` - see `super` (`mod.rs`) for +//! `WindowManager`'s field definitions; everything here is plain `impl WindowManager` +//! methods, unchanged from before the split. + +use super::*; + +impl WindowManager { + // ---- Hit testing ------------------------------------------------------ + + /// Topmost window whose frame contains `(x, y)`, along with what part of + /// its titlebar/border was hit (button, drag area, resize edge). + pub fn hit_test(&self, x: i32, y: i32) -> Option<(WindowId, TitlebarHit)> { + for w in self.order.iter().rev().filter_map(|id| self.windows.get(id)) { + if w.minimized { + continue; + } + if let Some(hit) = ResizeEdge::hit_test(w.geometry, x, y, w.decorated, w.border_width, self.resize_margin) { + return Some((w.id, hit)); + } + } + None + } + + /// Topmost non-minimised window containing a point, ignoring + /// decorations. Used for modifier+drag, where the grab applies anywhere + /// in the window rather than only on the titlebar (`hit_test`). + pub fn window_at(&self, x: i32, y: i32) -> Option<WindowId> { + self.order + .iter() + .rev() + .filter_map(|id| self.windows.get(id)) + .find(|w| !w.minimized && w.geometry.contains_point(x, y)) + .map(|w| w.id) + } + + /// The corner of `id` nearest a point, for modifier+right-drag resize: + /// grabbing the closest corner is what makes the gesture feel like it + /// pulls the edge you aimed at (matching Hyprland's `resizewindow`). + pub fn nearest_corner(&self, id: WindowId, x: i32, y: i32) -> ResizeEdge { + let Some(w) = self.windows.get(&id) else { return ResizeEdge::BottomRight }; + let (cx, cy) = w.geometry.center(); + match (x < cx, y < cy) { + (true, true) => ResizeEdge::TopLeft, + (false, true) => ResizeEdge::TopRight, + (true, false) => ResizeEdge::BottomLeft, + (false, false) => ResizeEdge::BottomRight, + } + } + +} |