diff --git a/CHANGELOG.md b/CHANGELOG.md index 3be2cf75..9417bd2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Unreleased` header. # Unreleased +- On X11, filter close to zero values in mouse device events - Move `dpi` types to its own crate, and re-export it from the root crate. - Implement `Sync` for `EventLoopProxy`. - **Breaking:** Move `Window::new` to `ActiveEventLoop::create_window` and `EventLoop::create_window` (with the latter being deprecated). diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index c6cd61e9..bca85ae6 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1518,8 +1518,8 @@ impl EventProcessor { let mask = unsafe { slice::from_raw_parts(xev.valuators.mask, xev.valuators.mask_len as usize) }; let mut value = xev.raw_values; - let mut mouse_delta = (0.0, 0.0); - let mut scroll_delta = (0.0, 0.0); + let mut mouse_delta = util::Delta::default(); + let mut scroll_delta = util::Delta::default(); for i in 0..xev.valuators.mask_len * 8 { if !xinput2::XIMaskIsSet(mask, i) { continue; @@ -1529,10 +1529,10 @@ impl EventProcessor { // We assume that every XInput2 device with analog axes is a pointing device emitting // relative coordinates. match i { - 0 => mouse_delta.0 = x, - 1 => mouse_delta.1 = x, - 2 => scroll_delta.0 = x as f32, - 3 => scroll_delta.1 = x as f32, + 0 => mouse_delta.set_x(x), + 1 => mouse_delta.set_y(x), + 2 => scroll_delta.set_x(x as f32), + 3 => scroll_delta.set_y(x as f32), _ => {} } @@ -1548,7 +1548,7 @@ impl EventProcessor { value = unsafe { value.offset(1) }; } - if mouse_delta != (0.0, 0.0) { + if let Some(mouse_delta) = mouse_delta.consume() { let event = Event::DeviceEvent { device_id: did, event: DeviceEvent::MouseMotion { delta: mouse_delta }, @@ -1556,7 +1556,7 @@ impl EventProcessor { callback(&self.target, event); } - if scroll_delta != (0.0, 0.0) { + if let Some(scroll_delta) = scroll_delta.consume() { let event = Event::DeviceEvent { device_id: did, event: DeviceEvent::MouseWheel { diff --git a/src/platform_impl/linux/x11/util/mod.rs b/src/platform_impl/linux/x11/util/mod.rs index 3246b072..0db5986c 100644 --- a/src/platform_impl/linux/x11/util/mod.rs +++ b/src/platform_impl/linux/x11/util/mod.rs @@ -15,13 +15,15 @@ mod icon; mod input; pub mod keys; pub(crate) mod memory; +mod mouse; mod randr; mod window_property; mod wm; mod xmodmap; pub use self::{ - cursor::*, geometry::*, hint::*, input::*, window_property::*, wm::*, xmodmap::ModifierKeymap, + cursor::*, geometry::*, hint::*, input::*, mouse::*, window_property::*, wm::*, + xmodmap::ModifierKeymap, }; use super::{atoms::*, ffi, VoidCookie, X11Error, XConnection, XError}; diff --git a/src/platform_impl/linux/x11/util/mouse.rs b/src/platform_impl/linux/x11/util/mouse.rs new file mode 100644 index 00000000..212ea572 --- /dev/null +++ b/src/platform_impl/linux/x11/util/mouse.rs @@ -0,0 +1,52 @@ +//! Utilities for handling mouse events. + +/// Recorded mouse delta designed to filter out noise. +pub struct Delta { + x: T, + y: T, +} + +impl Default for Delta { + fn default() -> Self { + Self { + x: Default::default(), + y: Default::default(), + } + } +} + +impl Delta { + pub(crate) fn set_x(&mut self, x: T) { + self.x = x; + } + + pub(crate) fn set_y(&mut self, y: T) { + self.y = y; + } +} + +macro_rules! consume { + ($this:expr, $ty:ty) => {{ + let this = $this; + let (x, y) = match (this.x.abs() < <$ty>::EPSILON, this.y.abs() < <$ty>::EPSILON) { + (true, true) => return None, + (true, false) => (this.x, 0.0), + (false, true) => (0.0, this.y), + (false, false) => (this.x, this.y), + }; + + Some((x, y)) + }}; +} + +impl Delta { + pub(crate) fn consume(self) -> Option<(f32, f32)> { + consume!(self, f32) + } +} + +impl Delta { + pub(crate) fn consume(self) -> Option<(f64, f64)> { + consume!(self, f64) + } +}