//! Input backend implementation for the X11 backend. use super::{window_inner::WindowInner, Window, WindowTemporary}; use crate::{ backend::input::{ self, AbsolutePositionEvent, Axis, AxisRelativeDirection, AxisSource, ButtonState, Device, DeviceCapability, InputBackend, KeyState, KeyboardKeyEvent, Keycode, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, UnusedEvent, }, utils::{Logical, Size}, }; use std::sync::Weak; /// Marker used to define the `InputBackend` types for the X11 backend. #[derive(Debug)] pub struct X11Input; /// Virtual input device used by the backend to associate input events. #[derive(Debug, PartialEq, Eq, Hash)] pub struct X11VirtualDevice; impl Device for X11VirtualDevice { fn id(&self) -> String { "x11".to_owned() } fn name(&self) -> String { "x11 virtual input".to_owned() } fn has_capability(&self, capability: DeviceCapability) -> bool { matches!( capability, DeviceCapability::Keyboard | DeviceCapability::Pointer | DeviceCapability::Touch ) } fn usb_id(&self) -> Option<(u32, u32)> { None } fn syspath(&self) -> Option { None } } /// X11-Backend internal event wrapping `X11`'s types into a [`KeyboardKeyEvent`]. #[derive(Debug, Clone)] pub struct X11KeyboardInputEvent { pub(crate) time: u32, pub(crate) key: Keycode, pub(crate) count: u32, pub(crate) state: KeyState, pub(crate) window: Weak, } impl X11KeyboardInputEvent { /// Returns a temporary reference to the window belonging to this event. /// /// Returns None if the window is not alive anymore. pub fn window(&self) -> Option + '_> { self.window.upgrade().map(Window).map(WindowTemporary) } } impl input::Event for X11KeyboardInputEvent { fn time(&self) -> u64 { self.time as u64 * 1000 } fn device(&self) -> X11VirtualDevice { X11VirtualDevice } } impl KeyboardKeyEvent for X11KeyboardInputEvent { fn key_code(&self) -> Keycode { self.key } fn state(&self) -> KeyState { self.state } fn count(&self) -> u32 { self.count } } /// X11-Backend internal event wrapping `X11`'s types into a [`PointerAxisEvent`] #[derive(Debug, Clone)] pub struct X11MouseWheelEvent { pub(crate) time: u32, pub(crate) axis: Axis, pub(crate) amount: f64, pub(crate) window: Weak, } impl X11MouseWheelEvent { /// Returns a temporary reference to the window belonging to this event. /// /// Returns None if the window is not alive anymore. pub fn window(&self) -> Option + '_> { self.window.upgrade().map(Window).map(WindowTemporary) } } impl input::Event for X11MouseWheelEvent { fn time(&self) -> u64 { self.time as u64 * 1000 } fn device(&self) -> X11VirtualDevice { X11VirtualDevice } } impl PointerAxisEvent for X11MouseWheelEvent { fn amount(&self, _axis: Axis) -> Option { None } fn amount_v120(&self, axis: Axis) -> Option { if self.axis == axis { match axis { Axis::Vertical => Some(-self.amount * 120.), Axis::Horizontal => Some(self.amount * 120.), } } else { Some(0.0) } } fn source(&self) -> AxisSource { // X11 seems to act within the scope of individual rachets of a scroll wheel. AxisSource::Wheel } fn relative_direction(&self, _axis: Axis) -> AxisRelativeDirection { AxisRelativeDirection::Identical } } /// X11-Backend internal event wrapping `X11`'s types into a [`PointerButtonEvent`] #[derive(Debug, Clone)] pub struct X11MouseInputEvent { pub(crate) time: u32, pub(crate) raw: u32, pub(crate) state: ButtonState, pub(crate) window: Weak, } impl X11MouseInputEvent { /// Returns a temporary reference to the window belonging to this event. /// /// Returns None if the window is not alive anymore. pub fn window(&self) -> Option + '_> { self.window.upgrade().map(Window).map(WindowTemporary) } } impl input::Event for X11MouseInputEvent { fn time(&self) -> u64 { self.time as u64 * 1000 } fn device(&self) -> X11VirtualDevice { X11VirtualDevice } } impl PointerButtonEvent for X11MouseInputEvent { fn button_code(&self) -> u32 { input::xorg_mouse_to_libinput(self.raw) } fn state(&self) -> ButtonState { self.state } } /// X11-Backend internal event wrapping `X11`'s types into a [`PointerMotionAbsoluteEvent`] #[derive(Debug, Clone)] pub struct X11MouseMovedEvent { pub(crate) time: u32, pub(crate) x: f64, pub(crate) y: f64, pub(crate) size: Size, pub(crate) window: Weak, } impl X11MouseMovedEvent { /// Returns a temporary reference to the window belonging to this event. /// /// Returns None if the window is not alive anymore. pub fn window(&self) -> Option + '_> { self.window.upgrade().map(Window).map(WindowTemporary) } } impl input::Event for X11MouseMovedEvent { fn time(&self) -> u64 { self.time as u64 * 1000 } fn device(&self) -> X11VirtualDevice { X11VirtualDevice } } impl PointerMotionAbsoluteEvent for X11MouseMovedEvent {} impl AbsolutePositionEvent for X11MouseMovedEvent { fn x(&self) -> f64 { self.x } fn y(&self) -> f64 { self.y } fn x_transformed(&self, width: i32) -> f64 { f64::max(self.x * width as f64 / self.size.w as f64, 0.0) } fn y_transformed(&self, height: i32) -> f64 { f64::max(self.y * height as f64 / self.size.h as f64, 0.0) } } impl InputBackend for X11Input { type Device = X11VirtualDevice; type KeyboardKeyEvent = X11KeyboardInputEvent; type PointerAxisEvent = X11MouseWheelEvent; type PointerButtonEvent = X11MouseInputEvent; type PointerMotionEvent = UnusedEvent; type PointerMotionAbsoluteEvent = X11MouseMovedEvent; type GestureSwipeBeginEvent = UnusedEvent; type GestureSwipeUpdateEvent = UnusedEvent; type GestureSwipeEndEvent = UnusedEvent; type GesturePinchBeginEvent = UnusedEvent; type GesturePinchUpdateEvent = UnusedEvent; type GesturePinchEndEvent = UnusedEvent; type GestureHoldBeginEvent = UnusedEvent; type GestureHoldEndEvent = UnusedEvent; type TouchDownEvent = UnusedEvent; type TouchUpEvent = UnusedEvent; type TouchMotionEvent = UnusedEvent; type TouchCancelEvent = UnusedEvent; type TouchFrameEvent = UnusedEvent; type TabletToolAxisEvent = UnusedEvent; type TabletToolProximityEvent = UnusedEvent; type TabletToolTipEvent = UnusedEvent; type TabletToolButtonEvent = UnusedEvent; type SwitchToggleEvent = UnusedEvent; type SpecialEvent = UnusedEvent; }