srdusr
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crates/config/src/engine/general.rs1
-rw-r--r--crates/config/src/engine/register.rs1
-rw-r--r--crates/config/src/engine/window.rs14
-rw-r--r--crates/core/src/manager/hittest.rs3
-rw-r--r--crates/core/src/manager/tests.rs17
-rw-r--r--crates/core/src/manager/windows.rs6
-rw-r--r--crates/core/src/rules.rs3
-rw-r--r--crates/core/src/window.rs6
-rw-r--r--docs/DEFAULTS.md4
9 files changed, 54 insertions, 1 deletions
diff --git a/crates/config/src/engine/general.rs b/crates/config/src/engine/general.rs
index d1a762a..96ea4d3 100644
--- a/crates/config/src/engine/general.rs
+++ b/crates/config/src/engine/general.rs
@@ -184,6 +184,7 @@ impl Engine {
border_width: actions.get("border_width")?,
pinned: actions.get("pinned")?,
opacity: actions.get("opacity")?,
+ resize_margin: actions.get("resize_margin")?,
},
};
state.borrow().wm.borrow_mut().add_rule(rule);
diff --git a/crates/config/src/engine/register.rs b/crates/config/src/engine/register.rs
index d68d253..abe919b 100644
--- a/crates/config/src/engine/register.rs
+++ b/crates/config/src/engine/register.rs
@@ -45,6 +45,7 @@ impl Engine {
window.set("set_border_color", self.fn_window_set_border_color()?)?;
window.set("set_border_width", self.fn_window_set_border_width()?)?;
window.set("set_opacity", self.fn_window_set_opacity()?)?;
+ window.set("set_resize_margin", self.fn_window_set_resize_margin()?)?;
window.set("set_floating", self.fn_window_set_floating()?)?;
window.set("toggle_floating", self.fn_window_action(WindowAction::ToggleFloating)?)?;
window.set("is_floating", self.fn_window_is_floating()?)?;
diff --git a/crates/config/src/engine/window.rs b/crates/config/src/engine/window.rs
index 6193f81..a7e6bf3 100644
--- a/crates/config/src/engine/window.rs
+++ b/crates/config/src/engine/window.rs
@@ -153,6 +153,20 @@ impl Engine {
})?)
}
+ pub(super) fn fn_window_set_resize_margin(&self) -> Result<mlua::Function<'_>> {
+ let state = self.state.clone();
+ Ok(self.lua.create_function(move |_, margin: i32| {
+ let wm = state.borrow().wm.clone();
+ let mut wm = wm.borrow_mut();
+ if let Some(id) = wm.focused_id() {
+ if let Some(w) = wm.window_mut(id) {
+ w.resize_margin = Some(margin);
+ }
+ }
+ Ok(())
+ })?)
+ }
+
pub(super) fn fn_window_set_floating(&self) -> Result<mlua::Function<'_>> {
let state = self.state.clone();
Ok(self.lua.create_function(move |_, floating: bool| {
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,
diff --git a/docs/DEFAULTS.md b/docs/DEFAULTS.md
index b5bf947..972e330 100644
--- a/docs/DEFAULTS.md
+++ b/docs/DEFAULTS.md
@@ -220,6 +220,10 @@ srd.rule(matcher, actions)
- `pinned` (bool) - always-on-top
- `opacity` (number, `0.0`..=`1.0`) - content opacity; srdwm's own
titlebar/border/shadow always stay fully opaque regardless
+- `resize_margin` (number, logical pixels) - per-window override of
+ `general.resize_margin` (Hyprland's per-window `extend_border_grab_area`).
+ Also settable live via `srd.window.set_resize_margin(n)` on the focused
+ window.
```lua
srd.rule({ class = "pavucontrol" }, { floating = true })