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, .. } => {
// 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 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;
let mut min_y = i32::MAX;
let mut max_x = 0;
let mut max_y = 0;
for output in self.niri.global_space.outputs() {
// FIXME: smarter clamping.
let geom = self.niri.global_space.output_geometry(output).unwrap();
min_x = min_x.min(geom.loc.x);
min_y = min_y.min(geom.loc.y);
max_x = max_x.max(geom.loc.x + geom.size.w);
max_y = max_y.max(geom.loc.y + geom.size.h);
// We have an output, so we can compute the new location and focus.
let mut new_pos = pos + event.delta();
if self
.niri
.global_space
.output_under(new_pos)
.next()
.is_none()
{
// 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);
pos.y = pos.y.clamp(min_y as f64, max_y as f64);
let under = self.niri.surface_under_and_global_space(pos);
let under = self.niri.surface_under_and_global_space(new_pos);
pointer.motion(
self,
under.clone(),
&MotionEvent {
location: pos,
location: new_pos,
serial,
time: event.time_msec(),
},