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
This commit is contained in:
Victor Berger 2020-07-12 20:08:44 +02:00 committed by Victor Berger
parent 25365ed69a
commit 49dda88c63
4 changed files with 53 additions and 54 deletions

View File

@ -132,7 +132,7 @@ impl AnvilState {
let screen_size = self.current_output_size(x); let screen_size = self.current_output_size(x);
// monitor coordinates // monitor coordinates
let (ux, uy) = evt.position_transformed(screen_size); 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 { } else {
// we are started in winit // we are started in winit
evt.position() evt.position()

View File

@ -243,22 +243,22 @@ impl PointerAxisEvent for UnusedEvent {
/// Trait for pointer events generated by relative device movement. /// Trait for pointer events generated by relative device movement.
pub trait PointerMotionEvent: Event { pub trait PointerMotionEvent: Event {
/// Delta between the last and new pointer device position interpreted as pixel movement /// 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()) (self.delta_x(), self.delta_y())
} }
/// Delta on the x axis between the last and new pointer device position interpreted as pixel movement /// 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 /// 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 { impl PointerMotionEvent for UnusedEvent {
fn delta_x(&self) -> i32 { fn delta_x(&self) -> f64 {
match *self {} match *self {}
} }
fn delta_y(&self) -> i32 { fn delta_y(&self) -> f64 {
match *self {} match *self {}
} }
} }
@ -284,7 +284,7 @@ pub trait PointerMotionAbsoluteEvent: Event {
/// Device position converted to the targets coordinate space. /// Device position converted to the targets coordinate space.
/// E.g. the focused output's resolution. /// 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.x_transformed(coordinate_space.0),
self.y_transformed(coordinate_space.1), 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. /// Device x position converted to the targets coordinate space's width.
/// E.g. the focused output'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. /// Device y position converted to the targets coordinate space's height.
/// E.g. the focused output'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 { impl PointerMotionAbsoluteEvent for UnusedEvent {
@ -309,11 +309,11 @@ impl PointerMotionAbsoluteEvent for UnusedEvent {
match *self {} match *self {}
} }
fn x_transformed(&self, _width: u32) -> u32 { fn x_transformed(&self, _width: u32) -> f64 {
match *self {} match *self {}
} }
fn y_transformed(&self, _height: u32) -> u32 { fn y_transformed(&self, _height: u32) -> f64 {
match *self {} match *self {}
} }
} }
@ -348,7 +348,7 @@ pub trait TouchDownEvent: Event {
/// Touch position converted into the target coordinate space. /// Touch position converted into the target coordinate space.
/// E.g. the focused output's resolution. /// 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.x_transformed(coordinate_space.0),
self.y_transformed(coordinate_space.1), 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. /// Touch event's x position converted to the targets coordinate space's width.
/// E.g. the focused output'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. /// Touch event's y position converted to the targets coordinate space's width.
/// E.g. the focused output'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 { impl TouchDownEvent for UnusedEvent {
@ -387,11 +387,11 @@ impl TouchDownEvent for UnusedEvent {
match *self {} match *self {}
} }
fn x_transformed(&self, _width: u32) -> u32 { fn x_transformed(&self, _width: u32) -> f64 {
match *self {} match *self {}
} }
fn y_transformed(&self, _height: u32) -> u32 { fn y_transformed(&self, _height: u32) -> f64 {
match *self {} match *self {}
} }
} }
@ -410,7 +410,7 @@ pub trait TouchMotionEvent: Event {
/// Touch position converted into the target coordinate space. /// Touch position converted into the target coordinate space.
/// E.g. the focused output's resolution. /// 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.x_transformed(coordinate_space.0),
self.y_transformed(coordinate_space.1), 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. /// Touch event's x position converted to the targets coordinate space's width.
/// E.g. the focused output'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. /// Touch event's y position converted to the targets coordinate space's width.
/// E.g. the focused output'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 { impl TouchMotionEvent for UnusedEvent {
@ -449,11 +449,11 @@ impl TouchMotionEvent for UnusedEvent {
match *self {} match *self {}
} }
fn x_transformed(&self, _width: u32) -> u32 { fn x_transformed(&self, _width: u32) -> f64 {
match *self {} match *self {}
} }
fn y_transformed(&self, _height: u32) -> u32 { fn y_transformed(&self, _height: u32) -> f64 {
match *self {} match *self {}
} }
} }

