fix(input): pointer lock + the missing per-iteration motion flush
Two capture bugs compounding into 'sluggish and not captured': 1. flush_motion was never called from the run loop — the GTK client's frame-clock tick flushed pending motion every frame, and the port lost it. Pure mouse movement only reached the host when a click/key/ scroll happened to flush it; the host cursor simply didn't follow. Now one coalesced MouseMove per loop iteration. 2. Capture forwarded ABSOLUTE letterboxed coordinates with no pointer confinement (GTK parity, the plan's deferred 'stage-2' item): the visible local cursor outran the host cursor by the full e2e and escaped the window. Capture is now real pointer lock — SDL relative mouse mode (hidden, confined, raw deltas) with relative MouseMove on the wire, so the host cursor is the only cursor. Also: focus-gain re-engages after an auto-release (Alt-Tab undoes itself; the startup focus race can no longer strand the session uncaptured) while a chord release stays released until the user opts back in. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2246,8 +2246,20 @@ fn pick_compositor(
|
||||
available: &[crate::vdisplay::Compositor],
|
||||
detected: Option<crate::vdisplay::Compositor>,
|
||||
) -> Option<crate::vdisplay::Compositor> {
|
||||
match crate::vdisplay::Compositor::from_pref(pref) {
|
||||
use crate::vdisplay::Compositor;
|
||||
match Compositor::from_pref(pref) {
|
||||
Some(want) if available.contains(&want) => Some(want),
|
||||
// `CompositorPref::Wlroots` names the wlroots *family* (D2): sway/river ([`Wlroots`]) and
|
||||
// Hyprland are distinct backends but mutually-exclusive live sessions, so honor the request
|
||||
// with whichever family member is actually available — the detected one if it's a family
|
||||
// member, else the first available of the two.
|
||||
Some(Compositor::Wlroots) => match detected {
|
||||
Some(d @ (Compositor::Wlroots | Compositor::Hyprland)) => Some(d),
|
||||
_ => [Compositor::Wlroots, Compositor::Hyprland]
|
||||
.into_iter()
|
||||
.find(|c| available.contains(c))
|
||||
.or(detected),
|
||||
},
|
||||
_ => detected,
|
||||
}
|
||||
}
|
||||
@@ -4111,6 +4123,22 @@ mod tests {
|
||||
pick_compositor(CompositorPref::Gamescope, &[Gamescope], None),
|
||||
Some(Gamescope)
|
||||
);
|
||||
// Wlroots family (D2): the shared `Wlroots` pref resolves to whichever of sway/river
|
||||
// (Wlroots) and Hyprland is the live session.
|
||||
assert_eq!(
|
||||
pick_compositor(CompositorPref::Wlroots, &[Hyprland], Some(Hyprland)),
|
||||
Some(Hyprland)
|
||||
);
|
||||
// …and to Wlroots-proper on a sway/river host.
|
||||
assert_eq!(
|
||||
pick_compositor(CompositorPref::Wlroots, &[Wlroots], Some(Wlroots)),
|
||||
Some(Wlroots)
|
||||
);
|
||||
// Family fallback even if detection came back empty but a member is available.
|
||||
assert_eq!(
|
||||
pick_compositor(CompositorPref::Wlroots, &[Hyprland], None),
|
||||
Some(Hyprland)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user