input: Clip pointer movement smarter

This commit is contained in:
Ivan Molodetskikh
2023-09-05 18:02:05 +04:00
parent 72d6b387e7
commit 934183ef00
+55 -18
View File
@@ -294,36 +294,73 @@ impl State {
} }
} }
InputEvent::PointerMotion { event, .. } => { InputEvent::PointerMotion { event, .. } => {
// We need an output to be able to move the pointer.
if self.niri.global_space.outputs().next().is_none() {
return;
}
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
let pointer = self.niri.seat.get_pointer().unwrap(); let pointer = self.niri.seat.get_pointer().unwrap();
let mut pos = pointer.current_location();
pos += event.delta(); let pos = pointer.current_location();
let mut min_x = i32::MAX; // We have an output, so we can compute the new location and focus.
let mut min_y = i32::MAX; let mut new_pos = pos + event.delta();
let mut max_x = 0;
let mut max_y = 0; if self
for output in self.niri.global_space.outputs() { .niri
// FIXME: smarter clamping. .global_space
let geom = self.niri.global_space.output_geometry(output).unwrap(); .output_under(new_pos)
min_x = min_x.min(geom.loc.x); .next()
min_y = min_y.min(geom.loc.y); .is_none()
max_x = max_x.max(geom.loc.x + geom.size.w); {
max_y = max_y.max(geom.loc.y + geom.size.h); // We ended up outside the outputs and need to clip the movement.
if let Some(output) = self.niri.global_space.output_under(pos).next() {
// The pointer was previously on some output. Clip the movement against its
// boundaries.
let geom = self.niri.global_space.output_geometry(output).unwrap();
new_pos.x = new_pos
.x
.clamp(geom.loc.x as f64, (geom.loc.x + geom.size.w - 1) as f64);
new_pos.y = new_pos
.y
.clamp(geom.loc.y as f64, (geom.loc.y + geom.size.h - 1) as f64);
} else {
// The pointer was not on any output in the first place. Find one for it.
// Start by clamping the X coordinate.
let mut min_x = i32::MAX;
let mut max_x = 0;
for output in self.niri.global_space.outputs() {
let geom = self.niri.global_space.output_geometry(output).unwrap();
min_x = min_x.min(geom.loc.x);
max_x = max_x.max(geom.loc.x + geom.size.w);
}
new_pos.x = new_pos.x.clamp(min_x as f64, (max_x - 1) as f64);
// Now clamp the Y coordinate. Assume every X from min to max has some
// output.
let geom = self
.niri
.global_space
.outputs()
.map(|output| self.niri.global_space.output_geometry(output).unwrap())
.find(|geom| geom.contains((new_pos.x as i32, geom.loc.y)))
.unwrap();
new_pos.y = new_pos
.y
.clamp(geom.loc.y as f64, (geom.loc.y + geom.size.h - 1) as f64);
}
} }
pos.x = pos.x.clamp(min_x as f64, max_x as f64); let under = self.niri.surface_under_and_global_space(new_pos);
pos.y = pos.y.clamp(min_y as f64, max_y as f64);
let under = self.niri.surface_under_and_global_space(pos);
pointer.motion( pointer.motion(
self, self,
under.clone(), under.clone(),
&MotionEvent { &MotionEvent {
location: pos, location: new_pos,
serial, serial,
time: event.time_msec(), time: event.time_msec(),
}, },