zoom: set cursor shapes with the enter serial (niri ignores a release's, so the hand stayed after a drag)
This commit is contained in:
1 parent
4bf53289ea
commit
1627056e00
1 file changed
+58
-15
+58
-15
@@ -74,6 +74,8 @@ pub struct Zoom {
|
|||||||
pointer: (f64, f64),
|
pointer: (f64, f64),
|
||||||
/// Last pointer position while the left button pans.
|
/// Last pointer position while the left button pans.
|
||||||
panning: Option<(f64, f64)>,
|
panning: Option<(f64, f64)>,
|
||||||
|
/// The latest pointer enter's serial: cursor shapes are set with it.
|
||||||
|
enter_serial: Option<u32>,
|
||||||
flashlight: bool,
|
flashlight: bool,
|
||||||
/// Flashlight radius in logical px.
|
/// Flashlight radius in logical px.
|
||||||
radius: f64,
|
radius: f64,
|
||||||
@@ -134,6 +136,7 @@ pub fn run(
|
|||||||
step: config.scroll_step,
|
step: config.scroll_step,
|
||||||
pointer: (0.0, 0.0),
|
pointer: (0.0, 0.0),
|
||||||
panning: None,
|
panning: None,
|
||||||
|
enter_serial: None,
|
||||||
flashlight: false,
|
flashlight: false,
|
||||||
radius: config.flashlight_radius,
|
radius: config.flashlight_radius,
|
||||||
ctrl: false,
|
ctrl: false,
|
||||||
@@ -236,32 +239,26 @@ impl Zoom {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let p = (event.position.0 * self.ratio, event.position.1 * self.ratio);
|
let p = (event.position.0 * self.ratio, event.position.1 * self.ratio);
|
||||||
|
if let (Some(device), Some((serial, shape))) = (
|
||||||
|
cursor,
|
||||||
|
cursor_change(self.enter_serial, &event.kind, self.panning.is_some()),
|
||||||
|
) {
|
||||||
|
device.set_shape(serial, shape);
|
||||||
|
}
|
||||||
match event.kind {
|
match event.kind {
|
||||||
PointerEventKind::Enter { serial } => {
|
PointerEventKind::Enter { serial } => {
|
||||||
if let Some(device) = cursor {
|
self.enter_serial = Some(serial);
|
||||||
device.set_shape(serial, self::cursor(self.panning.is_some()));
|
|
||||||
}
|
|
||||||
self.pointer = p;
|
self.pointer = p;
|
||||||
}
|
}
|
||||||
PointerEventKind::Press {
|
PointerEventKind::Press {
|
||||||
button: BTN_LEFT,
|
button: BTN_LEFT, ..
|
||||||
serial,
|
|
||||||
..
|
|
||||||
} => {
|
} => {
|
||||||
self.panning = Some(p);
|
self.panning = Some(p);
|
||||||
if let Some(device) = cursor {
|
|
||||||
device.set_shape(serial, self::cursor(true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PointerEventKind::Release {
|
PointerEventKind::Release {
|
||||||
button: BTN_LEFT,
|
button: BTN_LEFT, ..
|
||||||
serial,
|
|
||||||
..
|
|
||||||
} => {
|
} => {
|
||||||
self.panning = None;
|
self.panning = None;
|
||||||
if let Some(device) = cursor {
|
|
||||||
device.set_shape(serial, self::cursor(false));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PointerEventKind::Motion { .. } => {
|
PointerEventKind::Motion { .. } => {
|
||||||
self.pointer = p;
|
self.pointer = p;
|
||||||
@@ -320,6 +317,26 @@ impl Zoom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The cursor shape a pointer event calls for, with the serial to set it
|
||||||
|
/// with. The protocol wants the latest enter's serial: niri ignores a
|
||||||
|
/// release's, and the hand would stay after a drag.
|
||||||
|
fn cursor_change(
|
||||||
|
enter: Option<u32>,
|
||||||
|
kind: &PointerEventKind,
|
||||||
|
panning: bool,
|
||||||
|
) -> Option<(u32, Shape)> {
|
||||||
|
match kind {
|
||||||
|
PointerEventKind::Enter { serial } => Some((*serial, cursor(panning))),
|
||||||
|
PointerEventKind::Press {
|
||||||
|
button: BTN_LEFT, ..
|
||||||
|
} => Some((enter?, cursor(true))),
|
||||||
|
PointerEventKind::Release {
|
||||||
|
button: BTN_LEFT, ..
|
||||||
|
} => Some((enter?, cursor(false))),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The pointer over a zoom: a magnifier, so it reads as zoom mode, and a
|
/// The pointer over a zoom: a magnifier, so it reads as zoom mode, and a
|
||||||
/// grabbing hand while dragging the view.
|
/// grabbing hand while dragging the view.
|
||||||
fn cursor(panning: bool) -> Shape {
|
fn cursor(panning: bool) -> Shape {
|
||||||
@@ -334,6 +351,32 @@ fn cursor(panning: bool) -> Shape {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cursor_changes_use_the_enter_serial() {
|
||||||
|
let enter = PointerEventKind::Enter { serial: 5 };
|
||||||
|
let press = PointerEventKind::Press {
|
||||||
|
time: 0,
|
||||||
|
button: BTN_LEFT,
|
||||||
|
serial: 9,
|
||||||
|
};
|
||||||
|
let release = PointerEventKind::Release {
|
||||||
|
time: 0,
|
||||||
|
button: BTN_LEFT,
|
||||||
|
serial: 12,
|
||||||
|
};
|
||||||
|
assert_eq!(cursor_change(None, &enter, false), Some((5, Shape::ZoomIn)));
|
||||||
|
assert_eq!(
|
||||||
|
cursor_change(Some(5), &press, true),
|
||||||
|
Some((5, Shape::Grabbing))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cursor_change(Some(5), &release, false),
|
||||||
|
Some((5, Shape::ZoomIn)),
|
||||||
|
"a release's serial is ignored by the compositor"
|
||||||
|
);
|
||||||
|
assert_eq!(cursor_change(None, &press, true), None, "no enter yet");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn the_cursor_says_zoom_and_grabs_while_dragging() {
|
fn the_cursor_says_zoom_and_grabs_while_dragging() {
|
||||||
assert_eq!(cursor(false), Shape::ZoomIn);
|
assert_eq!(cursor(false), Shape::ZoomIn);
|
||||||
|
|||||||
Reference in new issue
Block a user