diff options
| author | srdusr <[email protected]> | 2024-08-22 16:06:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-08-22 16:06:00 +0200 |
| commit | 78da614d67c09e197dffc1cebb1c5ce2357c7128 (patch) | |
| tree | a39694108f7d1192276a0ea8956e458dc2595d79 /crates/core | |
| parent | 8d94ca5d77d6e2a189d299b8b88a461ba2e621c6 (diff) | |
| download | srdwm-78da614d67c09e197dffc1cebb1c5ce2357c7128.tar.gz srdwm-78da614d67c09e197dffc1cebb1c5ce2357c7128.zip | |
Add per-window resize-margin override (Hyprland's extend_border_grab_area)
MISSING.md had listed this as needing to touch srdwm_core::window::
hit_test's signature at every call site, including the honest-stub
Windows/macOS backends - overstated on closer inspection: that shared
function already takes a plain resize_margin: i32 parameter, agnostic
to where the value comes from. The only real change needed was reading
Window.resize_margin.unwrap_or(wm-wide default) instead of always the
WM-wide value, at the single call site inside WindowManager::hit_test
in core - no backend touched at all.
Window.resize_margin: Option<i32>, WindowRuleActions.resize_margin to
match, applied in add_window/reapply_rules_if_pending the same way
opacity already is. Settable via a rule action or
srd.window.set_resize_margin(n) on the focused window.
Diffstat (limited to 'crates/core')
| -rw-r--r-- | crates/core/src/manager/hittest.rs | 3 | ||||
| -rw-r--r-- | crates/core/src/manager/tests.rs | 17 | ||||
| -rw-r--r-- | crates/core/src/manager/windows.rs | 6 | ||||
| -rw-r--r-- | crates/core/src/rules.rs | 3 | ||||
| -rw-r--r-- | crates/core/src/window.rs | 6 |
5 files changed, 34 insertions, 1 deletions
diff --git a/crates/core/src/manager/hittest.rs b/crates/core/src/manager/hittest.rs index 2d52b57..06ac659 100644 --- a/crates/core/src/manager/hittest.rs +++ b/crates/core/src/manager/hittest.rs @@ -24,7 +24,8 @@ impl WindowManager { if w.minimized || w.workspace != self.current_workspace { continue; } - if let Some(hit) = ResizeEdge::hit_test(w.geometry, x, y, w.decorated, w.border_width, self.resize_margin) { + let margin = w.resize_margin.unwrap_or(self.resize_margin); + if let Some(hit) = ResizeEdge::hit_test(w.geometry, x, y, w.decorated, w.border_width, margin) { return Some((w.id, hit)); } } diff --git a/crates/core/src/manager/tests.rs b/crates/core/src/manager/tests.rs index 24e8932..e1518f1 100644 --- a/crates/core/src/manager/tests.rs +++ b/crates/core/src/manager/tests.rs @@ -246,6 +246,23 @@ } #[test] + fn per_window_resize_margin_overrides_the_wm_wide_default() { + // Hyprland's per-window `extend_border_grab_area` equivalent. + let mut wm = wm_with_monitor(); + wm.set_layout(wm.current_workspace(), "tiling"); // keeps add_window from overriding geometry via SmartPlacement + let id = wm.alloc_window_id(); + let mut w = Window::new(id, "a"); + w.geometry = Rect::new(100, 100, 400, 300); + w.resize_margin = Some(30); + wm.add_window(w); + + // 15px in from the left edge: well past the WM-wide default (6px), + // but still inside this window's own wider 30px override. + let hit = wm.hit_test(115, 250); + assert_eq!(hit.map(|(_, h)| h), Some(TitlebarHit::Resize(ResizeEdge::Left))); + } + + #[test] fn moving_window_to_another_workspace_removes_it_from_current() { let mut wm = wm_with_monitor(); let a = wm.alloc_window_id(); diff --git a/crates/core/src/manager/windows.rs b/crates/core/src/manager/windows.rs index 6171c15..4b4c0c8 100644 --- a/crates/core/src/manager/windows.rs +++ b/crates/core/src/manager/windows.rs @@ -52,6 +52,9 @@ impl WindowManager { if let Some(opacity) = a.opacity { window.opacity = opacity.clamp(0.0, 1.0); } + if let Some(margin) = a.resize_margin { + window.resize_margin = Some(margin); + } } if let Some(monitor) = self.primary_monitor() { @@ -127,6 +130,9 @@ impl WindowManager { if let Some(opacity) = actions.opacity { window.opacity = opacity.clamp(0.0, 1.0); } + if let Some(margin) = actions.resize_margin { + window.resize_margin = Some(margin); + } if let Some(geometry) = actions.geometry { window.geometry = geometry; } diff --git a/crates/core/src/rules.rs b/crates/core/src/rules.rs index e0e87cb..7d9ee31 100644 --- a/crates/core/src/rules.rs +++ b/crates/core/src/rules.rs @@ -90,6 +90,9 @@ pub struct WindowRuleActions { pub pinned: Option<bool>, /// Content opacity, `0.0`..=`1.0` (Hyprland's `windowrule = opacity`). pub opacity: Option<f32>, + /// Per-window resize-grab-margin override, in logical pixels + /// (Hyprland's per-window `extend_border_grab_area`). + pub resize_margin: Option<i32>, } #[derive(Debug, Clone, Default)] diff --git a/crates/core/src/window.rs b/crates/core/src/window.rs index b79151d..850b936 100644 --- a/crates/core/src/window.rs +++ b/crates/core/src/window.rs @@ -97,6 +97,11 @@ pub struct Window { /// effect still keeps its frame legible. Set via `srd.window. /// set_opacity()` or a rule's `opacity` action. pub opacity: f32, + /// Per-window override of `WindowManager::resize_margin`, `None` to + /// just inherit it. Hyprland's `extend_border_grab_area` is per-window + /// (a `windowrule`); this is the equivalent, set via a rule's + /// `resize_margin` action or `srd.window.set_resize_margin()`. + pub resize_margin: Option<i32>, pub workspace: usize, pub monitor: u32, /// Whether `WindowManager`'s class/title-matched rules have already @@ -143,6 +148,7 @@ impl Window { border_color: (136, 192, 208), // Nord accent, matches legacy theme default border_width: 2, opacity: 1.0, + resize_margin: None, workspace: 0, monitor: 0, rules_applied: false, |