srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/input.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-02-06 09:28:00 +0200
committersrdusr <[email protected]>2025-02-06 09:28:00 +0200
commitef2eff8f654884406c8989baf1ad345a2da43a58 (patch)
tree6638e1b0d5fb573ecc8b8bc5e51ebeb3dfddee42 /crates/wayland/src/input.rs
parentd25f28c5a779438bef01106ba2b28874e24d5029 (diff)
downloadsrdwm-ef2eff8f654884406c8989baf1ad345a2da43a58.tar.gz
srdwm-ef2eff8f654884406c8989baf1ad345a2da43a58.zip
Fix layer surfaces spuriously hiding/re-showing on their own realization
sync_layer_visibility could not tell a real hide (null-buffer commit on an already-visible surface) apart from a layer-shell client's ordinary realization sequence (commit with no buffer -> configure -> ack-commit with no buffer again -> attach real content): both look like "committed, no buffer" from has_buffer alone. Every layer surface's first realization was spuriously unmapped and immediately remapped, doubling LayerMap arrange() passes on every single popup open. Live-reproduced via an AGS peer session: a full-monitor click-outside-to- close popup surface came back from a hit-test with geometry wider than the real output after several open/close cycles on a wl_surface GTK had reused across role destroy/recreate, and sat in the Top layer above every real window with no input region set - silently swallowing clicks meant for windows, dropdowns, and CSD title bars alike. layer_surfaces_shown_once now gates the hide path on a surface having actually shown a buffer at least once, and is cleared in layer_destroyed so a reused wl_surface's next role starts clean rather than inheriting the previous role's flag.
Diffstat (limited to 'crates/wayland/src/input.rs')
-rw-r--r--crates/wayland/src/input.rs23
1 files changed, 13 insertions, 10 deletions
diff --git a/crates/wayland/src/input.rs b/crates/wayland/src/input.rs
index be5b15f..2463d02 100644
--- a/crates/wayland/src/input.rs
+++ b/crates/wayland/src/input.rs
@@ -17,6 +17,7 @@ use smithay::input::keyboard::FilterResult;
use smithay::input::pointer::{ButtonEvent, MotionEvent};
use smithay::output::Output;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
+use smithay::reexports::wayland_server::Resource as _;
use smithay::utils::{Logical, Point, SERIAL_COUNTER};
use smithay::wayland::compositor::with_states;
use smithay::wayland::shell::wlr_layer::{Anchor, ExclusiveZone, KeyboardInteractivity, Layer, LayerSurfaceCachedState};
@@ -89,25 +90,27 @@ pub(crate) fn layer_surface_under_layers(state: &CompState, pos: Point<f64, Logi
if !geo.to_f64().contains(local) {
continue;
}
- // Temporary: tracing a live report that a bottom-anchored
- // layer surface (a dock) receives no pointer input at all,
- // despite its own committed input region - as measured from
- // the AGS side - covering the point being tested. Logs
- // exactly what this compositor's own view of that surface is
- // at the moment of the hit-test, so the two sides' numbers can
- // be compared directly instead of guessed at. Remove once
- // that's settled.
+ // Temporary: verifying the `layer_surfaces_shown_once` fix
+ // (state/layers.rs) actually stops a reused `wl_surface`'s
+ // stale layer-shell entry from outliving its role destroy --
+ // live-reproduced this session as a full-monitor click-catcher
+ // popup whose hit-tested geometry came back wider than the
+ // real output after several open/close cycles. Remove once a
+ // restart confirms the geometry stays sane across repeated
+ // popup toggles.
let local_in_surface = local - geo.loc.to_f64();
// `None` here means "no region ever committed" - per-protocol
// that means the *whole* surface is input-sensitive, not that
- // nothing is, so it is its own distinct, meaningful answer.
+ // nothing is, so it is its own distinct, meaningful answer from
+ // `Some([])` (a region was committed and it is empty).
let region_dump = with_states(layer.wl_surface(), |states| {
states.cached_state.get::<smithay::wayland::compositor::SurfaceAttributes>().current().input_region.as_ref().map(|r| r.rects.clone())
});
log::info!(
- "layer_hit_test: layer={:?} namespace={:?} geo={:?} local_in_surface={:?} input_region={:?}",
+ "layer_hit_test: layer={:?} namespace={:?} surface={:?} geo={:?} local_in_surface={:?} input_region={:?}",
layer_kind,
layer.namespace(),
+ layer.wl_surface().id(),
geo,
local_in_surface,
region_dump