srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/elements.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-08-18 23:44:00 +0200
committersrdusr <[email protected]>2025-08-18 23:44:00 +0200
commitd2af06d00e1b91bf9953e8c86eb30ab3ad9ee829 (patch)
treebf6f73d4c89263f0be842429c2a597ff8e34fa0c /crates/wayland/src/elements.rs
parentb8376bd631a72f7484c24663699a7d4c813f600e (diff)
downloadsrdwm-d2af06d00e1b91bf9953e8c86eb30ab3ad9ee829.tar.gz
srdwm-d2af06d00e1b91bf9953e8c86eb30ab3ad9ee829.zip
Fix layer-shell surfaces unclickable/unpainted on a fractionally-scaled output
Reported live, in stages: general input sluggishness, then specifically dock/bar buttons not responding on the secondary monitor. Root-caused jointly with a peer session (dotfiles-16), who independently instrumented AGS itself (both bar and dock report correct visible/realized/revealed state - the client is asking for the right thing) and srdwm's own layer_hit_test log (the dock received zero hits across ~40 minutes while the same output's wallpaper and bar took hundreds). Confirmed against smithay 0.7.0's own source (desktop/wayland/layer.rs:: arrange): LayerMap::arrange() divides the output's physical mode by its own scale before arranging layers, so LayerMap::layer_geometry() is logical, not physical. Two call sites used it as physical, this compositor's convention everywhere else: - input/layers.rs::layer_surface_under_layers compared the physical pointer position directly against logical layer geometry. On a sub-1.0 scale output, logical space is larger than physical, so a bottom-anchored dock's rect sat entirely past the pointer's reachable range - permanently unclickable. A top-anchored bar only lost its own right-hand end, which is what made this look like "the dock is broken" rather than a scale bug affecting every layer surface there. - elements.rs::output_layer_elements pushed the same logical position straight into the physical framebuffer - for the dock, past the bottom edge entirely, painting nothing. Both fixed the same way udev/platform.rs::monitors() and udev/outputs.rs already fix the identical unit mismatch for usable-area computation (existing precedent, not a new technique): multiply by output. current_scale().fractional_scale(), rounding to the nearest physical pixel, before use. Also removed a temporary per-pointer-motion-event diagnostic log in layer_hit_test, still live from an earlier debugging session and explicitly marked for removal but never removed - a real, measurable cost on the hot input path, likely the direct cause of the separately reported general slowness. Full workspace test suite and clippy clean.
Diffstat (limited to 'crates/wayland/src/elements.rs')
-rw-r--r--crates/wayland/src/elements.rs19
1 files changed, 18 insertions, 1 deletions
diff --git a/crates/wayland/src/elements.rs b/crates/wayland/src/elements.rs
index de50ccf..b5be5a8 100644
--- a/crates/wayland/src/elements.rs
+++ b/crates/wayland/src/elements.rs
@@ -256,6 +256,22 @@ where
R: Renderer + ImportAll + ImportMem,
R::TextureId: Clone + Send + 'static,
{
+ // `LayerMap::layer_geometry` is logical (confirmed against smithay
+ // 0.7.0's own source, `desktop/wayland/layer.rs::arrange`: it divides
+ // the output's physical mode by its own scale before arranging), while
+ // every position this function's own caller pushes an element at is
+ // physical - this compositor's convention throughout. Left
+ // unconverted, a layer surface on any output with a non-1.0 scale
+ // renders at the wrong physical position; for a bottom/right-anchored
+ // one on a *sub*-1.0 scale (this output shrinks logical space *larger*
+ // than physical, so a position derived from it overshoots), that was
+ // enough to push it fully past the real framebuffer edge - confirmed
+ // live (independently measured by a peer session) as a bottom-anchored
+ // dock never painted at all on a 0.843-scale output, while a
+ // top-anchored bar on the same output still rendered (it starts at
+ // logical/physical `0` either way) but with its own far edge
+ // increasingly wrong the further right it drew.
+ let scale = output.current_scale().fractional_scale();
let map = layer_map_for_output(output);
let mut elements = Vec::new();
for layer in map.layers().rev() {
@@ -263,7 +279,8 @@ where
continue;
}
let Some(geo) = map.layer_geometry(layer) else { continue };
- elements.extend(surface_content_elements(renderer, layer.wl_surface(), (geo.loc.x, geo.loc.y), 1.0));
+ let pos = ((geo.loc.x as f64 * scale).round() as i32, (geo.loc.y as f64 * scale).round() as i32);
+ elements.extend(surface_content_elements(renderer, layer.wl_surface(), pos, 1.0));
}
elements
}