148 lines
6.6 KiB
Rust
148 lines
6.6 KiB
Rust
|
//! Implementation of input backend trait for types provided by `libinput`
|
||
|
|
||
|
use backend::SeatInternal;
|
||
|
use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities};
|
||
|
use input::{Libinput, Device, Seat as LibinputSeat, DeviceCapability};
|
||
|
use input::event::*;
|
||
|
|
||
|
use std::io::Error as IoError;
|
||
|
use std::collections::hash_map::{DefaultHasher, HashMap};
|
||
|
use std::hash::{Hash, Hasher};
|
||
|
|
||
|
pub struct LibinputInputBackend {
|
||
|
context: Libinput,
|
||
|
devices: Vec<Device>,
|
||
|
seats: HashMap<LibinputSeat, Seat>,
|
||
|
handler: Option<Box<InputHandler<LibinputInputBackend> + 'static>>,
|
||
|
}
|
||
|
|
||
|
impl InputBackend for LibinputInputBackend {
|
||
|
type InputConfig = [Device];
|
||
|
type EventError = IoError;
|
||
|
|
||
|
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
|
||
|
if self.handler.is_some() {
|
||
|
self.clear_handler();
|
||
|
}
|
||
|
for seat in self.seats.values() {
|
||
|
handler.on_seat_created(&seat);
|
||
|
}
|
||
|
self.handler = Some(Box::new(handler));
|
||
|
}
|
||
|
|
||
|
fn get_handler(&mut self) -> Option<&mut InputHandler<Self>> {
|
||
|
self.handler
|
||
|
.as_mut()
|
||
|
.map(|handler| handler as &mut InputHandler<Self>)
|
||
|
}
|
||
|
|
||
|
fn clear_handler(&mut self) {
|
||
|
if let Some(mut handler) = self.handler.take() {
|
||
|
for seat in self.seats.values() {
|
||
|
handler.on_seat_destroyed(&seat);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn input_config(&mut self) -> &mut Self::InputConfig {
|
||
|
&mut self.devices
|
||
|
}
|
||
|
|
||
|
fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> {
|
||
|
// FIXME later.
|
||
|
// This will be doable with the hardware cursor api and probably some more cases
|
||
|
Err(())
|
||
|
}
|
||
|
|
||
|
fn dispatch_new_events(&mut self) -> Result<(), IoError> {
|
||
|
self.context.dispatch()?;
|
||
|
for event in &mut self.context {
|
||
|
match event {
|
||
|
Event::Device(device_event) => {
|
||
|
use input::event::device::*;
|
||
|
match device_event {
|
||
|
DeviceEvent::Added(device_added_event) => {
|
||
|
let added = device_added_event.into_event().device();
|
||
|
|
||
|
let new_caps = SeatCapabilities {
|
||
|
pointer: added.has_capability(DeviceCapability::Pointer),
|
||
|
keyboard: added.has_capability(DeviceCapability::Keyboard),
|
||
|
touch: added.has_capability(DeviceCapability::Touch),
|
||
|
};
|
||
|
|
||
|
let device_seat = added.seat();
|
||
|
self.devices.push(added);
|
||
|
|
||
|
let contains = self.seats.contains_key(&device_seat);
|
||
|
if contains {
|
||
|
let old_seat = self.seats.get_mut(&device_seat).unwrap();
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
if let Some(ref mut handler) = self.handler {
|
||
|
handler.on_seat_changed(old_seat);
|
||
|
}
|
||
|
} else {
|
||
|
let mut hasher = DefaultHasher::default();
|
||
|
device_seat.hash(&mut hasher);
|
||
|
self.seats.insert(device_seat.clone(), Seat::new(hasher.finish(), new_caps));
|
||
|
if let Some(ref mut handler) = self.handler {
|
||
|
handler.on_seat_created(self.seats.get(&device_seat).unwrap());
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
DeviceEvent::Removed(device_removed_event) => {
|
||
|
let removed = device_removed_event.into_event().device();
|
||
|
|
||
|
// 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`.
|
||
|
if let Some(seat) = self.seats.get_mut(&device_seat) {
|
||
|
let caps = seat.capabilities_mut();
|
||
|
caps.pointer = self.devices.iter().any(|x| x.has_capability(DeviceCapability::Pointer));
|
||
|
caps.keyboard = self.devices.iter().any(|x| x.has_capability(DeviceCapability::Keyboard));
|
||
|
caps.touch = self.devices.iter().any(|x| x.has_capability(DeviceCapability::Touch));
|
||
|
} else {
|
||
|
//TODO is this the best we can do?
|
||
|
panic!("Seat changed that was never created")
|
||
|
}
|
||
|
|
||
|
// check if the seat has any other devices
|
||
|
if !self.devices.iter().any(|x| x.seat() == device_seat) {
|
||
|
// it has not, lets destroy it
|
||
|
if let Some(seat) = self.seats.remove(&device_seat) {
|
||
|
if let Some(ref mut handler) = self.handler {
|
||
|
handler.on_seat_destroyed(&seat);
|
||
|
}
|
||
|
} else {
|
||
|
//TODO is this the best we can do?
|
||
|
panic!("Seat destroyed that was never created");
|
||
|
}
|
||
|
} else {
|
||
|
// it has, notify about updates
|
||
|
if let Some(ref mut handler) = self.handler {
|
||
|
handler.on_seat_changed(self.seats.get(&device_seat).unwrap());
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
}
|
||
|
if let Some(ref mut handler) = self.handler {
|
||
|
handler.on_input_config_changed(&mut self.devices);
|
||
|
}
|
||
|
},
|
||
|
Event::Touch(touch_event) => {},
|
||
|
Event::Keyboard(keyboard_event) => {},
|
||
|
Event::Pointer(pointer_event) => {},
|
||
|
_ => {}, //FIXME: What to do with the rest.
|
||
|
}
|
||
|
};
|
||
|
Ok(())
|
||
|
}
|
||
|
}
|