srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/state/mod.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-02-13 01:14:00 +0200
committersrdusr <[email protected]>2025-02-13 01:14:00 +0200
commited0b8ecf6c08d920ffd1b52c9dc6a24a436ce977 (patch)
tree0841a1a8d13a5f36a89f611dde27e6cb9db31c5b /crates/wayland/src/state/mod.rs
parentb1d69a552cdcc7370c4befd42ef2111c8b367c46 (diff)
downloadsrdwm-ed0b8ecf6c08d920ffd1b52c9dc6a24a436ce977.tar.gz
srdwm-ed0b8ecf6c08d920ffd1b52c9dc6a24a436ce977.zip
Implement the Wayland implicit pointer grab
Every pointer motion event re-ran the same popup/layer/content hit-test from scratch and delivered focus to whatever it found right now - there was no notion of "a button is held, keep delivering to the surface that received the press" at all, which is standard, expected Wayland compositor behavior (every real compositor does this; it's how dragging, text selection, and scrollbar-thumb dragging all stay coherent even when the pointer briefly leaves the widget's bounds mid-gesture). Without it, a real human's hand drifting even slightly outside the pressed surface mid-drag - trivially easy during a fast, non-perfectly- straight mouse motion - sent that client an unrequested `leave` event in the middle of its own gesture. GTK's drag recognizers (a GtkHeaderBar's move-the-window gesture, concretely) treat a mid-gesture leave as "this isn't coherent, abort," which reads as "dragging this window by its title bar does nothing at all" - live-reproduced this work on Nemo, and consistent with move_request never having fired once all session despite real attempts. pointer_button_grab captures the (surface, origin) resolved on a button press once the held-button count goes from 0 to 1, and every event under the grab - motion or button, this press's or a later one overlapping it - is delivered there instead of wherever a fresh hit-test lands, until every held button is back up.
Diffstat (limited to 'crates/wayland/src/state/mod.rs')
-rw-r--r--crates/wayland/src/state/mod.rs29
1 files changed, 29 insertions, 0 deletions
diff --git a/crates/wayland/src/state/mod.rs b/crates/wayland/src/state/mod.rs
index 5643ebc..084e407 100644
--- a/crates/wayland/src/state/mod.rs
+++ b/crates/wayland/src/state/mod.rs
@@ -475,6 +475,35 @@ pub(crate) struct CompState {
/// event this session's earlier per-motion diagnostic-logging
/// regression already proved is worth being careful around) needs one.
pub(crate) last_idle_notify: Option<Instant>,
+ /// The Wayland-standard "implicit grab": once a pointer button goes
+ /// down over a surface, every subsequent motion/button event - no
+ /// matter where the pointer physically ends up - has to keep being
+ /// delivered to that *same* surface until every held button is
+ /// released, not whatever a fresh hit-test happens to land on next.
+ /// Nothing implemented this before: every motion event re-ran the same
+ /// popup/layer/content hit-test from scratch and called `pointer.
+ /// motion()` with whatever it found *right now*, so the moment a real
+ /// human's hand drifted even slightly outside the pressed surface's own
+ /// bounds mid-gesture (trivially easy during a fast drag - a mouse
+ /// does not move in a perfectly straight line), that client received an
+ /// unrequested `leave` in the middle of its own gesture. GTK's drag
+ /// recognizers (a `GtkHeaderBar`'s move-the-window gesture, concretely)
+ /// treat a mid-gesture `leave` as "this isn't coherent, abort" - which
+ /// reads as "dragging this window's title bar does nothing at all,"
+ /// live-reproduced this session. `(surface, origin)` is captured once,
+ /// from the same resolution `refresh_pointer_focus` already computes,
+ /// the instant the held-button count goes from 0 to 1; `origin` is
+ /// reused for every event under the grab so surface-local coordinates
+ /// keep updating correctly even though the target surface no longer
+ /// does.
+ pub(crate) pointer_button_grab: Option<(WlSurface, Point<f64, Logical>)>,
+ /// How many pointer buttons are currently held - what actually decides
+ /// when [`Self::pointer_button_grab`] starts (0 -> 1) and ends (only
+ /// once every button, not just one of several held at once, comes back
+ /// up), matching the real Wayland implicit-grab rule instead of the
+ /// single-button assumption that would break as soon as a drag and a
+ /// second accidental button overlapped.
+ pub(crate) pointer_buttons_held: u32,
/// Windows currently mid-tween - see `WindowAnim` and `sync_geometry`'s
/// `anim_from` handling. Driven forward once per frame by
/// `tick_animations`, called from both backends' poll loops.