diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-15 09:07:44 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-30 20:12:37 +0300 |
| commit | c008e1c5bcab360425780997f70818fa4252c938 (patch) | |
| tree | fe8b7138ddc3b7bc9a3616cbf42cf8d8defb807e /src/utils/mod.rs | |
| parent | 1aa60f0da3e7f1a0bf50d6b88d59db6ba094d4f0 (diff) | |
| download | niri-c008e1c5bcab360425780997f70818fa4252c938.tar.gz niri-c008e1c5bcab360425780997f70818fa4252c938.tar.bz2 niri-c008e1c5bcab360425780997f70818fa4252c938.zip | |
floating: Implement smarter clamping for window location
A small part of the window always remains on-screen regardless of the working
area changes.
Interactive move lets the user position the window anywhere; automatic actions
like toggle-window-floating and dialog opening try to put the window fully
on-screen.
The size-fraction canonical floating window position remains unclamped, and
clamping happens when recomputing the logical position.
Diffstat (limited to 'src/utils/mod.rs')
| -rw-r--r-- | src/utils/mod.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b4ba1002..e7dff735 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -272,6 +272,18 @@ pub fn ensure_min_max_size(mut x: i32, min_size: i32, max_size: i32) -> i32 { x } +pub fn clamp_preferring_top_left_in_area( + area: Rectangle<f64, Logical>, + rect: &mut Rectangle<f64, Logical>, +) { + rect.loc.x = f64::min(rect.loc.x, area.loc.x + area.size.w - rect.size.w); + rect.loc.y = f64::min(rect.loc.y, area.loc.y + area.size.h - rect.size.h); + + // Clamp by top and left last so it takes precedence. + rect.loc.x = f64::max(rect.loc.x, area.loc.x); + rect.loc.y = f64::max(rect.loc.y, area.loc.y); +} + #[cfg(feature = "dbus")] pub fn show_screenshot_notification(image_path: Option<PathBuf>) { let mut notification = notify_rust::Notification::new(); @@ -309,3 +321,40 @@ pub fn cause_panic() { let b = Duration::from_secs(2); let _ = a - b; } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_clamp_preferring_top_left() { + fn check( + (ax, ay, aw, ah): (i32, i32, i32, i32), + (rx, ry, rw, rh): (i32, i32, i32, i32), + (ex, ey): (i32, i32), + ) { + let area = Rectangle::from_loc_and_size((ax, ay), (aw, ah)).to_f64(); + let mut rect = Rectangle::from_loc_and_size((rx, ry), (rw, rh)).to_f64(); + clamp_preferring_top_left_in_area(area, &mut rect); + assert_eq!(rect.loc, Point::from((ex, ey)).to_f64()); + } + + check((0, 0, 10, 20), (2, 3, 4, 5), (2, 3)); + check((0, 0, 10, 20), (-2, 3, 4, 5), (0, 3)); + check((0, 0, 10, 20), (2, -3, 4, 5), (2, 0)); + check((0, 0, 10, 20), (-2, -3, 4, 5), (0, 0)); + + check((1, 1, 10, 20), (2, 3, 4, 5), (2, 3)); + check((1, 1, 10, 20), (-2, 3, 4, 5), (1, 3)); + check((1, 1, 10, 20), (2, -3, 4, 5), (2, 1)); + check((1, 1, 10, 20), (-2, -3, 4, 5), (1, 1)); + + check((0, 0, 10, 20), (20, 3, 4, 5), (6, 3)); + check((0, 0, 10, 20), (2, 30, 4, 5), (2, 15)); + check((0, 0, 10, 20), (20, 30, 4, 5), (6, 15)); + + check((0, 0, 10, 20), (20, 30, 40, 5), (0, 15)); + check((0, 0, 10, 20), (20, 30, 4, 50), (6, 0)); + check((0, 0, 10, 20), (20, 30, 40, 50), (0, 0)); + } +} |
