Rework `InputBackend` abstractions to track individual devices
Removes the notion of Seats from `InputBackend` and replaces it with `DeviceAdded` and `DeviceRemoved` events allowing compositors to descriminate between single devices. A new abstraction to model multiple seats on a single input backend may be be added separately at a later time.
This commit is contained in:
parent
736eb11cd5
commit
50741bc7bb
|
@ -109,7 +109,7 @@ pub fn run_winit(
|
|||
|
||||
while state.running.load(Ordering::SeqCst) {
|
||||
if input
|
||||
.dispatch_new_events(|event, _| state.process_input_event(event))
|
||||
.dispatch_new_events(|event| state.process_input_event(event))
|
||||
.is_err()
|
||||
{
|
||||
state.running.store(false, Ordering::SeqCst);
|
||||
|
|
|
@ -2,78 +2,33 @@
|
|||
|
||||
use std::error::Error;
|
||||
|
||||
/// A seat describes a group of input devices and at least one
|
||||
/// graphics device belonging together.
|
||||
/// Trait for generic functions every input device does provide
|
||||
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
|
||||
/// separated users, all with their own focus, input and cursor available.
|
||||
///
|
||||
/// Seats referring to the same internal id will always be equal and result in the same
|
||||
/// hash, but capabilities of cloned and copied [`Seat`]s will not be updated by smithay.
|
||||
/// Always refer to the [`Seat`] given by a callback for up-to-date information. You may
|
||||
/// use this to calculate the differences since the last callback.
|
||||
#[derive(Debug, Clone, Eq)]
|
||||
pub struct Seat {
|
||||
id: u64,
|
||||
name: String,
|
||||
capabilities: SeatCapabilities,
|
||||
/// Note: This means ids may be re-used by the backend for later devices.
|
||||
fn id(&self) -> String;
|
||||
/// Human-readable name of the device
|
||||
fn name(&self) -> String;
|
||||
/// Test if this device has a specific capability
|
||||
fn has_capability(&self, capability: DeviceCapability) -> bool;
|
||||
}
|
||||
|
||||
impl Seat {
|
||||
#[cfg(any(feature = "backend_winit", feature = "backend_libinput"))]
|
||||
pub(crate) fn new<S: std::string::ToString>(id: u64, name: S, capabilities: SeatCapabilities) -> Seat {
|
||||
Seat {
|
||||
id,
|
||||
name: name.to_string(),
|
||||
capabilities,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "backend_libinput")]
|
||||
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,
|
||||
/// Set of input types a device may provide
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(missing_docs)] // self explainatory
|
||||
pub enum DeviceCapability {
|
||||
Keyboard,
|
||||
Pointer,
|
||||
Touch,
|
||||
TabletTool,
|
||||
TabletPad,
|
||||
Gesture,
|
||||
Switch,
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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.
|
||||
// - Make stronger time guarantees, if possible
|
||||
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.
|
||||
|
@ -92,10 +49,14 @@ pub trait Event {
|
|||
#[derive(Debug)]
|
||||
pub enum UnusedEvent {}
|
||||
|
||||
impl Event for UnusedEvent {
|
||||
impl<B: InputBackend> Event<B> for UnusedEvent {
|
||||
fn time(&self) -> u32 {
|
||||
match *self {}
|
||||
}
|
||||
|
||||
fn device(&self) -> B::Device {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
/// State of key on a keyboard. Either pressed or released
|
||||
|
@ -108,7 +69,7 @@ pub enum KeyState {
|
|||
}
|
||||
|
||||
/// 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`
|
||||
fn key_code(&self) -> u32;
|
||||
/// State of the key
|
||||
|
@ -117,7 +78,7 @@ pub trait KeyboardKeyEvent: Event {
|
|||
fn count(&self) -> u32;
|
||||
}
|
||||
|
||||
impl KeyboardKeyEvent for UnusedEvent {
|
||||
impl<B: InputBackend> KeyboardKeyEvent<B> for UnusedEvent {
|
||||
fn key_code(&self) -> u32 {
|
||||
match *self {}
|
||||
}
|
||||
|
@ -154,14 +115,14 @@ pub enum MouseButtonState {
|
|||
}
|
||||
|
||||
/// 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
|
||||
fn button(&self) -> MouseButton;
|
||||
/// State of the button
|
||||
fn state(&self) -> MouseButtonState;
|
||||
}
|
||||
|
||||
impl PointerButtonEvent for UnusedEvent {
|
||||
impl<B: InputBackend> PointerButtonEvent<B> for UnusedEvent {
|
||||
fn button(&self) -> MouseButton {
|
||||
match *self {}
|
||||
}
|
||||
|
@ -214,7 +175,7 @@ pub enum AxisSource {
|
|||
}
|
||||
|
||||
/// 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`].
|
||||
///
|
||||
/// 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;
|
||||
}
|
||||
|
||||
impl PointerAxisEvent for UnusedEvent {
|
||||
impl<B: InputBackend> PointerAxisEvent<B> for UnusedEvent {
|
||||
fn amount(&self, _axis: Axis) -> Option<f64> {
|
||||
match *self {}
|
||||
}
|
||||
|
@ -244,7 +205,7 @@ impl PointerAxisEvent for UnusedEvent {
|
|||
}
|
||||
|
||||
/// 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
|
||||
fn delta(&self) -> (f64, f64) {
|
||||
(self.delta_x(), self.delta_y())
|
||||
|
@ -256,7 +217,7 @@ pub trait PointerMotionEvent: Event {
|
|||
fn delta_y(&self) -> f64;
|
||||
}
|
||||
|
||||
impl PointerMotionEvent for UnusedEvent {
|
||||
impl<B: InputBackend> PointerMotionEvent<B> for UnusedEvent {
|
||||
fn delta_x(&self) -> f64 {
|
||||
match *self {}
|
||||
}
|
||||
|
@ -267,7 +228,7 @@ impl PointerMotionEvent for UnusedEvent {
|
|||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// The format is defined by the backend implementation.
|
||||
|
@ -303,7 +264,7 @@ pub trait PointerMotionAbsoluteEvent: Event {
|
|||
fn y_transformed(&self, height: u32) -> f64;
|
||||
}
|
||||
|
||||
impl PointerMotionAbsoluteEvent for UnusedEvent {
|
||||
impl<B: InputBackend> PointerMotionAbsoluteEvent<B> for UnusedEvent {
|
||||
fn x(&self) -> f64 {
|
||||
match *self {}
|
||||
}
|
||||
|
@ -339,7 +300,7 @@ impl TouchSlot {
|
|||
}
|
||||
|
||||
/// 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
|
||||
fn slot(&self) -> Option<TouchSlot>;
|
||||
|
||||
|
@ -378,7 +339,7 @@ pub trait TouchDownEvent: Event {
|
|||
fn y_transformed(&self, height: u32) -> f64;
|
||||
}
|
||||
|
||||
impl TouchDownEvent for UnusedEvent {
|
||||
impl<B: InputBackend> TouchDownEvent<B> for UnusedEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
match *self {}
|
||||
}
|
||||
|
@ -401,7 +362,7 @@ impl TouchDownEvent for UnusedEvent {
|
|||
}
|
||||
|
||||
/// 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
|
||||
fn slot(&self) -> Option<TouchSlot>;
|
||||
|
||||
|
@ -440,7 +401,7 @@ pub trait TouchMotionEvent: Event {
|
|||
fn y_transformed(&self, height: u32) -> f64;
|
||||
}
|
||||
|
||||
impl TouchMotionEvent for UnusedEvent {
|
||||
impl<B: InputBackend> TouchMotionEvent<B> for UnusedEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
match *self {}
|
||||
}
|
||||
|
@ -463,33 +424,33 @@ impl TouchMotionEvent for UnusedEvent {
|
|||
}
|
||||
|
||||
/// Trait for touch events finishing.
|
||||
pub trait TouchUpEvent: Event {
|
||||
pub trait TouchUpEvent<B: InputBackend>: Event<B> {
|
||||
/// [`TouchSlot`], if the device has multi-touch capabilities
|
||||
fn slot(&self) -> Option<TouchSlot>;
|
||||
}
|
||||
|
||||
impl TouchUpEvent for UnusedEvent {
|
||||
impl<B: InputBackend> TouchUpEvent<B> for UnusedEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
fn slot(&self) -> Option<TouchSlot>;
|
||||
}
|
||||
|
||||
impl TouchCancelEvent for UnusedEvent {
|
||||
impl<B: InputBackend> TouchCancelEvent<B> for UnusedEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// 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 EventError: Error;
|
||||
|
||||
/// Type representing input devices
|
||||
type Device: Device;
|
||||
/// Type representing keyboard events
|
||||
type KeyboardKeyEvent: KeyboardKeyEvent;
|
||||
type KeyboardKeyEvent: KeyboardKeyEvent<Self>;
|
||||
/// Type representing axis events on pointer devices
|
||||
type PointerAxisEvent: PointerAxisEvent;
|
||||
type PointerAxisEvent: PointerAxisEvent<Self>;
|
||||
/// Type representing button events on pointer devices
|
||||
type PointerButtonEvent: PointerButtonEvent;
|
||||
type PointerButtonEvent: PointerButtonEvent<Self>;
|
||||
/// Type representing motion events of pointer devices
|
||||
type PointerMotionEvent: PointerMotionEvent;
|
||||
type PointerMotionEvent: PointerMotionEvent<Self>;
|
||||
/// Type representing motion events of pointer devices
|
||||
type PointerMotionAbsoluteEvent: PointerMotionAbsoluteEvent;
|
||||
type PointerMotionAbsoluteEvent: PointerMotionAbsoluteEvent<Self>;
|
||||
/// Type representing touch events starting
|
||||
type TouchDownEvent: TouchDownEvent;
|
||||
type TouchDownEvent: TouchDownEvent<Self>;
|
||||
/// Type representing touch events ending
|
||||
type TouchUpEvent: TouchUpEvent;
|
||||
type TouchUpEvent: TouchUpEvent<Self>;
|
||||
/// Type representing touch events from moving
|
||||
type TouchMotionEvent: TouchMotionEvent;
|
||||
type TouchMotionEvent: TouchMotionEvent<Self>;
|
||||
/// Type representing cancelling of touch events
|
||||
type TouchCancelEvent: TouchCancelEvent;
|
||||
type TouchCancelEvent: TouchCancelEvent<Self>;
|
||||
/// Type representing touch frame events
|
||||
type TouchFrameEvent: TouchFrameEvent;
|
||||
type TouchFrameEvent: TouchFrameEvent<Self>;
|
||||
|
||||
/// Special events that are custom to this backend
|
||||
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.
|
||||
///
|
||||
/// 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>
|
||||
where
|
||||
F: FnMut(InputEvent<Self>, &mut Self::InputConfig);
|
||||
F: FnMut(InputEvent<Self>);
|
||||
}
|
||||
|
||||
/// Different events that can be generated by an input backend
|
||||
#[derive(Debug)]
|
||||
pub enum InputEvent<B: InputBackend> {
|
||||
/// A new seat has been created
|
||||
NewSeat(Seat),
|
||||
/// A seat has changed
|
||||
SeatChanged(Seat),
|
||||
/// A seat has been removed
|
||||
SeatRemoved(Seat),
|
||||
/// An input device was connected
|
||||
DeviceAdded {
|
||||
/// The added device
|
||||
device: B::Device,
|
||||
},
|
||||
/// An input device was disconnected
|
||||
DeviceRemoved {
|
||||
/// The removed device
|
||||
device: B::Device,
|
||||
},
|
||||
/// A keyboard event occured
|
||||
Keyboard {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The keyboard event
|
||||
event: B::KeyboardKeyEvent,
|
||||
},
|
||||
/// A relative pointer motion occured
|
||||
PointerMotion {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The pointer motion event
|
||||
event: B::PointerMotionEvent,
|
||||
},
|
||||
/// An absolute pointer motion occures
|
||||
PointerMotionAbsolute {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The absolute pointer motion event
|
||||
event: B::PointerMotionAbsoluteEvent,
|
||||
},
|
||||
/// A pointer button was pressed or released
|
||||
PointerButton {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The pointer button event
|
||||
event: B::PointerButtonEvent,
|
||||
},
|
||||
/// A pointer axis was actionned
|
||||
PointerAxis {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The pointer axis event
|
||||
event: B::PointerAxisEvent,
|
||||
},
|
||||
/// A new touchpoint appeared
|
||||
TouchDown {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The touch down event
|
||||
event: B::TouchDownEvent,
|
||||
},
|
||||
/// A touchpoint moved
|
||||
TouchMotion {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The touch motion event
|
||||
event: B::TouchMotionEvent,
|
||||
},
|
||||
/// A touchpoint was removed
|
||||
TouchUp {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The touch up event
|
||||
event: B::TouchUpEvent,
|
||||
},
|
||||
/// A touch sequence was cancelled
|
||||
TouchCancel {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The touch cancel event
|
||||
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
|
||||
/// be interpreted as an atomic event.
|
||||
TouchFrame {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The touch frame event
|
||||
event: B::TouchFrameEvent,
|
||||
},
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
//! 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};
|
||||
#[cfg(feature = "backend_session")]
|
||||
use crate::{
|
||||
|
@ -15,7 +12,6 @@ use input::event;
|
|||
#[cfg(feature = "backend_session")]
|
||||
use std::path::Path;
|
||||
use std::{
|
||||
collections::hash_map::HashMap,
|
||||
io::Error as IoError,
|
||||
os::unix::io::{AsRawFd, RawFd},
|
||||
};
|
||||
|
@ -37,8 +33,6 @@ const INPUT_MAJOR: u32 = 13;
|
|||
#[derive(Debug)]
|
||||
pub struct LibinputInputBackend {
|
||||
context: libinput::Libinput,
|
||||
config: LibinputConfig,
|
||||
seats: HashMap<libinput::Seat, backend::Seat>,
|
||||
#[cfg(feature = "backend_session")]
|
||||
links: Vec<SignalToken>,
|
||||
logger: ::slog::Logger,
|
||||
|
@ -55,8 +49,6 @@ impl LibinputInputBackend {
|
|||
info!(log, "Initializing a libinput backend");
|
||||
LibinputInputBackend {
|
||||
context,
|
||||
config: LibinputConfig { devices: Vec::new() },
|
||||
seats: HashMap::new(),
|
||||
#[cfg(feature = "backend_session")]
|
||||
links: Vec::new(),
|
||||
logger: log,
|
||||
|
@ -87,13 +79,45 @@ impl Linkable<SessionSignal> for LibinputInputBackend {
|
|||
}
|
||||
}
|
||||
|
||||
impl backend::Event for event::keyboard::KeyboardKeyEvent {
|
||||
fn time(&self) -> u32 {
|
||||
event::keyboard::KeyboardEventTrait::time(self)
|
||||
impl backend::Device for libinput::Device {
|
||||
fn id(&self) -> String {
|
||||
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 {
|
||||
use input::event::keyboard::KeyboardEventTrait;
|
||||
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 {
|
||||
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> {
|
||||
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 {
|
||||
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 {
|
||||
match self.button() {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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> {
|
||||
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 {
|
||||
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> {
|
||||
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 {
|
||||
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> {
|
||||
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 {
|
||||
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> {
|
||||
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 {
|
||||
event::touch::TouchEventTrait::time(self)
|
||||
}
|
||||
|
||||
fn device(&self) -> libinput::Device {
|
||||
event::EventTrait::device(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl backend::TouchFrameEvent for event::touch::TouchFrameEvent {}
|
||||
|
||||
/// 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 {
|
||||
type EventError = IoError;
|
||||
|
||||
type Device = libinput::Device;
|
||||
type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent;
|
||||
type PointerAxisEvent = event::pointer::PointerAxisEvent;
|
||||
type PointerButtonEvent = event::pointer::PointerButtonEvent;
|
||||
|
@ -316,61 +354,70 @@ impl InputBackend for LibinputInputBackend {
|
|||
type TouchCancelEvent = event::touch::TouchCancelEvent;
|
||||
type TouchFrameEvent = event::touch::TouchFrameEvent;
|
||||
|
||||
type SpecialEvent = LibinputEvent;
|
||||
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
|
||||
}
|
||||
type SpecialEvent = backend::UnusedEvent;
|
||||
|
||||
fn dispatch_new_events<F>(&mut self, mut callback: F) -> Result<(), IoError>
|
||||
where
|
||||
F: FnMut(InputEvent<Self>, &mut LibinputConfig),
|
||||
F: FnMut(InputEvent<Self>),
|
||||
{
|
||||
self.context.dispatch()?;
|
||||
|
||||
for event in &mut self.context {
|
||||
match event {
|
||||
libinput::Event::Device(device_event) => {
|
||||
on_device_event(
|
||||
&mut callback,
|
||||
&mut self.seats,
|
||||
&mut self.config,
|
||||
device_event,
|
||||
&self.logger,
|
||||
);
|
||||
libinput::Event::Device(device_event) => match device_event {
|
||||
event::DeviceEvent::Added(device_added_event) => {
|
||||
let added = event::EventTrait::device(&device_added_event);
|
||||
|
||||
info!(self.logger, "New device {:?}", added.sysname(),);
|
||||
|
||||
callback(InputEvent::DeviceAdded { device: added });
|
||||
}
|
||||
libinput::Event::Touch(touch_event) => {
|
||||
on_touch_event(
|
||||
&mut callback,
|
||||
&self.seats,
|
||||
&mut self.config,
|
||||
touch_event,
|
||||
&self.logger,
|
||||
);
|
||||
event::DeviceEvent::Removed(device_removed_event) => {
|
||||
let removed = event::EventTrait::device(&device_removed_event);
|
||||
|
||||
info!(self.logger, "Removed device {:?}", removed.sysname(),);
|
||||
|
||||
callback(InputEvent::DeviceRemoved { device: removed });
|
||||
}
|
||||
libinput::Event::Keyboard(keyboard_event) => {
|
||||
on_keyboard_event(
|
||||
&mut callback,
|
||||
&self.seats,
|
||||
&mut self.config,
|
||||
keyboard_event,
|
||||
&self.logger,
|
||||
);
|
||||
},
|
||||
libinput::Event::Touch(touch_event) => match touch_event {
|
||||
event::TouchEvent::Down(down_event) => {
|
||||
callback(InputEvent::TouchDown { event: down_event });
|
||||
}
|
||||
libinput::Event::Pointer(pointer_event) => {
|
||||
on_pointer_event(
|
||||
&mut callback,
|
||||
&self.seats,
|
||||
&mut self.config,
|
||||
pointer_event,
|
||||
&self.logger,
|
||||
);
|
||||
event::TouchEvent::Motion(motion_event) => {
|
||||
callback(InputEvent::TouchMotion { event: motion_event });
|
||||
}
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
@ -460,14 +507,14 @@ impl AsRawFd for LibinputInputBackend {
|
|||
|
||||
impl EventSource for LibinputInputBackend {
|
||||
type Event = InputEvent<LibinputInputBackend>;
|
||||
type Metadata = LibinputConfig;
|
||||
type Metadata = ();
|
||||
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
|
||||
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<()> {
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -4,10 +4,10 @@ use crate::backend::egl::display::EGLDisplay;
|
|||
use crate::backend::{
|
||||
egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError},
|
||||
input::{
|
||||
Axis, AxisSource, Event as BackendEvent, InputBackend, InputEvent, KeyState, KeyboardKeyEvent,
|
||||
MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent,
|
||||
Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent,
|
||||
UnusedEvent,
|
||||
Axis, AxisSource, Device, DeviceCapability, Event as BackendEvent, InputBackend, InputEvent,
|
||||
KeyState, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
|
||||
PointerMotionAbsoluteEvent, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot,
|
||||
TouchUpEvent, UnusedEvent,
|
||||
},
|
||||
renderer::{
|
||||
gles2::{Gles2Error, Gles2Frame, Gles2Renderer},
|
||||
|
@ -77,8 +77,8 @@ pub struct WinitInputBackend {
|
|||
events_loop: EventLoop<()>,
|
||||
time: Instant,
|
||||
key_counter: u32,
|
||||
seat: Seat,
|
||||
logger: ::slog::Logger,
|
||||
initialized: bool,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
}
|
||||
|
||||
|
@ -200,15 +200,7 @@ where
|
|||
egl,
|
||||
time: Instant::now(),
|
||||
key_counter: 0,
|
||||
seat: Seat::new(
|
||||
0,
|
||||
"winit",
|
||||
SeatCapabilities {
|
||||
pointer: true,
|
||||
keyboard: true,
|
||||
touch: true,
|
||||
},
|
||||
),
|
||||
initialized: false,
|
||||
logger: log.new(o!("smithay_winit_component" => "input")),
|
||||
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`]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
|
||||
pub enum WinitInputError {
|
||||
|
@ -287,13 +300,17 @@ pub struct WinitKeyboardInputEvent {
|
|||
state: ElementState,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitKeyboardInputEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitKeyboardInputEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyboardKeyEvent for WinitKeyboardInputEvent {
|
||||
impl KeyboardKeyEvent<WinitInputBackend> for WinitKeyboardInputEvent {
|
||||
fn key_code(&self) -> u32 {
|
||||
self.key
|
||||
}
|
||||
|
@ -315,13 +332,17 @@ pub struct WinitMouseMovedEvent {
|
|||
logical_position: LogicalPosition<f64>,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitMouseMovedEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitMouseMovedEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerMotionAbsoluteEvent for WinitMouseMovedEvent {
|
||||
impl PointerMotionAbsoluteEvent<WinitInputBackend> for WinitMouseMovedEvent {
|
||||
// TODO: maybe use {Logical, Physical}Position from winit?
|
||||
fn x(&self) -> f64 {
|
||||
let wsize = self.size.borrow();
|
||||
|
@ -353,13 +374,17 @@ pub struct WinitMouseWheelEvent {
|
|||
delta: MouseScrollDelta,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitMouseWheelEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitMouseWheelEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerAxisEvent for WinitMouseWheelEvent {
|
||||
impl PointerAxisEvent<WinitInputBackend> for WinitMouseWheelEvent {
|
||||
fn source(&self) -> AxisSource {
|
||||
match self.delta {
|
||||
MouseScrollDelta::LineDelta(_, _) => AxisSource::Wheel,
|
||||
|
@ -392,13 +417,17 @@ pub struct WinitMouseInputEvent {
|
|||
state: ElementState,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitMouseInputEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitMouseInputEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerButtonEvent for WinitMouseInputEvent {
|
||||
impl PointerButtonEvent<WinitInputBackend> for WinitMouseInputEvent {
|
||||
fn button(&self) -> MouseButton {
|
||||
self.button.into()
|
||||
}
|
||||
|
@ -417,13 +446,17 @@ pub struct WinitTouchStartedEvent {
|
|||
id: u64,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitTouchStartedEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitTouchStartedEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl TouchDownEvent for WinitTouchStartedEvent {
|
||||
impl TouchDownEvent<WinitInputBackend> for WinitTouchStartedEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
Some(TouchSlot::new(self.id))
|
||||
}
|
||||
|
@ -460,13 +493,17 @@ pub struct WinitTouchMovedEvent {
|
|||
id: u64,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitTouchMovedEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitTouchMovedEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl TouchMotionEvent for WinitTouchMovedEvent {
|
||||
impl TouchMotionEvent<WinitInputBackend> for WinitTouchMovedEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
Some(TouchSlot::new(self.id))
|
||||
}
|
||||
|
@ -501,13 +538,17 @@ pub struct WinitTouchEndedEvent {
|
|||
id: u64,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitTouchEndedEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitTouchEndedEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl TouchUpEvent for WinitTouchEndedEvent {
|
||||
impl TouchUpEvent<WinitInputBackend> for WinitTouchEndedEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
Some(TouchSlot::new(self.id))
|
||||
}
|
||||
|
@ -520,27 +561,26 @@ pub struct WinitTouchCancelledEvent {
|
|||
id: u64,
|
||||
}
|
||||
|
||||
impl BackendEvent for WinitTouchCancelledEvent {
|
||||
impl BackendEvent<WinitInputBackend> for WinitTouchCancelledEvent {
|
||||
fn time(&self) -> u32 {
|
||||
self.time
|
||||
}
|
||||
|
||||
fn device(&self) -> WinitVirtualDevice {
|
||||
WinitVirtualDevice
|
||||
}
|
||||
}
|
||||
|
||||
impl TouchCancelEvent for WinitTouchCancelledEvent {
|
||||
impl TouchCancelEvent<WinitInputBackend> for WinitTouchCancelledEvent {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
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 {
|
||||
type EventError = WinitInputError;
|
||||
|
||||
type Device = WinitVirtualDevice;
|
||||
type KeyboardKeyEvent = WinitKeyboardInputEvent;
|
||||
type PointerAxisEvent = WinitMouseWheelEvent;
|
||||
type PointerButtonEvent = WinitMouseInputEvent;
|
||||
|
@ -553,17 +593,6 @@ impl InputBackend for WinitInputBackend {
|
|||
type TouchFrameEvent = UnusedEvent;
|
||||
|
||||
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.
|
||||
///
|
||||
|
@ -578,7 +607,7 @@ impl InputBackend for WinitInputBackend {
|
|||
/// not be used anymore as well.
|
||||
fn dispatch_new_events<F>(&mut self, mut callback: F) -> ::std::result::Result<(), WinitInputError>
|
||||
where
|
||||
F: FnMut(InputEvent<Self>, &mut WinitInputConfig),
|
||||
F: FnMut(InputEvent<Self>),
|
||||
{
|
||||
let mut closed = false;
|
||||
|
||||
|
@ -591,12 +620,17 @@ impl InputBackend for WinitInputBackend {
|
|||
let closed_ptr = &mut closed;
|
||||
let key_counter = &mut self.key_counter;
|
||||
let time = &self.time;
|
||||
let seat = &self.seat;
|
||||
let window = &self.window;
|
||||
let egl = &self.egl;
|
||||
let logger = &self.logger;
|
||||
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
|
||||
.run_return(move |event, _target, control_flow| match event {
|
||||
|
@ -651,7 +685,6 @@ impl InputBackend for WinitInputBackend {
|
|||
}
|
||||
};
|
||||
callback(InputEvent::Keyboard {
|
||||
seat: seat.clone(),
|
||||
event: WinitKeyboardInputEvent {
|
||||
time,
|
||||
key: scancode,
|
||||
|
@ -663,7 +696,6 @@ impl InputBackend for WinitInputBackend {
|
|||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let lpos = position.to_logical(window_size.borrow().scale_factor);
|
||||
callback(InputEvent::PointerMotionAbsolute {
|
||||
seat: seat.clone(),
|
||||
event: WinitMouseMovedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
|
@ -673,14 +705,10 @@ impl InputBackend for WinitInputBackend {
|
|||
}
|
||||
WindowEvent::MouseWheel { delta, .. } => {
|
||||
let event = WinitMouseWheelEvent { time, delta };
|
||||
callback(InputEvent::PointerAxis {
|
||||
seat: seat.clone(),
|
||||
event,
|
||||
});
|
||||
callback(InputEvent::PointerAxis { event });
|
||||
}
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
callback(InputEvent::PointerButton {
|
||||
seat: seat.clone(),
|
||||
event: WinitMouseInputEvent { time, button, state },
|
||||
});
|
||||
}
|
||||
|
@ -692,7 +720,6 @@ impl InputBackend for WinitInputBackend {
|
|||
..
|
||||
}) => {
|
||||
callback(InputEvent::TouchDown {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchStartedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
|
@ -708,7 +735,6 @@ impl InputBackend for WinitInputBackend {
|
|||
..
|
||||
}) => {
|
||||
callback(InputEvent::TouchMotion {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchMovedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
|
@ -725,7 +751,6 @@ impl InputBackend for WinitInputBackend {
|
|||
..
|
||||
}) => {
|
||||
callback(InputEvent::TouchMotion {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchMovedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
|
@ -734,7 +759,6 @@ impl InputBackend for WinitInputBackend {
|
|||
},
|
||||
});
|
||||
callback(InputEvent::TouchUp {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchEndedEvent { time, id },
|
||||
})
|
||||
}
|
||||
|
@ -745,11 +769,13 @@ impl InputBackend for WinitInputBackend {
|
|||
..
|
||||
}) => {
|
||||
callback(InputEvent::TouchCancel {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchCancelledEvent { time, id },
|
||||
});
|
||||
}
|
||||
WindowEvent::CloseRequested | WindowEvent::Destroyed => {
|
||||
callback(InputEvent::DeviceRemoved {
|
||||
device: WinitVirtualDevice,
|
||||
});
|
||||
warn!(logger, "Window closed");
|
||||
*closed_ptr = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue