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;
#[derive(Debug)]
pub struct X11Input;
#[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<std::path::PathBuf> {
None
}
}
#[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<WindowInner>,
}
impl X11KeyboardInputEvent {
pub fn window(&self) -> Option<impl AsRef<Window> + '_> {
self.window.upgrade().map(Window).map(WindowTemporary)
}
}
impl input::Event<X11Input> for X11KeyboardInputEvent {
fn time(&self) -> u64 {
self.time as u64 * 1000
}
fn device(&self) -> X11VirtualDevice {
X11VirtualDevice
}
}
impl KeyboardKeyEvent<X11Input> for X11KeyboardInputEvent {
fn key_code(&self) -> Keycode {
self.key
}
fn state(&self) -> KeyState {
self.state
}
fn count(&self) -> u32 {
self.count
}
}
#[derive(Debug, Clone)]
pub struct X11MouseWheelEvent {
pub(crate) time: u32,
pub(crate) axis: Axis,
pub(crate) amount: f64,
pub(crate) window: Weak<WindowInner>,
}
impl X11MouseWheelEvent {
pub fn window(&self) -> Option<impl AsRef<Window> + '_> {
self.window.upgrade().map(Window).map(WindowTemporary)
}
}
impl input::Event<X11Input> for X11MouseWheelEvent {
fn time(&self) -> u64 {
self.time as u64 * 1000
}
fn device(&self) -> X11VirtualDevice {
X11VirtualDevice
}
}
impl PointerAxisEvent<X11Input> for X11MouseWheelEvent {
fn amount(&self, _axis: Axis) -> Option<f64> {
None
}
fn amount_v120(&self, axis: Axis) -> Option<f64> {
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 {
AxisSource::Wheel
}
fn relative_direction(&self, _axis: Axis) -> AxisRelativeDirection {
AxisRelativeDirection::Identical
}
}
#[derive(Debug, Clone)]
pub struct X11MouseInputEvent {
pub(crate) time: u32,
pub(crate) raw: u32,
pub(crate) state: ButtonState,
pub(crate) window: Weak<WindowInner>,
}
impl X11MouseInputEvent {
pub fn window(&self) -> Option<impl AsRef<Window> + '_> {
self.window.upgrade().map(Window).map(WindowTemporary)
}
}
impl input::Event<X11Input> for X11MouseInputEvent {
fn time(&self) -> u64 {
self.time as u64 * 1000
}
fn device(&self) -> X11VirtualDevice {
X11VirtualDevice
}
}
impl PointerButtonEvent<X11Input> for X11MouseInputEvent {
fn button_code(&self) -> u32 {
input::xorg_mouse_to_libinput(self.raw)
}
fn state(&self) -> ButtonState {
self.state
}
}
#[derive(Debug, Clone)]
pub struct X11MouseMovedEvent {
pub(crate) time: u32,
pub(crate) x: f64,
pub(crate) y: f64,
pub(crate) size: Size<u16, Logical>,
pub(crate) window: Weak<WindowInner>,
}
impl X11MouseMovedEvent {
pub fn window(&self) -> Option<impl AsRef<Window> + '_> {
self.window.upgrade().map(Window).map(WindowTemporary)
}
}
impl input::Event<X11Input> for X11MouseMovedEvent {
fn time(&self) -> u64 {
self.time as u64 * 1000
}
fn device(&self) -> X11VirtualDevice {
X11VirtualDevice
}
}
impl PointerMotionAbsoluteEvent<X11Input> for X11MouseMovedEvent {}
impl AbsolutePositionEvent<X11Input> 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;
}