mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
input: Clip pointer movement smarter
This commit is contained in:
+55
-18
@@ -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(),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user