Merge pull request #318 from Smithay/refactor/input_backend

Rework `InputBackend` abstractions to track individual devices
This commit is contained in:
Victor Brekenfeld 2021-06-30 00:14:20 +02:00 committed by GitHub
commit 616bacdff2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 313 additions and 584 deletions

View File

@ -110,7 +110,7 @@ pub fn run_winit(
while state.running.load(Ordering::SeqCst) { while state.running.load(Ordering::SeqCst) {
if input if input
.dispatch_new_events(|event, _| state.process_input_event(event)) .dispatch_new_events(|event| state.process_input_event(event))
.is_err() .is_err()
{ {
state.running.store(false, Ordering::SeqCst); state.running.store(false, Ordering::SeqCst);

View File

@ -2,78 +2,33 @@
use std::error::Error; use std::error::Error;
/// A seat describes a group of input devices and at least one /// Trait for generic functions every input device does provide
/// graphics device belonging together. pub trait Device: PartialEq + Eq + std::hash::Hash {
/// /// Unique id of a single device at a point in time.
/// By default only one seat exists for most systems and smithay backends ///
/// however multiseat configurations are possible and should be treated as /// Note: This means ids may be re-used by the backend for later devices.
/// separated users, all with their own focus, input and cursor available. fn id(&self) -> String;
/// /// Human-readable name of the device
/// Seats referring to the same internal id will always be equal and result in the same fn name(&self) -> String;
/// hash, but capabilities of cloned and copied [`Seat`]s will not be updated by smithay. /// Test if this device has a specific capability
/// Always refer to the [`Seat`] given by a callback for up-to-date information. You may fn has_capability(&self, capability: DeviceCapability) -> bool;
/// use this to calculate the differences since the last callback.
#[derive(Debug, Clone, Eq)]
pub struct Seat {
id: u64,
name: String,
capabilities: SeatCapabilities,
} }
impl Seat { /// Set of input types a device may provide
#[cfg(any(feature = "backend_winit", feature = "backend_libinput"))] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) fn new<S: std::string::ToString>(id: u64, name: S, capabilities: SeatCapabilities) -> Seat { #[allow(missing_docs)] // self explainatory
Seat { pub enum DeviceCapability {
id, Keyboard,
name: name.to_string(), Pointer,
capabilities, Touch,
} TabletTool,
} TabletPad,
Gesture,
#[cfg(feature = "backend_libinput")] Switch,
pub(crate) fn capabilities_mut(&mut self) -> &mut SeatCapabilities {
&mut self.capabilities
}
/// Get the currently capabilities of this [`Seat`]
pub fn capabilities(&self) -> &SeatCapabilities {
&self.capabilities
}
/// Get the name of this [`Seat`]
pub fn name(&self) -> &str {
&*self.name
}
}
impl ::std::cmp::PartialEq for Seat {
fn eq(&self, other: &Seat) -> bool {
self.id == other.id
}
}
impl ::std::hash::Hash for Seat {
fn hash<H>(&self, state: &mut H)
where
H: ::std::hash::Hasher,
{
self.id.hash(state);
}
}
/// Describes capabilities a [`Seat`] has.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SeatCapabilities {
/// [`Seat`] has a pointer
pub pointer: bool,
/// [`Seat`] has a keyboard
pub keyboard: bool,
/// [`Seat`] has a touchscreen
pub touch: bool,
} }
/// Trait for generic functions every input event does provide /// Trait for generic functions every input event does provide
pub trait Event { pub trait Event<B: InputBackend> {
/// Returns an upward counting variable useful for event ordering. /// Returns an upward counting variable useful for event ordering.
/// ///
/// Makes no guarantees about actual time passed between events. /// Makes no guarantees about actual time passed between events.
@ -81,6 +36,8 @@ pub trait Event {
// - check if events can even arrive out of order. // - check if events can even arrive out of order.
// - Make stronger time guarantees, if possible // - Make stronger time guarantees, if possible
fn time(&self) -> u32; fn time(&self) -> u32;
/// Returns the device, that generated this event
fn device(&self) -> B::Device;
} }
/// Used to mark events never emitted by an [`InputBackend`] implementation. /// Used to mark events never emitted by an [`InputBackend`] implementation.
@ -92,10 +49,14 @@ pub trait Event {
#[derive(Debug)] #[derive(Debug)]
pub enum UnusedEvent {} pub enum UnusedEvent {}
impl Event for UnusedEvent { impl<B: InputBackend> Event<B> for UnusedEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
match *self {} match *self {}
} }
fn device(&self) -> B::Device {
match *self {}
}
} }
/// State of key on a keyboard. Either pressed or released /// State of key on a keyboard. Either pressed or released
@ -108,7 +69,7 @@ pub enum KeyState {
} }
/// Trait for keyboard event /// Trait for keyboard event
pub trait KeyboardKeyEvent: Event { pub trait KeyboardKeyEvent<B: InputBackend>: Event<B> {
/// Code of the pressed key. See `linux/input-event-codes.h` /// Code of the pressed key. See `linux/input-event-codes.h`
fn key_code(&self) -> u32; fn key_code(&self) -> u32;
/// State of the key /// State of the key
@ -117,7 +78,7 @@ pub trait KeyboardKeyEvent: Event {
fn count(&self) -> u32; fn count(&self) -> u32;
} }
impl KeyboardKeyEvent for UnusedEvent { impl<B: InputBackend> KeyboardKeyEvent<B> for UnusedEvent {
fn key_code(&self) -> u32 { fn key_code(&self) -> u32 {
match *self {} match *self {}
} }
@ -154,14 +115,14 @@ pub enum MouseButtonState {
} }
/// Common methods pointer event generated by pressed buttons do implement /// Common methods pointer event generated by pressed buttons do implement
pub trait PointerButtonEvent: Event { pub trait PointerButtonEvent<B: InputBackend>: Event<B> {
/// Pressed button of the event /// Pressed button of the event
fn button(&self) -> MouseButton; fn button(&self) -> MouseButton;
/// State of the button /// State of the button
fn state(&self) -> MouseButtonState; fn state(&self) -> MouseButtonState;
} }
impl PointerButtonEvent for UnusedEvent { impl<B: InputBackend> PointerButtonEvent<B> for UnusedEvent {
fn button(&self) -> MouseButton { fn button(&self) -> MouseButton {
match *self {} match *self {}
} }
@ -214,7 +175,7 @@ pub enum AxisSource {
} }
/// Trait for pointer events generated by scrolling on an axis. /// Trait for pointer events generated by scrolling on an axis.
pub trait PointerAxisEvent: Event { pub trait PointerAxisEvent<B: InputBackend>: Event<B> {
/// Amount of scrolling in pixels on the given [`Axis`]. /// Amount of scrolling in pixels on the given [`Axis`].
/// ///
/// Guaranteed to be `Some` when source returns either [`AxisSource::Finger`] or [`AxisSource::Continuous`]. /// Guaranteed to be `Some` when source returns either [`AxisSource::Finger`] or [`AxisSource::Continuous`].
@ -229,7 +190,7 @@ pub trait PointerAxisEvent: Event {
fn source(&self) -> AxisSource; fn source(&self) -> AxisSource;
} }
impl PointerAxisEvent for UnusedEvent { impl<B: InputBackend> PointerAxisEvent<B> for UnusedEvent {
fn amount(&self, _axis: Axis) -> Option<f64> { fn amount(&self, _axis: Axis) -> Option<f64> {
match *self {} match *self {}
} }
@ -244,7 +205,7 @@ 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<B: InputBackend>: Event<B> {
/// 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) -> (f64, f64) { fn delta(&self) -> (f64, f64) {
(self.delta_x(), self.delta_y()) (self.delta_x(), self.delta_y())
@ -256,7 +217,7 @@ pub trait PointerMotionEvent: Event {
fn delta_y(&self) -> f64; fn delta_y(&self) -> f64;
} }
impl PointerMotionEvent for UnusedEvent { impl<B: InputBackend> PointerMotionEvent<B> for UnusedEvent {
fn delta_x(&self) -> f64 { fn delta_x(&self) -> f64 {
match *self {} match *self {}
} }
@ -267,7 +228,7 @@ impl PointerMotionEvent for UnusedEvent {
} }
/// Trait for pointer events generated by absolute device positioning. /// Trait for pointer events generated by absolute device positioning.
pub trait PointerMotionAbsoluteEvent: Event { pub trait PointerMotionAbsoluteEvent<B: InputBackend>: Event<B> {
/// Device position in it's original coordinate space. /// Device position in it's original coordinate space.
/// ///
/// The format is defined by the backend implementation. /// The format is defined by the backend implementation.
@ -303,7 +264,7 @@ pub trait PointerMotionAbsoluteEvent: Event {
fn y_transformed(&self, height: u32) -> f64; fn y_transformed(&self, height: u32) -> f64;
} }
impl PointerMotionAbsoluteEvent for UnusedEvent { impl<B: InputBackend> PointerMotionAbsoluteEvent<B> for UnusedEvent {
fn x(&self) -> f64 { fn x(&self) -> f64 {
match *self {} match *self {}
} }
@ -339,7 +300,7 @@ impl TouchSlot {
} }
/// Trait for touch events starting at a given position. /// Trait for touch events starting at a given position.
pub trait TouchDownEvent: Event { pub trait TouchDownEvent<B: InputBackend>: Event<B> {
/// [`TouchSlot`], if the device has multi-touch capabilities /// [`TouchSlot`], if the device has multi-touch capabilities
fn slot(&self) -> Option<TouchSlot>; fn slot(&self) -> Option<TouchSlot>;
@ -378,7 +339,7 @@ pub trait TouchDownEvent: Event {
fn y_transformed(&self, height: u32) -> f64; fn y_transformed(&self, height: u32) -> f64;
} }
impl TouchDownEvent for UnusedEvent { impl<B: InputBackend> TouchDownEvent<B> for UnusedEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
match *self {} match *self {}
} }
@ -401,7 +362,7 @@ impl TouchDownEvent for UnusedEvent {
} }
/// Trait for touch events regarding movement on the screen /// Trait for touch events regarding movement on the screen
pub trait TouchMotionEvent: Event { pub trait TouchMotionEvent<B: InputBackend>: Event<B> {
/// [`TouchSlot`], if the device has multi-touch capabilities /// [`TouchSlot`], if the device has multi-touch capabilities
fn slot(&self) -> Option<TouchSlot>; fn slot(&self) -> Option<TouchSlot>;
@ -440,7 +401,7 @@ pub trait TouchMotionEvent: Event {
fn y_transformed(&self, height: u32) -> f64; fn y_transformed(&self, height: u32) -> f64;
} }
impl TouchMotionEvent for UnusedEvent { impl<B: InputBackend> TouchMotionEvent<B> for UnusedEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
match *self {} match *self {}
} }
@ -463,33 +424,33 @@ impl TouchMotionEvent for UnusedEvent {
} }
/// Trait for touch events finishing. /// Trait for touch events finishing.
pub trait TouchUpEvent: Event { pub trait TouchUpEvent<B: InputBackend>: Event<B> {
/// [`TouchSlot`], if the device has multi-touch capabilities /// [`TouchSlot`], if the device has multi-touch capabilities
fn slot(&self) -> Option<TouchSlot>; fn slot(&self) -> Option<TouchSlot>;
} }
impl TouchUpEvent for UnusedEvent { impl<B: InputBackend> TouchUpEvent<B> for UnusedEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
match *self {} match *self {}
} }
} }
/// Trait for touch events cancelling the chain /// Trait for touch events cancelling the chain
pub trait TouchCancelEvent: Event { pub trait TouchCancelEvent<B: InputBackend>: Event<B> {
/// [`TouchSlot`], if the device has multi-touch capabilities /// [`TouchSlot`], if the device has multi-touch capabilities
fn slot(&self) -> Option<TouchSlot>; fn slot(&self) -> Option<TouchSlot>;
} }
impl TouchCancelEvent for UnusedEvent { impl<B: InputBackend> TouchCancelEvent<B> for UnusedEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
match *self {} match *self {}
} }
} }
/// Trait for touch frame events /// Trait for touch frame events
pub trait TouchFrameEvent: Event {} pub trait TouchFrameEvent<B: InputBackend>: Event<B> {}
impl TouchFrameEvent for UnusedEvent {} impl<B: InputBackend> TouchFrameEvent<B> for UnusedEvent {}
/// Trait that describes objects providing a source of input events. All input backends /// Trait that describes objects providing a source of input events. All input backends
/// need to implement this and provide the same base guarantees about the precision of /// need to implement this and provide the same base guarantees about the precision of
@ -498,117 +459,93 @@ pub trait InputBackend: Sized {
/// Type representing errors that may be returned when processing events /// Type representing errors that may be returned when processing events
type EventError: Error; type EventError: Error;
/// Type representing input devices
type Device: Device;
/// Type representing keyboard events /// Type representing keyboard events
type KeyboardKeyEvent: KeyboardKeyEvent; type KeyboardKeyEvent: KeyboardKeyEvent<Self>;
/// Type representing axis events on pointer devices /// Type representing axis events on pointer devices
type PointerAxisEvent: PointerAxisEvent; type PointerAxisEvent: PointerAxisEvent<Self>;
/// Type representing button events on pointer devices /// Type representing button events on pointer devices
type PointerButtonEvent: PointerButtonEvent; type PointerButtonEvent: PointerButtonEvent<Self>;
/// Type representing motion events of pointer devices /// Type representing motion events of pointer devices
type PointerMotionEvent: PointerMotionEvent; type PointerMotionEvent: PointerMotionEvent<Self>;
/// Type representing motion events of pointer devices /// Type representing motion events of pointer devices
type PointerMotionAbsoluteEvent: PointerMotionAbsoluteEvent; type PointerMotionAbsoluteEvent: PointerMotionAbsoluteEvent<Self>;
/// Type representing touch events starting /// Type representing touch events starting
type TouchDownEvent: TouchDownEvent; type TouchDownEvent: TouchDownEvent<Self>;
/// Type representing touch events ending /// Type representing touch events ending
type TouchUpEvent: TouchUpEvent; type TouchUpEvent: TouchUpEvent<Self>;
/// Type representing touch events from moving /// Type representing touch events from moving
type TouchMotionEvent: TouchMotionEvent; type TouchMotionEvent: TouchMotionEvent<Self>;
/// Type representing cancelling of touch events /// Type representing cancelling of touch events
type TouchCancelEvent: TouchCancelEvent; type TouchCancelEvent: TouchCancelEvent<Self>;
/// Type representing touch frame events /// Type representing touch frame events
type TouchFrameEvent: TouchFrameEvent; type TouchFrameEvent: TouchFrameEvent<Self>;
/// Special events that are custom to this backend /// Special events that are custom to this backend
type SpecialEvent; type SpecialEvent;
/// Backend-specific type allowing you to configure it
type InputConfig: ?Sized;
/// Get the list of currently known Seats
fn seats(&self) -> Vec<Seat>;
/// Access the input configuration interface
fn input_config(&mut self) -> &mut Self::InputConfig;
/// Processes new events and calls the provided callback. /// Processes new events and calls the provided callback.
///
/// The callback can only assume its second argument to be usable if the event is
/// `InputEvent::ConfigChanged`.
fn dispatch_new_events<F>(&mut self, callback: F) -> Result<(), Self::EventError> fn dispatch_new_events<F>(&mut self, callback: F) -> Result<(), Self::EventError>
where where
F: FnMut(InputEvent<Self>, &mut Self::InputConfig); F: FnMut(InputEvent<Self>);
} }
/// Different events that can be generated by an input backend /// Different events that can be generated by an input backend
#[derive(Debug)] #[derive(Debug)]
pub enum InputEvent<B: InputBackend> { pub enum InputEvent<B: InputBackend> {
/// A new seat has been created /// An input device was connected
NewSeat(Seat), DeviceAdded {
/// A seat has changed /// The added device
SeatChanged(Seat), device: B::Device,
/// A seat has been removed },
SeatRemoved(Seat), /// An input device was disconnected
DeviceRemoved {
/// The removed device
device: B::Device,
},
/// A keyboard event occured /// A keyboard event occured
Keyboard { Keyboard {
/// Seat that generated the event
seat: Seat,
/// The keyboard event /// The keyboard event
event: B::KeyboardKeyEvent, event: B::KeyboardKeyEvent,
}, },
/// A relative pointer motion occured /// A relative pointer motion occured
PointerMotion { PointerMotion {
/// Seat that generated the event
seat: Seat,
/// The pointer motion event /// The pointer motion event
event: B::PointerMotionEvent, event: B::PointerMotionEvent,
}, },
/// An absolute pointer motion occures /// An absolute pointer motion occures
PointerMotionAbsolute { PointerMotionAbsolute {
/// Seat that generated the event
seat: Seat,
/// The absolute pointer motion event /// The absolute pointer motion event
event: B::PointerMotionAbsoluteEvent, event: B::PointerMotionAbsoluteEvent,
}, },
/// A pointer button was pressed or released /// A pointer button was pressed or released
PointerButton { PointerButton {
/// Seat that generated the event
seat: Seat,
/// The pointer button event /// The pointer button event
event: B::PointerButtonEvent, event: B::PointerButtonEvent,
}, },
/// A pointer axis was actionned /// A pointer axis was actionned
PointerAxis { PointerAxis {
/// Seat that generated the event
seat: Seat,
/// The pointer axis event /// The pointer axis event
event: B::PointerAxisEvent, event: B::PointerAxisEvent,
}, },
/// A new touchpoint appeared /// A new touchpoint appeared
TouchDown { TouchDown {
/// Seat that generated the event
seat: Seat,
/// The touch down event /// The touch down event
event: B::TouchDownEvent, event: B::TouchDownEvent,
}, },
/// A touchpoint moved /// A touchpoint moved
TouchMotion { TouchMotion {
/// Seat that generated the event
seat: Seat,
/// The touch motion event /// The touch motion event
event: B::TouchMotionEvent, event: B::TouchMotionEvent,
}, },
/// A touchpoint was removed /// A touchpoint was removed
TouchUp { TouchUp {
/// Seat that generated the event
seat: Seat,
/// The touch up event /// The touch up event
event: B::TouchUpEvent, event: B::TouchUpEvent,
}, },
/// A touch sequence was cancelled /// A touch sequence was cancelled
TouchCancel { TouchCancel {
/// Seat that generated the event
seat: Seat,
/// The touch cancel event /// The touch cancel event
event: B::TouchCancelEvent, event: B::TouchCancelEvent,
}, },
@ -617,8 +554,6 @@ pub enum InputEvent<B: InputBackend> {
/// A set of two events received on the same seat between two frames should /// A set of two events received on the same seat between two frames should
/// be interpreted as an atomic event. /// be interpreted as an atomic event.
TouchFrame { TouchFrame {
/// Seat that generated the event
seat: Seat,
/// The touch frame event /// The touch frame event
event: B::TouchFrameEvent, event: B::TouchFrameEvent,
}, },

View File

@ -1,8 +1,5 @@
//! Implementation of input backend trait for types provided by `libinput` //! Implementation of input backend trait for types provided by `libinput`
mod helpers;
use helpers::{on_device_event, on_keyboard_event, on_pointer_event, on_touch_event};
use crate::backend::input::{self as backend, Axis, InputBackend, InputEvent}; use crate::backend::input::{self as backend, Axis, InputBackend, InputEvent};
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
use crate::{ use crate::{
@ -15,7 +12,6 @@ use input::event;
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
use std::path::Path; use std::path::Path;
use std::{ use std::{
collections::hash_map::HashMap,
io::Error as IoError, io::Error as IoError,
os::unix::io::{AsRawFd, RawFd}, os::unix::io::{AsRawFd, RawFd},
}; };
@ -37,8 +33,6 @@ const INPUT_MAJOR: u32 = 13;
#[derive(Debug)] #[derive(Debug)]
pub struct LibinputInputBackend { pub struct LibinputInputBackend {
context: libinput::Libinput, context: libinput::Libinput,
config: LibinputConfig,
seats: HashMap<libinput::Seat, backend::Seat>,
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
links: Vec<SignalToken>, links: Vec<SignalToken>,
logger: ::slog::Logger, logger: ::slog::Logger,
@ -55,8 +49,6 @@ impl LibinputInputBackend {
info!(log, "Initializing a libinput backend"); info!(log, "Initializing a libinput backend");
LibinputInputBackend { LibinputInputBackend {
context, context,
config: LibinputConfig { devices: Vec::new() },
seats: HashMap::new(),
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
links: Vec::new(), links: Vec::new(),
logger: log, logger: log,
@ -87,13 +79,45 @@ impl Linkable<SessionSignal> for LibinputInputBackend {
} }
} }
impl backend::Event for event::keyboard::KeyboardKeyEvent { impl backend::Device for libinput::Device {
fn time(&self) -> u32 { fn id(&self) -> String {
event::keyboard::KeyboardEventTrait::time(self) self.sysname().into()
}
fn name(&self) -> String {
self.name().into()
}
fn has_capability(&self, capability: backend::DeviceCapability) -> bool {
libinput::Device::has_capability(self, capability.into())
} }
} }
impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent { impl From<backend::DeviceCapability> for libinput::DeviceCapability {
fn from(other: backend::DeviceCapability) -> libinput::DeviceCapability {
match other {
backend::DeviceCapability::Gesture => libinput::DeviceCapability::Gesture,
backend::DeviceCapability::Keyboard => libinput::DeviceCapability::Keyboard,
backend::DeviceCapability::Pointer => libinput::DeviceCapability::Pointer,
backend::DeviceCapability::Switch => libinput::DeviceCapability::Switch,
backend::DeviceCapability::TabletPad => libinput::DeviceCapability::TabletPad,
backend::DeviceCapability::TabletTool => libinput::DeviceCapability::TabletTool,
backend::DeviceCapability::Touch => libinput::DeviceCapability::Touch,
}
}
}
impl backend::Event<LibinputInputBackend> for event::keyboard::KeyboardKeyEvent {
fn time(&self) -> u32 {
event::keyboard::KeyboardEventTrait::time(self)
}
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
}
impl backend::KeyboardKeyEvent<LibinputInputBackend> for event::keyboard::KeyboardKeyEvent {
fn key_code(&self) -> u32 { fn key_code(&self) -> u32 {
use input::event::keyboard::KeyboardEventTrait; use input::event::keyboard::KeyboardEventTrait;
self.key() self.key()
@ -109,13 +133,17 @@ impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent {
} }
} }
impl<'a> backend::Event for event::pointer::PointerAxisEvent { impl<'a> backend::Event<LibinputInputBackend> for event::pointer::PointerAxisEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::pointer::PointerEventTrait::time(self) event::pointer::PointerEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::PointerAxisEvent for event::pointer::PointerAxisEvent { impl backend::PointerAxisEvent<LibinputInputBackend> for event::pointer::PointerAxisEvent {
fn amount(&self, axis: Axis) -> Option<f64> { fn amount(&self, axis: Axis) -> Option<f64> {
Some(self.axis_value(axis.into())) Some(self.axis_value(axis.into()))
} }
@ -129,13 +157,17 @@ impl backend::PointerAxisEvent for event::pointer::PointerAxisEvent {
} }
} }
impl backend::Event for event::pointer::PointerButtonEvent { impl backend::Event<LibinputInputBackend> for event::pointer::PointerButtonEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::pointer::PointerEventTrait::time(self) event::pointer::PointerEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::PointerButtonEvent for event::pointer::PointerButtonEvent { impl backend::PointerButtonEvent<LibinputInputBackend> for event::pointer::PointerButtonEvent {
fn button(&self) -> backend::MouseButton { fn button(&self) -> backend::MouseButton {
match self.button() { match self.button() {
0x110 => backend::MouseButton::Left, 0x110 => backend::MouseButton::Left,
@ -150,13 +182,17 @@ impl backend::PointerButtonEvent for event::pointer::PointerButtonEvent {
} }
} }
impl backend::Event for event::pointer::PointerMotionEvent { impl backend::Event<LibinputInputBackend> for event::pointer::PointerMotionEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::pointer::PointerEventTrait::time(self) event::pointer::PointerEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent { impl backend::PointerMotionEvent<LibinputInputBackend> for event::pointer::PointerMotionEvent {
fn delta_x(&self) -> f64 { fn delta_x(&self) -> f64 {
self.dx() self.dx()
} }
@ -165,13 +201,19 @@ impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent {
} }
} }
impl backend::Event for event::pointer::PointerMotionAbsoluteEvent { impl backend::Event<LibinputInputBackend> for event::pointer::PointerMotionAbsoluteEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::pointer::PointerEventTrait::time(self) event::pointer::PointerEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::PointerMotionAbsoluteEvent for event::pointer::PointerMotionAbsoluteEvent { impl backend::PointerMotionAbsoluteEvent<LibinputInputBackend>
for event::pointer::PointerMotionAbsoluteEvent
{
fn x(&self) -> f64 { fn x(&self) -> f64 {
self.absolute_x() self.absolute_x()
} }
@ -189,13 +231,17 @@ impl backend::PointerMotionAbsoluteEvent for event::pointer::PointerMotionAbsolu
} }
} }
impl backend::Event for event::touch::TouchDownEvent { impl backend::Event<LibinputInputBackend> for event::touch::TouchDownEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::touch::TouchEventTrait::time(self) event::touch::TouchEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::TouchDownEvent for event::touch::TouchDownEvent { impl backend::TouchDownEvent<LibinputInputBackend> for event::touch::TouchDownEvent {
fn slot(&self) -> Option<backend::TouchSlot> { fn slot(&self) -> Option<backend::TouchSlot> {
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
} }
@ -217,13 +263,17 @@ impl backend::TouchDownEvent for event::touch::TouchDownEvent {
} }
} }
impl backend::Event for event::touch::TouchMotionEvent { impl backend::Event<LibinputInputBackend> for event::touch::TouchMotionEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::touch::TouchEventTrait::time(self) event::touch::TouchEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::TouchMotionEvent for event::touch::TouchMotionEvent { impl backend::TouchMotionEvent<LibinputInputBackend> for event::touch::TouchMotionEvent {
fn slot(&self) -> Option<backend::TouchSlot> { fn slot(&self) -> Option<backend::TouchSlot> {
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
} }
@ -245,66 +295,54 @@ impl backend::TouchMotionEvent for event::touch::TouchMotionEvent {
} }
} }
impl backend::Event for event::touch::TouchUpEvent { impl backend::Event<LibinputInputBackend> for event::touch::TouchUpEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::touch::TouchEventTrait::time(self) event::touch::TouchEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::TouchUpEvent for event::touch::TouchUpEvent { impl backend::TouchUpEvent<LibinputInputBackend> for event::touch::TouchUpEvent {
fn slot(&self) -> Option<backend::TouchSlot> { fn slot(&self) -> Option<backend::TouchSlot> {
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
} }
} }
impl backend::Event for event::touch::TouchCancelEvent { impl backend::Event<LibinputInputBackend> for event::touch::TouchCancelEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::touch::TouchEventTrait::time(self) event::touch::TouchEventTrait::time(self)
} }
fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
}
} }
impl backend::TouchCancelEvent for event::touch::TouchCancelEvent { impl backend::TouchCancelEvent<LibinputInputBackend> for event::touch::TouchCancelEvent {
fn slot(&self) -> Option<backend::TouchSlot> { fn slot(&self) -> Option<backend::TouchSlot> {
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
} }
} }
impl backend::Event for event::touch::TouchFrameEvent { impl backend::Event<LibinputInputBackend> for event::touch::TouchFrameEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
event::touch::TouchEventTrait::time(self) event::touch::TouchEventTrait::time(self)
} }
}
impl backend::TouchFrameEvent for event::touch::TouchFrameEvent {} fn device(&self) -> libinput::Device {
event::EventTrait::device(self)
/// Special events generated by Libinput
#[derive(Debug)]
pub enum LibinputEvent {
/// A new device was plugged in
NewDevice(libinput::Device),
/// A device was plugged out
RemovedDevice(libinput::Device),
}
/// Configuration handle for libinput
///
/// This type allows you to access the list of know devices to configure them
/// if relevant
#[derive(Debug)]
pub struct LibinputConfig {
devices: Vec<libinput::Device>,
}
impl LibinputConfig {
/// Access the list of current devices
pub fn devices(&mut self) -> &mut [libinput::Device] {
&mut self.devices
} }
} }
impl backend::TouchFrameEvent<LibinputInputBackend> for event::touch::TouchFrameEvent {}
impl InputBackend for LibinputInputBackend { impl InputBackend for LibinputInputBackend {
type EventError = IoError; type EventError = IoError;
type Device = libinput::Device;
type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent; type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent;
type PointerAxisEvent = event::pointer::PointerAxisEvent; type PointerAxisEvent = event::pointer::PointerAxisEvent;
type PointerButtonEvent = event::pointer::PointerButtonEvent; type PointerButtonEvent = event::pointer::PointerButtonEvent;
@ -316,61 +354,70 @@ impl InputBackend for LibinputInputBackend {
type TouchCancelEvent = event::touch::TouchCancelEvent; type TouchCancelEvent = event::touch::TouchCancelEvent;
type TouchFrameEvent = event::touch::TouchFrameEvent; type TouchFrameEvent = event::touch::TouchFrameEvent;
type SpecialEvent = LibinputEvent; type SpecialEvent = backend::UnusedEvent;
type InputConfig = LibinputConfig;
fn seats(&self) -> Vec<backend::Seat> {
self.seats.values().cloned().collect()
}
fn input_config(&mut self) -> &mut Self::InputConfig {
&mut self.config
}
fn dispatch_new_events<F>(&mut self, mut callback: F) -> Result<(), IoError> fn dispatch_new_events<F>(&mut self, mut callback: F) -> Result<(), IoError>
where where
F: FnMut(InputEvent<Self>, &mut LibinputConfig), F: FnMut(InputEvent<Self>),
{ {
self.context.dispatch()?; self.context.dispatch()?;
for event in &mut self.context { for event in &mut self.context {
match event { match event {
libinput::Event::Device(device_event) => { libinput::Event::Device(device_event) => match device_event {
on_device_event( event::DeviceEvent::Added(device_added_event) => {
&mut callback, let added = event::EventTrait::device(&device_added_event);
&mut self.seats,
&mut self.config, info!(self.logger, "New device {:?}", added.sysname(),);
device_event,
&self.logger, callback(InputEvent::DeviceAdded { device: added });
);
} }
libinput::Event::Touch(touch_event) => { event::DeviceEvent::Removed(device_removed_event) => {
on_touch_event( let removed = event::EventTrait::device(&device_removed_event);
&mut callback,
&self.seats, info!(self.logger, "Removed device {:?}", removed.sysname(),);
&mut self.config,
touch_event, callback(InputEvent::DeviceRemoved { device: removed });
&self.logger,
);
} }
libinput::Event::Keyboard(keyboard_event) => { },
on_keyboard_event( libinput::Event::Touch(touch_event) => match touch_event {
&mut callback, event::TouchEvent::Down(down_event) => {
&self.seats, callback(InputEvent::TouchDown { event: down_event });
&mut self.config,
keyboard_event,
&self.logger,
);
} }
libinput::Event::Pointer(pointer_event) => { event::TouchEvent::Motion(motion_event) => {
on_pointer_event( callback(InputEvent::TouchMotion { event: motion_event });
&mut callback,
&self.seats,
&mut self.config,
pointer_event,
&self.logger,
);
} }
event::TouchEvent::Up(up_event) => {
callback(InputEvent::TouchUp { event: up_event });
}
event::TouchEvent::Cancel(cancel_event) => {
callback(InputEvent::TouchCancel { event: cancel_event });
}
event::TouchEvent::Frame(frame_event) => {
callback(InputEvent::TouchFrame { event: frame_event });
}
},
libinput::Event::Keyboard(keyboard_event) => match keyboard_event {
event::KeyboardEvent::Key(key_event) => {
callback(InputEvent::Keyboard { event: key_event });
}
},
libinput::Event::Pointer(pointer_event) => match pointer_event {
event::PointerEvent::Motion(motion_event) => {
callback(InputEvent::PointerMotion { event: motion_event });
}
event::PointerEvent::MotionAbsolute(motion_abs_event) => {
callback(InputEvent::PointerMotionAbsolute {
event: motion_abs_event,
});
}
event::PointerEvent::Axis(axis_event) => {
callback(InputEvent::PointerAxis { event: axis_event });
}
event::PointerEvent::Button(button_event) => {
callback(InputEvent::PointerButton { event: button_event });
}
},
_ => {} //FIXME: What to do with the rest. _ => {} //FIXME: What to do with the rest.
} }
} }
@ -460,14 +507,14 @@ impl AsRawFd for LibinputInputBackend {
impl EventSource for LibinputInputBackend { impl EventSource for LibinputInputBackend {
type Event = InputEvent<LibinputInputBackend>; type Event = InputEvent<LibinputInputBackend>;
type Metadata = LibinputConfig; type Metadata = ();
type Ret = (); type Ret = ();
fn process_events<F>(&mut self, _: Readiness, _: Token, callback: F) -> std::io::Result<()> fn process_events<F>(&mut self, _: Readiness, _: Token, mut callback: F) -> std::io::Result<()>
where where
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, F: FnMut(Self::Event, &mut ()) -> Self::Ret,
{ {
self.dispatch_new_events(callback) self.dispatch_new_events(|event| callback(event, &mut ()))
} }
fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {

View File

@ -1,279 +0,0 @@
use crate::backend::input::{self as backend, InputEvent};
use input as libinput;
use input::event::{
device::DeviceEvent, keyboard::KeyboardEvent, pointer::PointerEvent, touch::TouchEvent, EventTrait,
};
use slog::Logger;
use super::{LibinputConfig, LibinputEvent, LibinputInputBackend};
use std::{
collections::hash_map::{DefaultHasher, Entry, HashMap},
hash::{Hash, Hasher},
};
use slog::{info, warn};
#[inline(always)]
pub fn on_device_event<F>(
callback: &mut F,
seats: &mut HashMap<libinput::Seat, backend::Seat>,
config: &mut LibinputConfig,
event: DeviceEvent,
logger: &Logger,
) where
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{
match event {
DeviceEvent::Added(device_added_event) => {
let added = device_added_event.device();
let new_caps = backend::SeatCapabilities {
pointer: added.has_capability(libinput::DeviceCapability::Pointer),
keyboard: added.has_capability(libinput::DeviceCapability::Keyboard),
touch: added.has_capability(libinput::DeviceCapability::Touch),
};
let device_seat = added.seat();
info!(
logger,
"New device {:?} on seat {:?}",
added.sysname(),
device_seat.logical_name()
);
config.devices.push(added.clone());
match seats.entry(device_seat.clone()) {
Entry::Occupied(mut seat_entry) => {
let old_seat = seat_entry.get_mut();
{
let caps = old_seat.capabilities_mut();
caps.pointer = new_caps.pointer || caps.pointer;
caps.keyboard = new_caps.keyboard || caps.keyboard;
caps.touch = new_caps.touch || caps.touch;
}
callback(InputEvent::SeatChanged(old_seat.clone()), config);
}
Entry::Vacant(seat_entry) => {
let mut hasher = DefaultHasher::default();
seat_entry.key().hash(&mut hasher);
let seat = seat_entry.insert(backend::Seat::new(
hasher.finish(),
format!("{}:{}", device_seat.physical_name(), device_seat.logical_name()),
new_caps,
));
callback(InputEvent::NewSeat(seat.clone()), config);
}
}
callback(InputEvent::Special(LibinputEvent::NewDevice(added)), config);
}
DeviceEvent::Removed(device_removed_event) => {
let removed = device_removed_event.device();
// remove device
config.devices.retain(|dev| *dev != removed);
let device_seat = removed.seat();
info!(
logger,
"Removed device {:?} on seat {:?}",
removed.sysname(),
device_seat.logical_name()
);
// update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`.
if let Some(seat) = seats.get_mut(&device_seat) {
let caps = seat.capabilities_mut();
caps.pointer = config
.devices
.iter()
.filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Pointer));
caps.keyboard = config
.devices
.iter()
.filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Keyboard));
caps.touch = config
.devices
.iter()
.filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Touch));
} else {
warn!(logger, "Seat changed that was never created");
return;
}
// check if the seat has any other devices
if !config.devices.iter().any(|x| x.seat() == device_seat) {
// it has not, lets destroy it
if let Some(seat) = seats.remove(&device_seat) {
info!(
logger,
"Removing seat {} which no longer has any device",
device_seat.logical_name()
);
callback(InputEvent::SeatRemoved(seat), config);
} else {
warn!(logger, "Seat destroyed that was never created");
return;
}
// it has, notify about updates
} else if let Some(seat) = seats.get(&device_seat) {
callback(InputEvent::SeatChanged(seat.clone()), config);
} else {
warn!(logger, "Seat changed that was never created");
return;
}
callback(InputEvent::Special(LibinputEvent::RemovedDevice(removed)), config);
}
}
}
#[inline(always)]
pub fn on_touch_event<F>(
callback: &mut F,
seats: &HashMap<libinput::Seat, backend::Seat>,
config: &mut LibinputConfig,
event: TouchEvent,
logger: &Logger,
) where
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{
let device_seat = event.device().seat();
if let Some(seat) = seats.get(&device_seat).cloned() {
match event {
TouchEvent::Down(down_event) => {
callback(
InputEvent::TouchDown {
seat,
event: down_event,
},
config,
);
}
TouchEvent::Motion(motion_event) => {
callback(
InputEvent::TouchMotion {
seat,
event: motion_event,
},
config,
);
}
TouchEvent::Up(up_event) => {
callback(
InputEvent::TouchUp {
seat,
event: up_event,
},
config,
);
}
TouchEvent::Cancel(cancel_event) => {
callback(
InputEvent::TouchCancel {
seat,
event: cancel_event,
},
config,
);
}
TouchEvent::Frame(frame_event) => {
callback(
InputEvent::TouchFrame {
seat,
event: frame_event,
},
config,
);
}
}
} else {
warn!(logger, "Received touch event of non existing Seat");
}
}
#[inline(always)]
pub fn on_keyboard_event<F>(
callback: &mut F,
seats: &HashMap<libinput::Seat, backend::Seat>,
config: &mut LibinputConfig,
event: KeyboardEvent,
logger: &Logger,
) where
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{
match event {
KeyboardEvent::Key(key_event) => {
let device_seat = key_event.device().seat();
if let Some(seat) = seats.get(&device_seat).cloned() {
callback(
InputEvent::Keyboard {
seat,
event: key_event,
},
config,
);
} else {
warn!(logger, "Received key event of non existing Seat");
}
}
}
}
#[inline(always)]
pub fn on_pointer_event<F>(
callback: &mut F,
seats: &HashMap<libinput::Seat, backend::Seat>,
config: &mut LibinputConfig,
event: PointerEvent,
logger: &Logger,
) where
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{
let device_seat = event.device().seat();
if let Some(seat) = seats.get(&device_seat).cloned() {
match event {
PointerEvent::Motion(motion_event) => {
callback(
InputEvent::PointerMotion {
seat,
event: motion_event,
},
config,
);
}
PointerEvent::MotionAbsolute(motion_abs_event) => {
callback(
InputEvent::PointerMotionAbsolute {
seat,
event: motion_abs_event,
},
config,
);
}
PointerEvent::Axis(axis_event) => {
callback(
InputEvent::PointerAxis {
seat,
event: axis_event,
},
config,
);
}
PointerEvent::Button(button_event) => {
callback(
InputEvent::PointerButton {
seat,
event: button_event,
},
config,
);
}
}
} else {
warn!(logger, "Received pointer event of non existing Seat");
}
}

View File

@ -4,10 +4,10 @@ use crate::backend::egl::display::EGLDisplay;
use crate::backend::{ use crate::backend::{
egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError}, egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError},
input::{ input::{
Axis, AxisSource, Event as BackendEvent, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, Axis, AxisSource, Device, DeviceCapability, Event as BackendEvent, InputBackend, InputEvent,
MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, KeyState, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent, PointerMotionAbsoluteEvent, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot,
UnusedEvent, TouchUpEvent, UnusedEvent,
}, },
renderer::{ renderer::{
gles2::{Gles2Error, Gles2Frame, Gles2Renderer}, gles2::{Gles2Error, Gles2Frame, Gles2Renderer},
@ -77,8 +77,8 @@ pub struct WinitInputBackend {
events_loop: EventLoop<()>, events_loop: EventLoop<()>,
time: Instant, time: Instant,
key_counter: u32, key_counter: u32,
seat: Seat,
logger: ::slog::Logger, logger: ::slog::Logger,
initialized: bool,
size: Rc<RefCell<WindowSize>>, size: Rc<RefCell<WindowSize>>,
} }
@ -200,15 +200,7 @@ where
egl, egl,
time: Instant::now(), time: Instant::now(),
key_counter: 0, key_counter: 0,
seat: Seat::new( initialized: false,
0,
"winit",
SeatCapabilities {
pointer: true,
keyboard: true,
touch: true,
},
),
logger: log.new(o!("smithay_winit_component" => "input")), logger: log.new(o!("smithay_winit_component" => "input")),
size, size,
}, },
@ -268,6 +260,27 @@ impl WinitGraphicsBackend {
} }
} }
/// Virtual input device used by the backend to associate input events
#[derive(PartialEq, Eq, Hash)]
pub struct WinitVirtualDevice;
impl Device for WinitVirtualDevice {
fn id(&self) -> String {
String::from("winit")
}
fn name(&self) -> String {
String::from("winit virtual input")
}
fn has_capability(&self, capability: DeviceCapability) -> bool {
matches!(
capability,
DeviceCapability::Keyboard | DeviceCapability::Pointer | DeviceCapability::Touch
)
}
}
/// Errors that may happen when driving the event loop of [`WinitInputBackend`] /// Errors that may happen when driving the event loop of [`WinitInputBackend`]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
pub enum WinitInputError { pub enum WinitInputError {
@ -287,13 +300,17 @@ pub struct WinitKeyboardInputEvent {
state: ElementState, state: ElementState,
} }
impl BackendEvent for WinitKeyboardInputEvent { impl BackendEvent<WinitInputBackend> for WinitKeyboardInputEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl KeyboardKeyEvent for WinitKeyboardInputEvent { impl KeyboardKeyEvent<WinitInputBackend> for WinitKeyboardInputEvent {
fn key_code(&self) -> u32 { fn key_code(&self) -> u32 {
self.key self.key
} }
@ -315,13 +332,17 @@ pub struct WinitMouseMovedEvent {
logical_position: LogicalPosition<f64>, logical_position: LogicalPosition<f64>,
} }
impl BackendEvent for WinitMouseMovedEvent { impl BackendEvent<WinitInputBackend> for WinitMouseMovedEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl PointerMotionAbsoluteEvent for WinitMouseMovedEvent { impl PointerMotionAbsoluteEvent<WinitInputBackend> for WinitMouseMovedEvent {
// TODO: maybe use {Logical, Physical}Position from winit? // TODO: maybe use {Logical, Physical}Position from winit?
fn x(&self) -> f64 { fn x(&self) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
@ -353,13 +374,17 @@ pub struct WinitMouseWheelEvent {
delta: MouseScrollDelta, delta: MouseScrollDelta,
} }
impl BackendEvent for WinitMouseWheelEvent { impl BackendEvent<WinitInputBackend> for WinitMouseWheelEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl PointerAxisEvent for WinitMouseWheelEvent { impl PointerAxisEvent<WinitInputBackend> for WinitMouseWheelEvent {
fn source(&self) -> AxisSource { fn source(&self) -> AxisSource {
match self.delta { match self.delta {
MouseScrollDelta::LineDelta(_, _) => AxisSource::Wheel, MouseScrollDelta::LineDelta(_, _) => AxisSource::Wheel,
@ -392,13 +417,17 @@ pub struct WinitMouseInputEvent {
state: ElementState, state: ElementState,
} }
impl BackendEvent for WinitMouseInputEvent { impl BackendEvent<WinitInputBackend> for WinitMouseInputEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl PointerButtonEvent for WinitMouseInputEvent { impl PointerButtonEvent<WinitInputBackend> for WinitMouseInputEvent {
fn button(&self) -> MouseButton { fn button(&self) -> MouseButton {
self.button.into() self.button.into()
} }
@ -417,13 +446,17 @@ pub struct WinitTouchStartedEvent {
id: u64, id: u64,
} }
impl BackendEvent for WinitTouchStartedEvent { impl BackendEvent<WinitInputBackend> for WinitTouchStartedEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl TouchDownEvent for WinitTouchStartedEvent { impl TouchDownEvent<WinitInputBackend> for WinitTouchStartedEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
Some(TouchSlot::new(self.id)) Some(TouchSlot::new(self.id))
} }
@ -460,13 +493,17 @@ pub struct WinitTouchMovedEvent {
id: u64, id: u64,
} }
impl BackendEvent for WinitTouchMovedEvent { impl BackendEvent<WinitInputBackend> for WinitTouchMovedEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl TouchMotionEvent for WinitTouchMovedEvent { impl TouchMotionEvent<WinitInputBackend> for WinitTouchMovedEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
Some(TouchSlot::new(self.id)) Some(TouchSlot::new(self.id))
} }
@ -501,13 +538,17 @@ pub struct WinitTouchEndedEvent {
id: u64, id: u64,
} }
impl BackendEvent for WinitTouchEndedEvent { impl BackendEvent<WinitInputBackend> for WinitTouchEndedEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl TouchUpEvent for WinitTouchEndedEvent { impl TouchUpEvent<WinitInputBackend> for WinitTouchEndedEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
Some(TouchSlot::new(self.id)) Some(TouchSlot::new(self.id))
} }
@ -520,27 +561,26 @@ pub struct WinitTouchCancelledEvent {
id: u64, id: u64,
} }
impl BackendEvent for WinitTouchCancelledEvent { impl BackendEvent<WinitInputBackend> for WinitTouchCancelledEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
self.time self.time
} }
fn device(&self) -> WinitVirtualDevice {
WinitVirtualDevice
}
} }
impl TouchCancelEvent for WinitTouchCancelledEvent { impl TouchCancelEvent<WinitInputBackend> for WinitTouchCancelledEvent {
fn slot(&self) -> Option<TouchSlot> { fn slot(&self) -> Option<TouchSlot> {
Some(TouchSlot::new(self.id)) Some(TouchSlot::new(self.id))
} }
} }
/// Input config for Winit
///
/// This backend does not allow any input configuration, so this type does nothing.
#[derive(Debug)]
pub struct WinitInputConfig;
impl InputBackend for WinitInputBackend { impl InputBackend for WinitInputBackend {
type EventError = WinitInputError; type EventError = WinitInputError;
type Device = WinitVirtualDevice;
type KeyboardKeyEvent = WinitKeyboardInputEvent; type KeyboardKeyEvent = WinitKeyboardInputEvent;
type PointerAxisEvent = WinitMouseWheelEvent; type PointerAxisEvent = WinitMouseWheelEvent;
type PointerButtonEvent = WinitMouseInputEvent; type PointerButtonEvent = WinitMouseInputEvent;
@ -553,17 +593,6 @@ impl InputBackend for WinitInputBackend {
type TouchFrameEvent = UnusedEvent; type TouchFrameEvent = UnusedEvent;
type SpecialEvent = WinitEvent; type SpecialEvent = WinitEvent;
type InputConfig = WinitInputConfig;
fn seats(&self) -> Vec<Seat> {
vec![self.seat.clone()]
}
fn input_config(&mut self) -> &mut Self::InputConfig {
/// So much effort to return a useless singleton!
static mut CONFIG: WinitInputConfig = WinitInputConfig;
unsafe { &mut CONFIG }
}
/// Processes new events of the underlying event loop and calls the provided callback. /// Processes new events of the underlying event loop and calls the provided callback.
/// ///
@ -578,7 +607,7 @@ impl InputBackend for WinitInputBackend {
/// not be used anymore as well. /// not be used anymore as well.
fn dispatch_new_events<F>(&mut self, mut callback: F) -> ::std::result::Result<(), WinitInputError> fn dispatch_new_events<F>(&mut self, mut callback: F) -> ::std::result::Result<(), WinitInputError>
where where
F: FnMut(InputEvent<Self>, &mut WinitInputConfig), F: FnMut(InputEvent<Self>),
{ {
let mut closed = false; let mut closed = false;
@ -591,12 +620,17 @@ impl InputBackend for WinitInputBackend {
let closed_ptr = &mut closed; let closed_ptr = &mut closed;
let key_counter = &mut self.key_counter; let key_counter = &mut self.key_counter;
let time = &self.time; let time = &self.time;
let seat = &self.seat;
let window = &self.window; let window = &self.window;
let egl = &self.egl; let egl = &self.egl;
let logger = &self.logger; let logger = &self.logger;
let window_size = &self.size; let window_size = &self.size;
let mut callback = move |event| callback(event, &mut WinitInputConfig);
if !self.initialized {
callback(InputEvent::DeviceAdded {
device: WinitVirtualDevice,
});
self.initialized = true;
}
self.events_loop self.events_loop
.run_return(move |event, _target, control_flow| match event { .run_return(move |event, _target, control_flow| match event {
@ -651,7 +685,6 @@ impl InputBackend for WinitInputBackend {
} }
}; };
callback(InputEvent::Keyboard { callback(InputEvent::Keyboard {
seat: seat.clone(),
event: WinitKeyboardInputEvent { event: WinitKeyboardInputEvent {
time, time,
key: scancode, key: scancode,
@ -663,7 +696,6 @@ impl InputBackend for WinitInputBackend {
WindowEvent::CursorMoved { position, .. } => { WindowEvent::CursorMoved { position, .. } => {
let lpos = position.to_logical(window_size.borrow().scale_factor); let lpos = position.to_logical(window_size.borrow().scale_factor);
callback(InputEvent::PointerMotionAbsolute { callback(InputEvent::PointerMotionAbsolute {
seat: seat.clone(),
event: WinitMouseMovedEvent { event: WinitMouseMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
@ -673,14 +705,10 @@ impl InputBackend for WinitInputBackend {
} }
WindowEvent::MouseWheel { delta, .. } => { WindowEvent::MouseWheel { delta, .. } => {
let event = WinitMouseWheelEvent { time, delta }; let event = WinitMouseWheelEvent { time, delta };
callback(InputEvent::PointerAxis { callback(InputEvent::PointerAxis { event });
seat: seat.clone(),
event,
});
} }
WindowEvent::MouseInput { state, button, .. } => { WindowEvent::MouseInput { state, button, .. } => {
callback(InputEvent::PointerButton { callback(InputEvent::PointerButton {
seat: seat.clone(),
event: WinitMouseInputEvent { time, button, state }, event: WinitMouseInputEvent { time, button, state },
}); });
} }
@ -692,7 +720,6 @@ impl InputBackend for WinitInputBackend {
.. ..
}) => { }) => {
callback(InputEvent::TouchDown { callback(InputEvent::TouchDown {
seat: seat.clone(),
event: WinitTouchStartedEvent { event: WinitTouchStartedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
@ -708,7 +735,6 @@ impl InputBackend for WinitInputBackend {
.. ..
}) => { }) => {
callback(InputEvent::TouchMotion { callback(InputEvent::TouchMotion {
seat: seat.clone(),
event: WinitTouchMovedEvent { event: WinitTouchMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
@ -725,7 +751,6 @@ impl InputBackend for WinitInputBackend {
.. ..
}) => { }) => {
callback(InputEvent::TouchMotion { callback(InputEvent::TouchMotion {
seat: seat.clone(),
event: WinitTouchMovedEvent { event: WinitTouchMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
@ -734,7 +759,6 @@ impl InputBackend for WinitInputBackend {
}, },
}); });
callback(InputEvent::TouchUp { callback(InputEvent::TouchUp {
seat: seat.clone(),
event: WinitTouchEndedEvent { time, id }, event: WinitTouchEndedEvent { time, id },
}) })
} }
@ -745,11 +769,13 @@ impl InputBackend for WinitInputBackend {
.. ..
}) => { }) => {
callback(InputEvent::TouchCancel { callback(InputEvent::TouchCancel {
seat: seat.clone(),
event: WinitTouchCancelledEvent { time, id }, event: WinitTouchCancelledEvent { time, id },
}); });
} }
WindowEvent::CloseRequested | WindowEvent::Destroyed => { WindowEvent::CloseRequested | WindowEvent::Destroyed => {
callback(InputEvent::DeviceRemoved {
device: WinitVirtualDevice,
});
warn!(logger, "Window closed"); warn!(logger, "Window closed");
*closed_ptr = true; *closed_ptr = true;
} }