aboutsummaryrefslogtreecommitdiff
path: root/src/input.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-09-05 18:02:05 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-09-05 18:02:05 +0400
commit934183ef003714f4d8dedeba55396c76ec8d5e4c (patch)
tree4fb554e0bfa46f269ef5ec51121c8412a3dc6925 /src/input.rs
parent72d6b387e74940c912f06ee91045cafa3b360c2d (diff)
downloadniri-934183ef003714f4d8dedeba55396c76ec8d5e4c.tar.gz
niri-934183ef003714f4d8dedeba55396c76ec8d5e4c.tar.bz2
niri-934183ef003714f4d8dedeba55396c76ec8d5e4c.zip
input: Clip pointer movement smarter
Diffstat (limited to 'src/input.rs')
-rw-r--r--src/input.rs77
1 files changed, 57 insertions, 20 deletions
diff --git a/src/input.rs b/src/input.rs
index 3dc589c0..ec3f9afd 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -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 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);
- }
- 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 pos = pointer.current_location();
+
+ // 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);
+ }
+ }
- 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(),
},