From f9697985ff605cfa4e781278d8c9f96b5fd58b15 Mon Sep 17 00:00:00 2001 From: Corbin Crutchley Date: Sun, 5 Jul 2026 04:31:14 -0700 Subject: [PATCH] fix: handle scaling in shell properly --- .../src/compositor/output.rs | 7 ++++++ .../src/compositor/rendering.rs | 7 +++--- .../src/compositor/windows.rs | 24 +++++++++++++++---- .../src/compositor/windows/hit_testing.rs | 17 +++++++++---- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/crates/hearthspace-compositor/src/compositor/output.rs b/crates/hearthspace-compositor/src/compositor/output.rs index d7f091d..39ea2bc 100644 --- a/crates/hearthspace-compositor/src/compositor/output.rs +++ b/crates/hearthspace-compositor/src/compositor/output.rs @@ -266,6 +266,13 @@ impl App { .map(OutputRecord::logical_rect) } + pub(super) fn output_scale_for_name(&self, name: Option<&str>) -> i32 { + self.outputs + .output_for_name(name) + .map(|output| output.scale.max(1)) + .unwrap_or(1) + } + pub(in crate::compositor) fn set_output_layout(&mut self, layout: OutputLayout) -> bool { self.outputs.set_layout(layout) } diff --git a/crates/hearthspace-compositor/src/compositor/rendering.rs b/crates/hearthspace-compositor/src/compositor/rendering.rs index b24fb8a..3284fd6 100644 --- a/crates/hearthspace-compositor/src/compositor/rendering.rs +++ b/crates/hearthspace-compositor/src/compositor/rendering.rs @@ -259,9 +259,10 @@ impl App { pub(super) fn window_render_scale(&self, window_index: usize) -> f64 { match self.windows[window_index].kind { ManagedWindowKind::Normal => self.viewport_scale, - ManagedWindowKind::ShellBar - | ManagedWindowKind::Launcher - | ManagedWindowKind::ShellWatcher => 1.0, + ManagedWindowKind::ShellBar | ManagedWindowKind::Launcher => f64::from( + self.output_scale_for_name(self.windows[window_index].shell_output_name.as_deref()), + ), + ManagedWindowKind::ShellWatcher => 1.0, } } diff --git a/crates/hearthspace-compositor/src/compositor/windows.rs b/crates/hearthspace-compositor/src/compositor/windows.rs index 4cc93c6..ddfbde6 100644 --- a/crates/hearthspace-compositor/src/compositor/windows.rs +++ b/crates/hearthspace-compositor/src/compositor/windows.rs @@ -528,8 +528,10 @@ impl App { /// Logical screen-space origin of a launcher palette: pinned below its /// output's shell bar. fn launcher_logical_origin(&self, window_index: usize) -> Option> { + let scale = + self.output_scale_for_name(self.windows[window_index].shell_output_name.as_deref()); self.shell_bar_logical_origin(window_index) - .map(launcher_logical_origin_for_shell_bar) + .map(|origin| launcher_logical_origin_for_shell_bar(origin, scale)) } pub(super) fn surface_screen_origin(&self, window_index: usize) -> Point { @@ -547,8 +549,14 @@ impl App { } } -fn launcher_logical_origin_for_shell_bar(origin: Point) -> Point { - Point::from((origin.x, origin.y + CONTROL_BAR_HEIGHT)) +fn launcher_logical_origin_for_shell_bar( + origin: Point, + output_scale: i32, +) -> Point { + Point::from(( + origin.x, + origin.y + CONTROL_BAR_HEIGHT * output_scale.max(1), + )) } fn surface_tree_contains(root: &wl_surface::WlSurface, target: &wl_surface::WlSurface) -> bool { @@ -581,8 +589,16 @@ mod tests { let output = Rectangle::::new((1280, 120).into(), (1024, 768).into()); assert_eq!( - launcher_logical_origin_for_shell_bar(output.loc), + launcher_logical_origin_for_shell_bar(output.loc, 1), Point::from((1280, 168)) ); } + + #[test] + fn launcher_origin_sits_below_scaled_output_shell_bar() { + assert_eq!( + launcher_logical_origin_for_shell_bar(Point::from((0, 10)), 3), + Point::from((0, 154)) + ); + } } diff --git a/crates/hearthspace-compositor/src/compositor/windows/hit_testing.rs b/crates/hearthspace-compositor/src/compositor/windows/hit_testing.rs index 20fbf6f..ab51d03 100644 --- a/crates/hearthspace-compositor/src/compositor/windows/hit_testing.rs +++ b/crates/hearthspace-compositor/src/compositor/windows/hit_testing.rs @@ -23,16 +23,18 @@ impl App { match window.kind { ManagedWindowKind::ShellBar => { if let Some(origin) = self.shell_bar_logical_origin(window_index) + && let scale = self.window_render_scale(window_index) && let Some(target) = - self.hit_test_shell_surface(window_index, location, origin) + self.hit_test_shell_surface(window_index, location, origin, scale) { return Some(target); } } ManagedWindowKind::Launcher => { if let Some(origin) = self.launcher_logical_origin(window_index) + && let scale = self.window_render_scale(window_index) && let Some(target) = - self.hit_test_shell_surface(window_index, location, origin) + self.hit_test_shell_surface(window_index, location, origin, scale) { return Some(target); } @@ -133,15 +135,22 @@ impl App { window_index: usize, location: Point, origin: Point, + scale: f64, ) -> Option { let window = &self.windows[window_index]; + let scale = scale.max(1.0); + let origin_f64 = origin.to_f64(); + let unscaled_location = Point::from(( + origin_f64.x + (location.x - origin_f64.x) / scale, + origin_f64.y + (location.y - origin_f64.y) / scale, + )); let (surface, surface_location) = under_from_surface_tree( window.surface.wl_surface(), - location, + unscaled_location, origin, WindowSurfaceType::ALL, )?; - let relative_surface_location = location - surface_location.to_f64(); + let relative_surface_location = unscaled_location - surface_location.to_f64(); let pointer_focus_origin = location - relative_surface_location; Some(HitTarget::Client { window_index, -- 2.51.2