From 49dda88c637105b1659282a3373b39c97f28a5b8 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 12 Jul 2020 20:08:44 +0200 Subject: [PATCH] backend.input: keep sub-pixel precision in events libinput provides sub-pixel precision for pointer motion & touch events. Keep this precision by switching all coordinates values from input events to f64 (rather than i32 or u32). Otherwise, values are rounded and part of the movment is lost. Potentially fixes #224 --- anvil/src/input_handler.rs | 2 +- src/backend/input.rs | 40 ++++++++++++++++++------------------- src/backend/libinput/mod.rs | 32 ++++++++++++++--------------- src/backend/winit.rs | 33 +++++++++++++++--------------- 4 files changed, 53 insertions(+), 54 deletions(-) diff --git a/anvil/src/input_handler.rs b/anvil/src/input_handler.rs index 9d288e6..bebf4df 100644 --- a/anvil/src/input_handler.rs +++ b/anvil/src/input_handler.rs @@ -132,7 +132,7 @@ impl AnvilState { let screen_size = self.current_output_size(x); // monitor coordinates let (ux, uy) = evt.position_transformed(screen_size); - ((ux + self.current_output_offset(x)) as f64, uy as f64) + (ux + self.current_output_offset(x) as f64, uy as f64) } else { // we are started in winit evt.position() diff --git a/src/backend/input.rs b/src/backend/input.rs index e9b64b2..24625d5 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -243,22 +243,22 @@ impl PointerAxisEvent for UnusedEvent { /// Trait for pointer events generated by relative device movement. pub trait PointerMotionEvent: Event { /// Delta between the last and new pointer device position interpreted as pixel movement - fn delta(&self) -> (i32, i32) { + fn delta(&self) -> (f64, f64) { (self.delta_x(), self.delta_y()) } /// Delta on the x axis between the last and new pointer device position interpreted as pixel movement - fn delta_x(&self) -> i32; + fn delta_x(&self) -> f64; /// Delta on the y axis between the last and new pointer device position interpreted as pixel movement - fn delta_y(&self) -> i32; + fn delta_y(&self) -> f64; } impl PointerMotionEvent for UnusedEvent { - fn delta_x(&self) -> i32 { + fn delta_x(&self) -> f64 { match *self {} } - fn delta_y(&self) -> i32 { + fn delta_y(&self) -> f64 { match *self {} } } @@ -284,7 +284,7 @@ pub trait PointerMotionAbsoluteEvent: Event { /// Device position converted to the targets coordinate space. /// E.g. the focused output's resolution. - fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { + fn position_transformed(&self, coordinate_space: (u32, u32)) -> (f64, f64) { ( self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1), @@ -293,11 +293,11 @@ pub trait PointerMotionAbsoluteEvent: Event { /// Device x position converted to the targets coordinate space's width. /// E.g. the focused output's width. - fn x_transformed(&self, width: u32) -> u32; + fn x_transformed(&self, width: u32) -> f64; /// Device y position converted to the targets coordinate space's height. /// E.g. the focused output's height. - fn y_transformed(&self, height: u32) -> u32; + fn y_transformed(&self, height: u32) -> f64; } impl PointerMotionAbsoluteEvent for UnusedEvent { @@ -309,11 +309,11 @@ impl PointerMotionAbsoluteEvent for UnusedEvent { match *self {} } - fn x_transformed(&self, _width: u32) -> u32 { + fn x_transformed(&self, _width: u32) -> f64 { match *self {} } - fn y_transformed(&self, _height: u32) -> u32 { + fn y_transformed(&self, _height: u32) -> f64 { match *self {} } } @@ -348,7 +348,7 @@ pub trait TouchDownEvent: Event { /// Touch position converted into the target coordinate space. /// E.g. the focused output's resolution. - fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { + fn position_transformed(&self, coordinate_space: (u32, u32)) -> (f64, f64) { ( self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1), @@ -367,11 +367,11 @@ pub trait TouchDownEvent: Event { /// Touch event's x position converted to the targets coordinate space's width. /// E.g. the focused output's width. - fn x_transformed(&self, width: u32) -> u32; + fn x_transformed(&self, width: u32) -> f64; /// Touch event's y position converted to the targets coordinate space's width. /// E.g. the focused output's width. - fn y_transformed(&self, height: u32) -> u32; + fn y_transformed(&self, height: u32) -> f64; } impl TouchDownEvent for UnusedEvent { @@ -387,11 +387,11 @@ impl TouchDownEvent for UnusedEvent { match *self {} } - fn x_transformed(&self, _width: u32) -> u32 { + fn x_transformed(&self, _width: u32) -> f64 { match *self {} } - fn y_transformed(&self, _height: u32) -> u32 { + fn y_transformed(&self, _height: u32) -> f64 { match *self {} } } @@ -410,7 +410,7 @@ pub trait TouchMotionEvent: Event { /// Touch position converted into the target coordinate space. /// E.g. the focused output's resolution. - fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { + fn position_transformed(&self, coordinate_space: (u32, u32)) -> (f64, f64) { ( self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1), @@ -429,11 +429,11 @@ pub trait TouchMotionEvent: Event { /// Touch event's x position converted to the targets coordinate space's width. /// E.g. the focused output's width. - fn x_transformed(&self, width: u32) -> u32; + fn x_transformed(&self, width: u32) -> f64; /// Touch event's y position converted to the targets coordinate space's width. /// E.g. the focused output's width. - fn y_transformed(&self, height: u32) -> u32; + fn y_transformed(&self, height: u32) -> f64; } impl TouchMotionEvent for UnusedEvent { @@ -449,11 +449,11 @@ impl TouchMotionEvent for UnusedEvent { match *self {} } - fn x_transformed(&self, _width: u32) -> u32 { + fn x_transformed(&self, _width: u32) -> f64 { match *self {} } - fn y_transformed(&self, _height: u32) -> u32 { + fn y_transformed(&self, _height: u32) -> f64 { match *self {} } } diff --git a/src/backend/libinput/mod.rs b/src/backend/libinput/mod.rs index 3672993..f14364f 100644 --- a/src/backend/libinput/mod.rs +++ b/src/backend/libinput/mod.rs @@ -152,11 +152,11 @@ impl backend::Event for event::pointer::PointerMotionEvent { } impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent { - fn delta_x(&self) -> i32 { - self.dx() as i32 + fn delta_x(&self) -> f64 { + self.dx() } - fn delta_y(&self) -> i32 { - self.dy() as i32 + fn delta_y(&self) -> f64 { + self.dy() } } @@ -175,12 +175,12 @@ impl backend::PointerMotionAbsoluteEvent for event::pointer::PointerMotionAbsolu self.absolute_y() } - fn x_transformed(&self, width: u32) -> u32 { - self.absolute_x_transformed(width) as u32 + fn x_transformed(&self, width: u32) -> f64 { + self.absolute_x_transformed(width) } - fn y_transformed(&self, height: u32) -> u32 { - self.absolute_y_transformed(height) as u32 + fn y_transformed(&self, height: u32) -> f64 { + self.absolute_y_transformed(height) } } @@ -203,12 +203,12 @@ impl backend::TouchDownEvent for event::touch::TouchDownEvent { event::touch::TouchEventPosition::y(self) } - fn x_transformed(&self, width: u32) -> u32 { - event::touch::TouchEventPosition::x_transformed(self, width) as u32 + fn x_transformed(&self, width: u32) -> f64 { + event::touch::TouchEventPosition::x_transformed(self, width) } - fn y_transformed(&self, height: u32) -> u32 { - event::touch::TouchEventPosition::y_transformed(self, height) as u32 + fn y_transformed(&self, height: u32) -> f64 { + event::touch::TouchEventPosition::y_transformed(self, height) } } @@ -231,12 +231,12 @@ impl backend::TouchMotionEvent for event::touch::TouchMotionEvent { event::touch::TouchEventPosition::y(self) } - fn x_transformed(&self, width: u32) -> u32 { - event::touch::TouchEventPosition::x_transformed(self, width) as u32 + fn x_transformed(&self, width: u32) -> f64 { + event::touch::TouchEventPosition::x_transformed(self, width) } - fn y_transformed(&self, height: u32) -> u32 { - event::touch::TouchEventPosition::y_transformed(self, height) as u32 + fn y_transformed(&self, height: u32) -> f64 { + event::touch::TouchEventPosition::y_transformed(self, height) } } diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 4204c56..8bd2fce 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -15,7 +15,6 @@ use crate::backend::{ use nix::libc::c_void; use std::{ cell::{Ref, RefCell}, - cmp, convert::TryInto, rc::Rc, time::Instant, @@ -415,16 +414,16 @@ impl PointerMotionAbsoluteEvent for WinitMouseMovedEvent { self.logical_position.y * wsize.scale_factor } - fn x_transformed(&self, width: u32) -> u32 { + fn x_transformed(&self, width: u32) -> f64 { let wsize = self.size.borrow(); let w_width = wsize.physical_size.to_logical::(wsize.scale_factor).width; - cmp::max((self.logical_position.x * width as f64 / w_width) as i32, 0) as u32 + f64::max(self.logical_position.x * width as f64 / w_width, 0.0) } - fn y_transformed(&self, height: u32) -> u32 { + fn y_transformed(&self, height: u32) -> f64 { let wsize = self.size.borrow(); let w_height = wsize.physical_size.to_logical::(wsize.scale_factor).height; - cmp::max((self.logical_position.y * height as f64 / w_height) as i32, 0) as u32 + f64::max(self.logical_position.y * height as f64 / w_height, 0.0) } } @@ -520,16 +519,16 @@ impl TouchDownEvent for WinitTouchStartedEvent { self.location.1 * wsize.scale_factor } - fn x_transformed(&self, width: u32) -> u32 { + fn x_transformed(&self, width: u32) -> f64 { let wsize = self.size.borrow(); - let w_width = wsize.physical_size.to_logical::(wsize.scale_factor).width; - cmp::min(self.location.0 as i32 * width as i32 / w_width, 0) as u32 + let w_width = wsize.physical_size.to_logical::(wsize.scale_factor).width; + f64::max(self.location.0 * width as f64 / w_width, 0.0) } - fn y_transformed(&self, height: u32) -> u32 { + fn y_transformed(&self, height: u32) -> f64 { let wsize = self.size.borrow(); - let w_height = wsize.physical_size.to_logical::(wsize.scale_factor).height; - cmp::min(self.location.1 as i32 * height as i32 / w_height, 0) as u32 + let w_height = wsize.physical_size.to_logical::(wsize.scale_factor).height; + f64::max(self.location.1 * height as f64 / w_height, 0.0) } } @@ -563,16 +562,16 @@ impl TouchMotionEvent for WinitTouchMovedEvent { self.location.1 * wsize.scale_factor } - fn x_transformed(&self, width: u32) -> u32 { + fn x_transformed(&self, width: u32) -> f64 { let wsize = self.size.borrow(); - let w_width = wsize.physical_size.to_logical::(wsize.scale_factor).width; - self.location.0 as u32 * width / w_width + let w_width = wsize.physical_size.to_logical::(wsize.scale_factor).width; + f64::max(self.location.0 * width as f64 / w_width, 0.0) } - fn y_transformed(&self, height: u32) -> u32 { + fn y_transformed(&self, height: u32) -> f64 { let wsize = self.size.borrow(); - let w_height = wsize.physical_size.to_logical::(wsize.scale_factor).height; - self.location.1 as u32 * height / w_height + let w_height = wsize.physical_size.to_logical::(wsize.scale_factor).height; + f64::max(self.location.1 * height as f64 / w_height, 0.0) } }