Skip to content

Commit 20c5343

Browse files
committed
fix(input): fix pointer clamping with multiple displays
1 parent 3f68eee commit 20c5343

1 file changed

Lines changed: 45 additions & 12 deletions

File tree

src/input/mod.rs

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use smithay::{
5959
reexports::{
6060
input::Device as InputDevice, wayland_server::protocol::wl_shm::Format as ShmFormat,
6161
},
62-
utils::{Point, Rectangle, SERIAL_COUNTER, Serial},
62+
utils::{Coordinate, Point, Rectangle, SERIAL_COUNTER, Serial},
6363
wayland::{
6464
image_copy_capture::{BufferConstraints, CursorSessionRef},
6565
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
@@ -350,21 +350,48 @@ impl State {
350350
let original_position = position;
351351
position += event.delta().as_global();
352352

353-
let output = shell
354-
.outputs()
355-
.find(|output| output.geometry().to_f64().contains(position))
353+
let output_containing_position =
354+
State::output_containing_point(position, &shell);
355+
356+
let output = output_containing_position
356357
.cloned()
357358
.unwrap_or(current_output.clone());
358359

359360
let output_geometry = output.geometry();
360-
position.x = position.x.clamp(
361-
output_geometry.loc.x as f64,
362-
(output_geometry.loc.x + output_geometry.size.w - 1) as f64,
363-
);
364-
position.y = position.y.clamp(
365-
output_geometry.loc.y as f64,
366-
(output_geometry.loc.y + output_geometry.size.h - 1) as f64,
367-
);
361+
362+
{
363+
// Clamp the position to the output geometry
364+
let top_left: Point<f64, Global> =
365+
Point::new(output_geometry.loc.x as f64, output_geometry.loc.y as f64);
366+
let bottom_right: Point<f64, Global> = Point::new(
367+
top_left.x.saturating_add(output_geometry.size.w as f64) - 1.0,
368+
top_left.y.saturating_add(output_geometry.size.h as f64) - 1.0,
369+
);
370+
if output_containing_position.is_none() {
371+
position.x = position.x.clamp(top_left.x, bottom_right.x);
372+
position.y = position.y.clamp(top_left.y, bottom_right.y);
373+
} else {
374+
let old_position = position.clone();
375+
if position.x > bottom_right.x
376+
&& State::output_containing_point(
377+
Point::new(bottom_right.x + 1.0, old_position.y),
378+
&shell,
379+
)
380+
.is_none()
381+
{
382+
position.x = bottom_right.x;
383+
}
384+
if position.y > bottom_right.y
385+
&& State::output_containing_point(
386+
Point::new(old_position.x, bottom_right.y + 1.0),
387+
&shell,
388+
)
389+
.is_none()
390+
{
391+
position.y = bottom_right.y;
392+
}
393+
}
394+
}
368395

369396
let new_under = State::surface_under(position, &output, &shell)
370397
.map(|(target, pos)| (target, pos.as_logical()));
@@ -2166,6 +2193,12 @@ impl State {
21662193
.flatten()
21672194
}
21682195

2196+
pub fn output_containing_point(point: Point<f64, Global>, shell: &Shell) -> Option<&Output> {
2197+
shell
2198+
.outputs()
2199+
.find(|output| output.geometry().to_f64().contains(point))
2200+
}
2201+
21692202
#[profiling::function]
21702203
pub fn surface_under(
21712204
global_pos: Point<f64, Global>,

0 commit comments

Comments
 (0)