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