2017-04-14 22:23:16 +00:00
|
|
|
//! Implementation of input backend trait for types provided by `libinput`
|
|
|
|
|
2018-12-15 20:32:28 +00:00
|
|
|
use crate::backend::input::{self as backend, Axis, InputBackend};
|
2017-11-07 00:18:52 +00:00
|
|
|
#[cfg(feature = "backend_session")]
|
2018-12-15 20:32:28 +00:00
|
|
|
use crate::backend::session::{AsErrno, Session, SessionObserver};
|
2017-04-23 17:55:43 +00:00
|
|
|
use input as libinput;
|
|
|
|
use input::event;
|
2018-09-28 16:01:33 +00:00
|
|
|
|
2018-11-22 08:44:05 +00:00
|
|
|
#[cfg(feature = "backend_session")]
|
|
|
|
use std::path::Path;
|
2018-10-04 22:37:43 +00:00
|
|
|
use std::{
|
|
|
|
collections::hash_map::{DefaultHasher, Entry, HashMap},
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
io::Error as IoError,
|
2018-11-21 08:37:57 +00:00
|
|
|
os::unix::io::{AsRawFd, RawFd},
|
2018-10-04 22:37:43 +00:00
|
|
|
};
|
2018-09-24 22:30:39 +00:00
|
|
|
|
2019-02-05 16:26:09 +00:00
|
|
|
use calloop::{
|
2018-11-21 08:37:57 +00:00
|
|
|
generic::{EventedFd, Generic},
|
2018-11-17 17:01:04 +00:00
|
|
|
mio::Ready,
|
2018-11-21 09:41:55 +00:00
|
|
|
InsertError, LoopHandle, Source,
|
2018-10-04 22:37:43 +00:00
|
|
|
};
|
2017-04-14 22:23:16 +00:00
|
|
|
|
2018-01-23 23:10:00 +00:00
|
|
|
// No idea if this is the same across unix platforms
|
|
|
|
// Lets make this linux exclusive for now, once someone tries to build it for
|
|
|
|
// any BSD-like system, they can verify if this is right and make a PR to change this.
|
2018-12-08 17:31:08 +00:00
|
|
|
#[cfg(all(any(target_os = "linux", target_os = "android"), feature = "backend_session"))]
|
2018-01-23 23:10:00 +00:00
|
|
|
const INPUT_MAJOR: u32 = 13;
|
|
|
|
|
2018-12-08 12:40:07 +00:00
|
|
|
/// Libinput based [`InputBackend`].
|
2017-04-15 20:53:09 +00:00
|
|
|
///
|
|
|
|
/// Tracks input of all devices given manually or via a udev seat to a provided libinput
|
|
|
|
/// context.
|
2017-04-14 22:23:16 +00:00
|
|
|
pub struct LibinputInputBackend {
|
2017-04-23 17:55:43 +00:00
|
|
|
context: libinput::Libinput,
|
|
|
|
devices: Vec<libinput::Device>,
|
2017-04-23 22:30:02 +00:00
|
|
|
seats: HashMap<libinput::Seat, backend::Seat>,
|
2018-12-15 20:58:43 +00:00
|
|
|
handler: Option<Box<dyn backend::InputHandler<LibinputInputBackend> + 'static>>,
|
2017-04-15 18:17:26 +00:00
|
|
|
logger: ::slog::Logger,
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-15 20:34:28 +00:00
|
|
|
impl LibinputInputBackend {
|
2018-12-08 12:40:07 +00:00
|
|
|
/// Initialize a new [`LibinputInputBackend`] from a given already initialized
|
|
|
|
/// [libinput context](libinput::Libinput).
|
2017-04-23 17:55:43 +00:00
|
|
|
pub fn new<L>(context: libinput::Libinput, logger: L) -> Self
|
2017-06-20 09:31:18 +00:00
|
|
|
where
|
|
|
|
L: Into<Option<::slog::Logger>>,
|
2017-04-15 20:34:28 +00:00
|
|
|
{
|
2018-12-15 20:32:28 +00:00
|
|
|
let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_libinput"));
|
2017-04-15 20:34:28 +00:00
|
|
|
info!(log, "Initializing a libinput backend");
|
|
|
|
LibinputInputBackend {
|
2018-06-28 09:33:49 +00:00
|
|
|
context,
|
2017-04-15 20:34:28 +00:00
|
|
|
devices: Vec::new(),
|
|
|
|
seats: HashMap::new(),
|
|
|
|
handler: None,
|
|
|
|
logger: log,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-23 17:55:43 +00:00
|
|
|
impl backend::Event for event::keyboard::KeyboardKeyEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::keyboard::KeyboardEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent {
|
|
|
|
fn key_code(&self) -> u32 {
|
2017-04-26 18:10:22 +00:00
|
|
|
use input::event::keyboard::KeyboardEventTrait;
|
2017-04-23 17:55:43 +00:00
|
|
|
self.key()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn state(&self) -> backend::KeyState {
|
2017-04-26 18:10:22 +00:00
|
|
|
use input::event::keyboard::KeyboardEventTrait;
|
2017-04-23 17:55:43 +00:00
|
|
|
self.key_state().into()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn count(&self) -> u32 {
|
|
|
|
self.seat_key_count()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-22 15:09:58 +00:00
|
|
|
impl<'a> backend::Event for event::pointer::PointerAxisEvent {
|
2017-04-23 17:55:43 +00:00
|
|
|
fn time(&self) -> u32 {
|
2018-03-22 15:09:58 +00:00
|
|
|
event::pointer::PointerEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-22 15:09:58 +00:00
|
|
|
impl backend::PointerAxisEvent for event::pointer::PointerAxisEvent {
|
2020-01-01 10:43:16 +00:00
|
|
|
fn amount(&self, axis: Axis) -> Option<f64> {
|
|
|
|
Some(self.axis_value(axis.into()))
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
2020-01-01 10:43:16 +00:00
|
|
|
fn amount_discrete(&self, axis: Axis) -> Option<f64> {
|
|
|
|
self.axis_value_discrete(axis.into())
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 15:09:58 +00:00
|
|
|
fn source(&self) -> backend::AxisSource {
|
|
|
|
self.axis_source().into()
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::pointer::PointerButtonEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::pointer::PointerEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::PointerButtonEvent for event::pointer::PointerButtonEvent {
|
|
|
|
fn button(&self) -> backend::MouseButton {
|
|
|
|
match self.button() {
|
|
|
|
0x110 => backend::MouseButton::Left,
|
|
|
|
0x111 => backend::MouseButton::Right,
|
|
|
|
0x112 => backend::MouseButton::Middle,
|
|
|
|
x => backend::MouseButton::Other(x as u8),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn state(&self) -> backend::MouseButtonState {
|
2017-04-23 22:30:02 +00:00
|
|
|
self.button_state().into()
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::pointer::PointerMotionEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::pointer::PointerEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent {
|
2018-03-13 14:06:52 +00:00
|
|
|
fn delta_x(&self) -> i32 {
|
|
|
|
self.dx() as i32
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
2018-03-13 14:06:52 +00:00
|
|
|
fn delta_y(&self) -> i32 {
|
|
|
|
self.dy() as i32
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::pointer::PointerMotionAbsoluteEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::pointer::PointerEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::PointerMotionAbsoluteEvent for event::pointer::PointerMotionAbsoluteEvent {
|
|
|
|
fn x(&self) -> f64 {
|
|
|
|
self.absolute_x()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn y(&self) -> f64 {
|
|
|
|
self.absolute_y()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn x_transformed(&self, width: u32) -> u32 {
|
|
|
|
self.absolute_x_transformed(width) as u32
|
|
|
|
}
|
|
|
|
|
|
|
|
fn y_transformed(&self, height: u32) -> u32 {
|
|
|
|
self.absolute_y_transformed(height) as u32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::touch::TouchDownEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::TouchDownEvent for event::touch::TouchDownEvent {
|
|
|
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn x(&self) -> f64 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::x(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn y(&self) -> f64 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::y(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn x_transformed(&self, width: u32) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::x_transformed(self, width) as u32
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn y_transformed(&self, height: u32) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::y_transformed(self, height) as u32
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::touch::TouchMotionEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::TouchMotionEvent for event::touch::TouchMotionEvent {
|
|
|
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn x(&self) -> f64 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::x(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn y(&self) -> f64 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::y(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn x_transformed(&self, width: u32) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::x_transformed(self, width) as u32
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn y_transformed(&self, height: u32) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventPosition::y_transformed(self, height) as u32
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::touch::TouchUpEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::TouchUpEvent for event::touch::TouchUpEvent {
|
|
|
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::touch::TouchCancelEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::TouchCancelEvent for event::touch::TouchCancelEvent {
|
|
|
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::Event for event::touch::TouchFrameEvent {
|
|
|
|
fn time(&self) -> u32 {
|
2017-04-23 22:30:02 +00:00
|
|
|
event::touch::TouchEventTrait::time(self)
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl backend::TouchFrameEvent for event::touch::TouchFrameEvent {}
|
|
|
|
|
2018-12-08 12:40:07 +00:00
|
|
|
impl InputBackend for LibinputInputBackend {
|
2017-04-23 17:55:43 +00:00
|
|
|
type InputConfig = [libinput::Device];
|
2017-04-14 22:23:16 +00:00
|
|
|
type EventError = IoError;
|
|
|
|
|
2017-04-23 17:55:43 +00:00
|
|
|
type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent;
|
2018-03-22 15:09:58 +00:00
|
|
|
type PointerAxisEvent = event::pointer::PointerAxisEvent;
|
2017-04-23 17:55:43 +00:00
|
|
|
type PointerButtonEvent = event::pointer::PointerButtonEvent;
|
|
|
|
type PointerMotionEvent = event::pointer::PointerMotionEvent;
|
|
|
|
type PointerMotionAbsoluteEvent = event::pointer::PointerMotionAbsoluteEvent;
|
|
|
|
type TouchDownEvent = event::touch::TouchDownEvent;
|
|
|
|
type TouchUpEvent = event::touch::TouchUpEvent;
|
|
|
|
type TouchMotionEvent = event::touch::TouchMotionEvent;
|
|
|
|
type TouchCancelEvent = event::touch::TouchCancelEvent;
|
|
|
|
type TouchFrameEvent = event::touch::TouchFrameEvent;
|
|
|
|
|
2018-04-18 07:53:54 +00:00
|
|
|
fn set_handler<H: backend::InputHandler<Self> + 'static>(&mut self, mut handler: H) {
|
2017-04-14 22:23:16 +00:00
|
|
|
if self.handler.is_some() {
|
2018-04-18 07:53:54 +00:00
|
|
|
self.clear_handler();
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
2017-11-07 00:18:52 +00:00
|
|
|
info!(self.logger, "New input handler set");
|
2017-04-23 22:30:02 +00:00
|
|
|
for seat in self.seats.values() {
|
|
|
|
trace!(self.logger, "Calling on_seat_created with {:?}", seat);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_seat_created(seat);
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
self.handler = Some(Box::new(handler));
|
|
|
|
}
|
|
|
|
|
2018-12-15 20:58:43 +00:00
|
|
|
fn get_handler(&mut self) -> Option<&mut dyn backend::InputHandler<Self>> {
|
2017-09-05 17:51:05 +00:00
|
|
|
self.handler
|
|
|
|
.as_mut()
|
2018-12-15 20:58:43 +00:00
|
|
|
.map(|handler| handler as &mut dyn backend::InputHandler<Self>)
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
|
2018-04-18 07:53:54 +00:00
|
|
|
fn clear_handler(&mut self) {
|
2017-04-14 22:23:16 +00:00
|
|
|
if let Some(mut handler) = self.handler.take() {
|
2017-04-23 22:30:02 +00:00
|
|
|
for seat in self.seats.values() {
|
|
|
|
trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_seat_destroyed(seat);
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
2017-04-15 18:17:26 +00:00
|
|
|
info!(self.logger, "Removing input handler");
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn input_config(&mut self) -> &mut Self::InputConfig {
|
|
|
|
&mut self.devices
|
|
|
|
}
|
|
|
|
|
2018-04-18 07:53:54 +00:00
|
|
|
fn dispatch_new_events(&mut self) -> Result<(), IoError> {
|
2017-04-23 17:55:43 +00:00
|
|
|
use input::event::EventTrait;
|
|
|
|
|
2017-04-14 22:23:16 +00:00
|
|
|
self.context.dispatch()?;
|
2017-04-23 17:55:43 +00:00
|
|
|
|
2017-04-14 22:23:16 +00:00
|
|
|
for event in &mut self.context {
|
|
|
|
match event {
|
2017-04-23 17:55:43 +00:00
|
|
|
libinput::Event::Device(device_event) => {
|
2017-04-14 22:23:16 +00:00
|
|
|
use input::event::device::*;
|
|
|
|
match device_event {
|
|
|
|
DeviceEvent::Added(device_added_event) => {
|
2017-04-23 17:55:43 +00:00
|
|
|
let added = device_added_event.device();
|
2017-04-14 22:23:16 +00:00
|
|
|
|
2017-04-23 17:55:43 +00:00
|
|
|
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),
|
2017-04-14 22:23:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let device_seat = added.seat();
|
|
|
|
self.devices.push(added);
|
|
|
|
|
2018-01-16 15:27:56 +00:00
|
|
|
match self.seats.entry(device_seat.clone()) {
|
2017-04-15 17:19:09 +00:00
|
|
|
Entry::Occupied(mut seat_entry) => {
|
|
|
|
let old_seat = seat_entry.get_mut();
|
|
|
|
{
|
2017-04-23 22:30:02 +00:00
|
|
|
let caps = old_seat.capabilities_mut();
|
2017-04-15 17:19:09 +00:00
|
|
|
caps.pointer = new_caps.pointer || caps.pointer;
|
|
|
|
caps.keyboard = new_caps.keyboard || caps.keyboard;
|
|
|
|
caps.touch = new_caps.touch || caps.touch;
|
|
|
|
}
|
|
|
|
if let Some(ref mut handler) = self.handler {
|
2017-04-23 22:30:02 +00:00
|
|
|
trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_seat_changed(old_seat);
|
2017-04-15 17:19:09 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2017-04-15 17:19:09 +00:00
|
|
|
Entry::Vacant(seat_entry) => {
|
|
|
|
let mut hasher = DefaultHasher::default();
|
|
|
|
seat_entry.key().hash(&mut hasher);
|
2018-01-16 15:27:56 +00:00
|
|
|
let seat = seat_entry.insert(backend::Seat::new(
|
|
|
|
hasher.finish(),
|
|
|
|
format!(
|
|
|
|
"{}:{}",
|
|
|
|
device_seat.physical_name(),
|
|
|
|
device_seat.logical_name()
|
|
|
|
),
|
|
|
|
new_caps,
|
|
|
|
));
|
2017-04-15 17:19:09 +00:00
|
|
|
if let Some(ref mut handler) = self.handler {
|
2017-04-23 22:30:02 +00:00
|
|
|
trace!(self.logger, "Calling on_seat_created with {:?}", seat);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_seat_created(seat);
|
2017-04-15 17:19:09 +00:00
|
|
|
}
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2017-04-14 22:23:16 +00:00
|
|
|
DeviceEvent::Removed(device_removed_event) => {
|
2017-04-23 17:55:43 +00:00
|
|
|
let removed = device_removed_event.device();
|
2017-04-14 22:23:16 +00:00
|
|
|
|
|
|
|
// remove device
|
|
|
|
self.devices.retain(|dev| *dev == removed);
|
|
|
|
|
|
|
|
let device_seat = removed.seat();
|
|
|
|
|
|
|
|
// update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`.
|
2017-04-23 22:30:02 +00:00
|
|
|
if let Some(seat) = self.seats.get_mut(&device_seat) {
|
|
|
|
let caps = seat.capabilities_mut();
|
2018-09-24 22:32:09 +00:00
|
|
|
caps.pointer = self
|
|
|
|
.devices
|
2017-09-05 17:51:05 +00:00
|
|
|
.iter()
|
|
|
|
.filter(|x| x.seat() == device_seat)
|
|
|
|
.any(|x| x.has_capability(libinput::DeviceCapability::Pointer));
|
2018-09-24 22:32:09 +00:00
|
|
|
caps.keyboard = self
|
|
|
|
.devices
|
2017-09-05 17:51:05 +00:00
|
|
|
.iter()
|
|
|
|
.filter(|x| x.seat() == device_seat)
|
|
|
|
.any(|x| x.has_capability(libinput::DeviceCapability::Keyboard));
|
2018-09-24 22:32:09 +00:00
|
|
|
caps.touch = self
|
|
|
|
.devices
|
2017-09-05 17:51:05 +00:00
|
|
|
.iter()
|
|
|
|
.filter(|x| x.seat() == device_seat)
|
|
|
|
.any(|x| x.has_capability(libinput::DeviceCapability::Touch));
|
2017-04-14 22:23:16 +00:00
|
|
|
} else {
|
2018-01-27 12:04:42 +00:00
|
|
|
warn!(self.logger, "Seat changed that was never created");
|
|
|
|
continue;
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// check if the seat has any other devices
|
|
|
|
if !self.devices.iter().any(|x| x.seat() == device_seat) {
|
|
|
|
// it has not, lets destroy it
|
2017-04-23 22:30:02 +00:00
|
|
|
if let Some(seat) = self.seats.remove(&device_seat) {
|
2017-04-14 22:23:16 +00:00
|
|
|
if let Some(ref mut handler) = self.handler {
|
2017-04-23 22:30:02 +00:00
|
|
|
trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_seat_destroyed(&seat);
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-01-27 12:04:42 +00:00
|
|
|
warn!(self.logger, "Seat destroyed that was never created");
|
|
|
|
continue;
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
2017-06-20 09:31:18 +00:00
|
|
|
// it has, notify about updates
|
2017-04-26 18:19:57 +00:00
|
|
|
} else if let Some(ref mut handler) = self.handler {
|
2018-01-27 12:04:42 +00:00
|
|
|
if let Some(seat) = self.seats.get(&device_seat) {
|
|
|
|
trace!(self.logger, "Calling on_seat_changed with {:?}", seat);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_seat_changed(&seat);
|
2018-01-27 12:04:42 +00:00
|
|
|
} else {
|
|
|
|
warn!(self.logger, "Seat changed that was never created");
|
|
|
|
continue;
|
|
|
|
}
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
|
|
|
if let Some(ref mut handler) = self.handler {
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_input_config_changed(&mut self.devices);
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2017-04-23 17:55:43 +00:00
|
|
|
libinput::Event::Touch(touch_event) => {
|
2017-04-26 18:10:22 +00:00
|
|
|
use input::event::touch::*;
|
2017-04-15 20:20:11 +00:00
|
|
|
if let Some(ref mut handler) = self.handler {
|
|
|
|
let device_seat = touch_event.device().seat();
|
2018-06-28 09:33:49 +00:00
|
|
|
if let Some(ref seat) = self.seats.get(&device_seat) {
|
2018-01-27 12:04:42 +00:00
|
|
|
match touch_event {
|
|
|
|
TouchEvent::Down(down_event) => {
|
|
|
|
trace!(self.logger, "Calling on_touch_down with {:?}", down_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_touch_down(seat, down_event)
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
|
|
|
TouchEvent::Motion(motion_event) => {
|
2018-09-24 22:32:09 +00:00
|
|
|
trace!(self.logger, "Calling on_touch_motion with {:?}", motion_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_touch_motion(seat, motion_event)
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
|
|
|
TouchEvent::Up(up_event) => {
|
|
|
|
trace!(self.logger, "Calling on_touch_up with {:?}", up_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_touch_up(seat, up_event)
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
|
|
|
TouchEvent::Cancel(cancel_event) => {
|
2018-09-24 22:32:09 +00:00
|
|
|
trace!(self.logger, "Calling on_touch_cancel with {:?}", cancel_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_touch_cancel(seat, cancel_event)
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
|
|
|
TouchEvent::Frame(frame_event) => {
|
|
|
|
trace!(self.logger, "Calling on_touch_frame with {:?}", frame_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_touch_frame(seat, frame_event)
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2018-01-27 12:04:42 +00:00
|
|
|
} else {
|
2018-10-30 12:56:30 +00:00
|
|
|
warn!(self.logger, "Received touch event of non existing Seat");
|
2018-01-27 12:04:42 +00:00
|
|
|
continue;
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
2017-04-15 20:20:11 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2017-04-23 17:55:43 +00:00
|
|
|
libinput::Event::Keyboard(keyboard_event) => {
|
2017-04-26 18:10:22 +00:00
|
|
|
use input::event::keyboard::*;
|
2017-04-15 18:26:44 +00:00
|
|
|
match keyboard_event {
|
2018-12-08 17:31:08 +00:00
|
|
|
KeyboardEvent::Key(key_event) => {
|
|
|
|
if let Some(ref mut handler) = self.handler {
|
|
|
|
let device_seat = key_event.device().seat();
|
|
|
|
if let Some(ref seat) = self.seats.get(&device_seat) {
|
|
|
|
trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event);
|
|
|
|
handler.on_keyboard_key(seat, key_event);
|
|
|
|
} else {
|
|
|
|
warn!(self.logger, "Received key event of non existing Seat");
|
|
|
|
continue;
|
|
|
|
}
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
2018-12-08 17:31:08 +00:00
|
|
|
}
|
2017-04-15 18:26:44 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2017-04-23 17:55:43 +00:00
|
|
|
libinput::Event::Pointer(pointer_event) => {
|
2017-04-26 18:10:22 +00:00
|
|
|
use input::event::pointer::*;
|
2017-04-23 17:55:43 +00:00
|
|
|
if let Some(ref mut handler) = self.handler {
|
|
|
|
let device_seat = pointer_event.device().seat();
|
2018-06-28 09:33:49 +00:00
|
|
|
if let Some(ref seat) = self.seats.get(&device_seat) {
|
2018-01-27 12:04:42 +00:00
|
|
|
match pointer_event {
|
|
|
|
PointerEvent::Motion(motion_event) => {
|
2018-09-24 22:32:09 +00:00
|
|
|
trace!(self.logger, "Calling on_pointer_move with {:?}", motion_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_pointer_move(seat, motion_event);
|
2017-04-15 19:46:27 +00:00
|
|
|
}
|
2018-01-27 12:04:42 +00:00
|
|
|
PointerEvent::MotionAbsolute(motion_abs_event) => {
|
2017-06-20 09:31:18 +00:00
|
|
|
trace!(
|
|
|
|
self.logger,
|
2018-01-27 12:04:42 +00:00
|
|
|
"Calling on_pointer_move_absolute with {:?}",
|
|
|
|
motion_abs_event
|
2017-06-20 09:31:18 +00:00
|
|
|
);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_pointer_move_absolute(seat, motion_abs_event);
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
|
|
|
PointerEvent::Axis(axis_event) => {
|
2018-03-22 15:09:58 +00:00
|
|
|
trace!(self.logger, "Calling on_pointer_axis with {:?}", axis_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_pointer_axis(seat, axis_event);
|
2018-01-27 12:04:42 +00:00
|
|
|
}
|
|
|
|
PointerEvent::Button(button_event) => {
|
2018-09-24 22:32:09 +00:00
|
|
|
trace!(self.logger, "Calling on_pointer_button with {:?}", button_event);
|
2018-04-18 07:53:54 +00:00
|
|
|
handler.on_pointer_button(seat, button_event);
|
2017-04-15 19:46:27 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2018-01-27 12:04:42 +00:00
|
|
|
} else {
|
2018-10-30 12:56:30 +00:00
|
|
|
warn!(self.logger, "Received pointer event of non existing Seat");
|
2018-01-27 12:04:42 +00:00
|
|
|
continue;
|
2017-04-15 19:46:27 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
|
|
|
_ => {} //FIXME: What to do with the rest.
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
2017-04-26 18:10:22 +00:00
|
|
|
}
|
2017-04-14 22:23:16 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2017-04-23 17:55:43 +00:00
|
|
|
}
|
2017-04-18 19:57:53 +00:00
|
|
|
|
2017-04-23 17:55:43 +00:00
|
|
|
impl From<event::keyboard::KeyState> for backend::KeyState {
|
|
|
|
fn from(libinput: event::keyboard::KeyState) -> Self {
|
|
|
|
match libinput {
|
|
|
|
event::keyboard::KeyState::Pressed => backend::KeyState::Pressed,
|
|
|
|
event::keyboard::KeyState::Released => backend::KeyState::Released,
|
2017-04-18 19:57:53 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-14 22:23:16 +00:00
|
|
|
}
|
2017-04-15 18:26:44 +00:00
|
|
|
|
2017-04-23 17:55:43 +00:00
|
|
|
impl From<event::pointer::Axis> for backend::Axis {
|
|
|
|
fn from(libinput: event::pointer::Axis) -> Self {
|
2017-04-15 18:26:44 +00:00
|
|
|
match libinput {
|
2017-04-23 17:55:43 +00:00
|
|
|
event::pointer::Axis::Vertical => backend::Axis::Vertical,
|
|
|
|
event::pointer::Axis::Horizontal => backend::Axis::Horizontal,
|
2017-04-15 18:26:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-15 19:46:27 +00:00
|
|
|
|
2018-03-22 15:09:58 +00:00
|
|
|
impl From<backend::Axis> for event::pointer::Axis {
|
|
|
|
fn from(axis: backend::Axis) -> Self {
|
|
|
|
match axis {
|
|
|
|
backend::Axis::Vertical => event::pointer::Axis::Vertical,
|
|
|
|
backend::Axis::Horizontal => event::pointer::Axis::Horizontal,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-23 17:55:43 +00:00
|
|
|
impl From<event::pointer::AxisSource> for backend::AxisSource {
|
|
|
|
fn from(libinput: event::pointer::AxisSource) -> Self {
|
2017-04-15 19:46:27 +00:00
|
|
|
match libinput {
|
2017-04-23 17:55:43 +00:00
|
|
|
event::pointer::AxisSource::Finger => backend::AxisSource::Finger,
|
|
|
|
event::pointer::AxisSource::Continuous => backend::AxisSource::Continuous,
|
|
|
|
event::pointer::AxisSource::Wheel => backend::AxisSource::Wheel,
|
|
|
|
event::pointer::AxisSource::WheelTilt => backend::AxisSource::WheelTilt,
|
2017-04-15 19:46:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-15 20:02:44 +00:00
|
|
|
|
2017-04-23 17:55:43 +00:00
|
|
|
impl From<event::pointer::ButtonState> for backend::MouseButtonState {
|
|
|
|
fn from(libinput: event::pointer::ButtonState) -> Self {
|
2017-04-15 20:02:44 +00:00
|
|
|
match libinput {
|
2017-04-23 17:55:43 +00:00
|
|
|
event::pointer::ButtonState::Pressed => backend::MouseButtonState::Pressed,
|
|
|
|
event::pointer::ButtonState::Released => backend::MouseButtonState::Released,
|
2017-04-15 20:02:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-07 00:18:52 +00:00
|
|
|
|
2017-12-03 21:44:45 +00:00
|
|
|
#[cfg(feature = "backend_session")]
|
2017-11-07 00:18:52 +00:00
|
|
|
impl SessionObserver for libinput::Libinput {
|
2018-04-18 07:53:54 +00:00
|
|
|
fn pause(&mut self, device: Option<(u32, u32)>) {
|
2018-01-23 23:10:00 +00:00
|
|
|
if let Some((major, _)) = device {
|
|
|
|
if major != INPUT_MAJOR {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// lets hope multiple suspends are okay in case of logind?
|
2017-11-07 00:18:52 +00:00
|
|
|
self.suspend()
|
|
|
|
}
|
|
|
|
|
2018-04-18 07:53:54 +00:00
|
|
|
fn activate(&mut self, _device: Option<(u32, u32, Option<RawFd>)>) {
|
2018-01-23 23:10:00 +00:00
|
|
|
// libinput closes the devices on suspend, so we should not get any INPUT_MAJOR calls
|
|
|
|
// also lets hope multiple resumes are okay in case of logind
|
2017-11-07 00:18:52 +00:00
|
|
|
self.resume().expect("Unable to resume libinput context");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 12:40:07 +00:00
|
|
|
/// Wrapper for types implementing the [`Session`] trait to provide
|
|
|
|
/// a [`libinput::LibinputInterface`] implementation.
|
2017-12-03 21:44:45 +00:00
|
|
|
#[cfg(feature = "backend_session")]
|
2017-11-07 00:18:52 +00:00
|
|
|
pub struct LibinputSessionInterface<S: Session>(S);
|
|
|
|
|
2017-12-03 21:44:45 +00:00
|
|
|
#[cfg(feature = "backend_session")]
|
2017-11-07 00:18:52 +00:00
|
|
|
impl<S: Session> From<S> for LibinputSessionInterface<S> {
|
|
|
|
fn from(session: S) -> LibinputSessionInterface<S> {
|
|
|
|
LibinputSessionInterface(session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-03 21:44:45 +00:00
|
|
|
#[cfg(feature = "backend_session")]
|
2017-11-07 00:18:52 +00:00
|
|
|
impl<S: Session> libinput::LibinputInterface for LibinputSessionInterface<S> {
|
|
|
|
fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<RawFd, i32> {
|
|
|
|
use nix::fcntl::OFlag;
|
2017-12-15 17:38:10 +00:00
|
|
|
self.0
|
|
|
|
.open(path, OFlag::from_bits_truncate(flags))
|
|
|
|
.map_err(|err| err.as_errno().unwrap_or(1 /*Use EPERM by default*/))
|
2017-11-07 00:18:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn close_restricted(&mut self, fd: RawFd) {
|
|
|
|
let _ = self.0.close(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-21 08:37:57 +00:00
|
|
|
impl AsRawFd for LibinputInputBackend {
|
|
|
|
fn as_raw_fd(&self) -> RawFd {
|
2018-12-05 08:30:11 +00:00
|
|
|
self.context.as_raw_fd()
|
2018-11-21 08:37:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 12:40:07 +00:00
|
|
|
/// Binds a [`LibinputInputBackend`] to a given [`LoopHandle`].
|
2017-11-29 19:00:16 +00:00
|
|
|
///
|
|
|
|
/// Automatically feeds the backend with incoming events without any manual calls to
|
2018-12-08 12:40:07 +00:00
|
|
|
/// [`dispatch_new_events`](InputBackend::dispatch_new_events). Should be used to achieve the smallest possible latency.
|
2018-09-24 22:30:39 +00:00
|
|
|
pub fn libinput_bind<Data: 'static>(
|
2018-09-28 16:01:33 +00:00
|
|
|
backend: LibinputInputBackend,
|
2018-09-24 22:30:39 +00:00
|
|
|
handle: LoopHandle<Data>,
|
2018-11-21 09:41:55 +00:00
|
|
|
) -> ::std::result::Result<
|
|
|
|
Source<Generic<EventedFd<LibinputInputBackend>>>,
|
|
|
|
InsertError<Generic<EventedFd<LibinputInputBackend>>>,
|
|
|
|
> {
|
2018-11-21 08:37:57 +00:00
|
|
|
let mut source = Generic::from_fd_source(backend);
|
2018-09-24 22:30:39 +00:00
|
|
|
source.set_interest(Ready::readable());
|
2018-11-21 08:37:57 +00:00
|
|
|
|
|
|
|
handle.insert_source(source, move |evt, _| {
|
|
|
|
let mut backend = evt.source.borrow_mut();
|
|
|
|
if let Err(error) = backend.0.dispatch_new_events() {
|
|
|
|
warn!(backend.0.logger, "Libinput errored: {}", error);
|
|
|
|
}
|
|
|
|
})
|
2018-09-24 22:32:09 +00:00
|
|
|
}
|