View File

@ -152,11 +152,11 @@ impl backend::Event for event::pointer::PointerMotionEvent {
} }
impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent { impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent {
fn delta_x(&self) -> i32 { fn delta_x(&self) -> f64 {
self.dx() as i32 self.dx()
} }
fn delta_y(&self) -> i32 { fn delta_y(&self) -> f64 {
self.dy() as i32 self.dy()
} }
} }
@ -175,12 +175,12 @@ impl backend::PointerMotionAbsoluteEvent for event::pointer::PointerMotionAbsolu
self.absolute_y() self.absolute_y()
} }
fn x_transformed(&self, width: u32) -> u32 { fn x_transformed(&self, width: u32) -> f64 {
self.absolute_x_transformed(width) as u32 self.absolute_x_transformed(width)
} }
fn y_transformed(&self, height: u32) -> u32 { fn y_transformed(&self, height: u32) -> f64 {
self.absolute_y_transformed(height) as u32 self.absolute_y_transformed(height)
} }
} }
@ -203,12 +203,12 @@ impl backend::TouchDownEvent for event::touch::TouchDownEvent {
event::touch::TouchEventPosition::y(self) event::touch::TouchEventPosition::y(self)
} }
fn x_transformed(&self, width: u32) -> u32 { fn x_transformed(&self, width: u32) -> f64 {
event::touch::TouchEventPosition::x_transformed(self, width) as u32 event::touch::TouchEventPosition::x_transformed(self, width)
} }
fn y_transformed(&self, height: u32) -> u32 { fn y_transformed(&self, height: u32) -> f64 {
event::touch::TouchEventPosition::y_transformed(self, height) as u32 event::touch::TouchEventPosition::y_transformed(self, height)
} }
} }
@ -231,12 +231,12 @@ impl backend::TouchMotionEvent for event::touch::TouchMotionEvent {
event::touch::TouchEventPosition::y(self) event::touch::TouchEventPosition::y(self)
} }
fn x_transformed(&self, width: u32) -> u32 { fn x_transformed(&self, width: u32) -> f64 {
event::touch::TouchEventPosition::x_transformed(self, width) as u32 event::touch::TouchEventPosition::x_transformed(self, width)
} }
fn y_transformed(&self, height: u32) -> u32 { fn y_transformed(&self, height: u32) -> f64 {
event::touch::TouchEventPosition::y_transformed(self, height) as u32 event::touch::TouchEventPosition::y_transformed(self, height)
} }
} }

View File

@ -15,7 +15,6 @@ use crate::backend::{
use nix::libc::c_void; use nix::libc::c_void;
use std::{ use std::{
cell::{Ref, RefCell}, cell::{Ref, RefCell},
cmp,
convert::TryInto, convert::TryInto,
rc::Rc, rc::Rc,
time::Instant, time::Instant,
@ -415,16 +414,16 @@ impl PointerMotionAbsoluteEvent for WinitMouseMovedEvent {
self.logical_position.y * wsize.scale_factor 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 wsize = self.size.borrow();
let w_width = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).width; let w_width = wsize.physical_size.to_logical::<f64>(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 wsize = self.size.borrow();
let w_height = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).height; let w_height = wsize.physical_size.to_logical::<f64>(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 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 wsize = self.size.borrow();
let w_width = wsize.physical_size.to_logical::<i32>(wsize.scale_factor).width; let w_width = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).width;
cmp::min(self.location.0 as i32 * width as i32 / w_width, 0) as u32 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 wsize = self.size.borrow();
let w_height = wsize.physical_size.to_logical::<i32>(wsize.scale_factor).height; let w_height = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).height;
cmp::min(self.location.1 as i32 * height as i32 / w_height, 0) as u32 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 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 wsize = self.size.borrow();
let w_width = wsize.physical_size.to_logical::<u32>(wsize.scale_factor).width; let w_width = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).width;
self.location.0 as u32 * width / w_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 wsize = self.size.borrow();
let w_height = wsize.physical_size.to_logical::<u32>(wsize.scale_factor).height; let w_height = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).height;
self.location.1 as u32 * height / w_height f64::max(self.location.1 * height as f64 / w_height, 0.0)
} }
} }