From cba111bf4f98e834fd01ca5c666b51c1a83a7698 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 00:23:03 +0200 Subject: [PATCH 01/30] Add input crate --- Cargo.toml | 4 +++- src/backend/mod.rs | 2 ++ src/lib.rs | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 433ba3f..090b92c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,12 +13,14 @@ slog = { version = "2.0.0" } slog-stdlog = "2.0.0-0.2" glutin = { version = "~0.7.4", optional = true } glium = { version = "~0.16.0", optional = true } +input = { path = "../input", optional = true } clippy = { version = "*", optional = true } [dev-dependencies] slog-term = "~1.5" [features] -default = ["backend_glutin", "renderer_glium"] +default = ["backend_glutin", "backend_libinput", "renderer_glium"] backend_glutin = ["glutin", "wayland-server/dlopen"] renderer_glium = ["glium"] +backend_libinput = ["input"] diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 6e01f97..4b79aed 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -17,6 +17,8 @@ pub mod graphics; #[cfg(feature = "backend_glutin")] pub mod glutin; +#[cfg(feature = "backend_libinput")] +pub mod libinput; #[cfg(feature = "renderer_glium")] mod glium; diff --git a/src/lib.rs b/src/lib.rs index d266b43..7ac03cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,8 @@ extern crate tempfile; #[cfg(feature = "backend_glutin")] extern crate glutin; +#[cfg(feature = "backend_libinput")] +extern crate input; #[cfg(feature = "renderer_glium")] extern crate glium; From 5369cc2927207445482af642be07248a39359441 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 00:23:16 +0200 Subject: [PATCH 02/30] First draft of a libinput backend - Only does DeviceEvent parsing for now - No way to initialize it --- src/backend/libinput.rs | 147 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/backend/libinput.rs diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs new file mode 100644 index 0000000..b3938c7 --- /dev/null +++ b/src/backend/libinput.rs @@ -0,0 +1,147 @@ +//! 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, + seats: HashMap, + handler: Option + 'static>>, +} + +impl InputBackend for LibinputInputBackend { + type InputConfig = [Device]; + type EventError = IoError; + + fn set_handler + '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.handler + .as_mut() + .map(|handler| handler as &mut InputHandler) + } + + 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(()) + } +} From 7aca2edb1361dec2429ecdec3c5848020a798790 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 00:24:23 +0200 Subject: [PATCH 03/30] Adjust InputBackend for libinput compatibility - Make id be an `u64` to be able to populate it by a hash - Add internal interface to get a mutable capabilities reference from a `Seat`. - `InputConfig` type does not need to be `Sized` on `InputBackend` --- src/backend/input.rs | 11 ++++++++--- src/backend/mod.rs | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/backend/input.rs b/src/backend/input.rs index 03d0ca5..65a0210 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -12,19 +12,24 @@ use std::error::Error; /// separated users, all with their own focus, input and cursor available. /// /// Seats can be checked for equality and hashed for differentiation. +// FIXME: Impl PartialEq, Eq and Hash only dependant on `id`. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Seat { - id: u32, + id: u64, capabilities: SeatCapabilities, } impl SeatInternal for Seat { - fn new(id: u32, capabilities: SeatCapabilities) -> Seat { + fn new(id: u64, capabilities: SeatCapabilities) -> Seat { Seat { id: id, capabilities: capabilities, } } + + fn capabilities_mut(&mut self) -> &mut SeatCapabilities { + &mut self.capabilities + } } impl Seat { @@ -182,7 +187,7 @@ pub enum TouchEvent { /// given events. pub trait InputBackend: Sized { /// Type of input device associated with the backend - type InputConfig; + type InputConfig: ?Sized; /// Type representing errors that may be returned when processing events type EventError: Error; diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 4b79aed..bf235bb 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -28,7 +28,8 @@ pub use glium::*; /// Internal functions that need to be accessible by the different backend implementations trait SeatInternal { - fn new(id: u32, capabilities: input::SeatCapabilities) -> Self; + fn new(id: u64, capabilities: input::SeatCapabilities) -> Self; + fn capabilities_mut(&mut self) -> &mut input::SeatCapabilities; } trait TouchSlotInternal { From 10857d108e0eb9b48bac01d9b7dbfeb7e8043e7e Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 00:28:39 +0200 Subject: [PATCH 04/30] Move over to crates.io version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 090b92c..a72b80a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ slog = { version = "2.0.0" } slog-stdlog = "2.0.0-0.2" glutin = { version = "~0.7.4", optional = true } glium = { version = "~0.16.0", optional = true } -input = { path = "../input", optional = true } +input = { version = "0.1", optional = true } clippy = { version = "*", optional = true } [dev-dependencies] From ab35f140a08503c3003f5588a674fd6c7002f4b3 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 19:19:09 +0200 Subject: [PATCH 05/30] Use entry api for `DeviceAddedEvent`s seat creation/update --- src/backend/libinput.rs | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index b3938c7..631af2d 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -6,7 +6,7 @@ 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::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::hash::{Hash, Hasher}; pub struct LibinputInputBackend { @@ -73,24 +73,26 @@ impl InputBackend for LibinputInputBackend { 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()); + match self.seats.entry(device_seat) { + 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; + } + if let Some(ref mut handler) = self.handler { + handler.on_seat_changed(old_seat); + } + }, + Entry::Vacant(seat_entry) => { + let mut hasher = DefaultHasher::default(); + seat_entry.key().hash(&mut hasher); + let seat = seat_entry.insert(Seat::new(hasher.finish(), new_caps)); + if let Some(ref mut handler) = self.handler { + handler.on_seat_created(seat); + } } } }, From 0980f8a66c3150d26f46aba8d5ff2126a329a65d Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 19:19:33 +0200 Subject: [PATCH 06/30] Remove done todos --- src/backend/libinput.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 631af2d..63befc6 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -111,7 +111,6 @@ impl InputBackend for LibinputInputBackend { 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") } @@ -123,7 +122,6 @@ impl InputBackend for LibinputInputBackend { handler.on_seat_destroyed(&seat); } } else { - //TODO is this the best we can do? panic!("Seat destroyed that was never created"); } } else { From 4f3a140543856f6172981b0ae5aec8e89e3aa265 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 19:20:53 +0200 Subject: [PATCH 07/30] Fix capability update --- src/backend/libinput.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 63befc6..2ff3999 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -107,9 +107,9 @@ impl InputBackend for LibinputInputBackend { // 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)); + caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Pointer)); + caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Keyboard)); + caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Touch)); } else { panic!("Seat changed that was never created") } From 3edb489a92fce9c4e63c9ac6802f79e01385ce75 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 20:17:26 +0200 Subject: [PATCH 08/30] Add logging to libinput backend --- src/backend/libinput.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 2ff3999..9e61b61 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -14,6 +14,7 @@ pub struct LibinputInputBackend { devices: Vec, seats: HashMap, handler: Option + 'static>>, + logger: ::slog::Logger, } impl InputBackend for LibinputInputBackend { @@ -24,7 +25,9 @@ impl InputBackend for LibinputInputBackend { if self.handler.is_some() { self.clear_handler(); } + info!(self.logger, "New input handler set."); for seat in self.seats.values() { + trace!(self.logger, "Calling on_seat_created with {:?}", seat); handler.on_seat_created(&seat); } self.handler = Some(Box::new(handler)); @@ -39,8 +42,10 @@ impl InputBackend for LibinputInputBackend { fn clear_handler(&mut self) { if let Some(mut handler) = self.handler.take() { for seat in self.seats.values() { + trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat); handler.on_seat_destroyed(&seat); } + info!(self.logger, "Removing input handler"); } } @@ -51,6 +56,7 @@ impl InputBackend for LibinputInputBackend { 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 + warn!(self.logger, "Setting the cursor position is currently unsupported by the libinput backend"); Err(()) } @@ -83,6 +89,7 @@ impl InputBackend for LibinputInputBackend { caps.touch = new_caps.touch || caps.touch; } if let Some(ref mut handler) = self.handler { + trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat); handler.on_seat_changed(old_seat); } }, @@ -91,6 +98,7 @@ impl InputBackend for LibinputInputBackend { seat_entry.key().hash(&mut hasher); let seat = seat_entry.insert(Seat::new(hasher.finish(), new_caps)); if let Some(ref mut handler) = self.handler { + trace!(self.logger, "Calling on_seat_created with {:?}", seat); handler.on_seat_created(seat); } } @@ -119,6 +127,7 @@ impl InputBackend for LibinputInputBackend { // it has not, lets destroy it if let Some(seat) = self.seats.remove(&device_seat) { if let Some(ref mut handler) = self.handler { + trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat); handler.on_seat_destroyed(&seat); } } else { @@ -127,7 +136,9 @@ impl InputBackend for LibinputInputBackend { } else { // it has, notify about updates if let Some(ref mut handler) = self.handler { - handler.on_seat_changed(self.seats.get(&device_seat).unwrap()); + let seat = self.seats.get(&device_seat).unwrap(); + trace!(self.logger, "Calling on_seat_changed with {:?}", seat); + handler.on_seat_changed(seat); } } }, From a5cfed8715b4ac8990bbde6531053fc4686b928d Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 20:26:44 +0200 Subject: [PATCH 09/30] Impl key events --- src/backend/libinput.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 9e61b61..f14e054 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -148,7 +148,18 @@ impl InputBackend for LibinputInputBackend { } }, Event::Touch(touch_event) => {}, - Event::Keyboard(keyboard_event) => {}, + Event::Keyboard(keyboard_event) => { + use ::input::event::keyboard::*; + match keyboard_event { + KeyboardEvent::Key(event) => { + if let Some(ref mut handler) = self.handler { + let device_seat = event.device().seat(); + handler.on_keyboard_key(self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"), + event.time(), event.key(), event.key_state().into(), event.seat_key_count()); + } + } + } + }, Event::Pointer(pointer_event) => {}, _ => {}, //FIXME: What to do with the rest. } @@ -156,3 +167,12 @@ impl InputBackend for LibinputInputBackend { Ok(()) } } + +impl From<::input::event::keyboard::KeyState> for ::backend::input::KeyState { + fn from(libinput: ::input::event::keyboard::KeyState) -> Self { + match libinput { + ::input::event::keyboard::KeyState::Pressed => ::backend::input::KeyState::Pressed, + ::input::event::keyboard::KeyState::Released => ::backend::input::KeyState::Released, + } + } +} From 01884a6aa8fabf4e898f8d0b53519ac7b5de162f Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 21:46:27 +0200 Subject: [PATCH 10/30] Add pointer axis event passing --- src/backend/glutin.rs | 4 +- src/backend/input.rs | 2 +- src/backend/libinput.rs | 114 ++++++++++++++++++++++++++++++++-------- 3 files changed, 94 insertions(+), 26 deletions(-) diff --git a/src/backend/glutin.rs b/src/backend/glutin.rs index c545d52..5a289e5 100644 --- a/src/backend/glutin.rs +++ b/src/backend/glutin.rs @@ -291,14 +291,14 @@ impl InputBackend for GlutinInputBackend { handler.on_pointer_scroll(&self.seat, self.time_counter, Axis::Vertical, - AxisSource::Continous, + AxisSource::Continuous, x as f64); } if y != 0.0 { handler.on_pointer_scroll(&self.seat, self.time_counter, Axis::Horizontal, - AxisSource::Continous, + AxisSource::Continuous, y as f64); } } diff --git a/src/backend/input.rs b/src/backend/input.rs index 65a0210..9c2c613 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -110,7 +110,7 @@ pub enum AxisSource { /// The coordinate system is identical to /// the cursor movement, i.e. a scroll value of 1 represents the equivalent relative /// motion of 1. - Continous, + Continuous, /// Scroll wheel. /// /// No terminating event is guaranteed (though it may happen). Scrolling is in diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index f14e054..fcb5729 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -9,10 +9,15 @@ use std::io::Error as IoError; use std::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::hash::{Hash, Hasher}; +struct SeatDesc { + seat: Seat, + pointer: (u32, u32), +} + pub struct LibinputInputBackend { context: Libinput, devices: Vec, - seats: HashMap, + seats: HashMap, handler: Option + 'static>>, logger: ::slog::Logger, } @@ -26,9 +31,9 @@ impl InputBackend for LibinputInputBackend { self.clear_handler(); } info!(self.logger, "New input handler set."); - for seat in self.seats.values() { - trace!(self.logger, "Calling on_seat_created with {:?}", seat); - handler.on_seat_created(&seat); + for desc in self.seats.values() { + trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat); + handler.on_seat_created(&desc.seat); } self.handler = Some(Box::new(handler)); } @@ -41,9 +46,9 @@ impl InputBackend for LibinputInputBackend { fn clear_handler(&mut self) { if let Some(mut handler) = self.handler.take() { - for seat in self.seats.values() { - trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat); - handler.on_seat_destroyed(&seat); + for desc in self.seats.values() { + trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat); + handler.on_seat_destroyed(&desc.seat); } info!(self.logger, "Removing input handler"); } @@ -83,23 +88,26 @@ impl InputBackend for LibinputInputBackend { Entry::Occupied(mut seat_entry) => { let old_seat = seat_entry.get_mut(); { - let caps = old_seat.capabilities_mut(); + let caps = old_seat.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 { - trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat); - handler.on_seat_changed(old_seat); + trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat.seat); + handler.on_seat_changed(&old_seat.seat); } }, Entry::Vacant(seat_entry) => { let mut hasher = DefaultHasher::default(); seat_entry.key().hash(&mut hasher); - let seat = seat_entry.insert(Seat::new(hasher.finish(), new_caps)); + let desc = seat_entry.insert(SeatDesc { + seat: Seat::new(hasher.finish(), new_caps), + pointer: (0, 0) //FIXME: What position to assume? Maybe center of the screen instead. Probably call `set_cursor_position` after this. + }); if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_seat_created with {:?}", seat); - handler.on_seat_created(seat); + trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat); + handler.on_seat_created(&desc.seat); } } } @@ -113,8 +121,8 @@ impl InputBackend for LibinputInputBackend { 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(); + if let Some(desc) = self.seats.get_mut(&device_seat) { + let caps = desc.seat.capabilities_mut(); caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Pointer)); caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Keyboard)); caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Touch)); @@ -125,10 +133,10 @@ impl InputBackend for LibinputInputBackend { // 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(desc) = self.seats.remove(&device_seat) { if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat); - handler.on_seat_destroyed(&seat); + trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat); + handler.on_seat_destroyed(&desc.seat); } } else { panic!("Seat destroyed that was never created"); @@ -136,9 +144,9 @@ impl InputBackend for LibinputInputBackend { } else { // it has, notify about updates if let Some(ref mut handler) = self.handler { - let seat = self.seats.get(&device_seat).unwrap(); - trace!(self.logger, "Calling on_seat_changed with {:?}", seat); - handler.on_seat_changed(seat); + let desc = self.seats.get(&device_seat).unwrap(); + trace!(self.logger, "Calling on_seat_changed with {:?}", desc.seat); + handler.on_seat_changed(&desc.seat); } } }, @@ -154,13 +162,62 @@ impl InputBackend for LibinputInputBackend { KeyboardEvent::Key(event) => { if let Some(ref mut handler) = self.handler { let device_seat = event.device().seat(); - handler.on_keyboard_key(self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"), + handler.on_keyboard_key(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat, event.time(), event.key(), event.key_state().into(), event.seat_key_count()); } } } }, - Event::Pointer(pointer_event) => {}, + Event::Pointer(pointer_event) => { + use ::input::event::pointer::*; + match pointer_event { + PointerEvent::Motion(motion_event) => { + let device_seat = motion_event.device().seat(); + let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); + desc.pointer.0 += motion_event.dx() as u32; + desc.pointer.1 += motion_event.dy() as u32; + if let Some(ref mut handler) = self.handler { + handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer); + } + }, + PointerEvent::MotionAbsolute(motion_event) => { + let device_seat = motion_event.device().seat(); + let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); + desc.pointer = ( + motion_event.absolute_x_transformed( + /*FIXME: global.get_focused_output().width() or something like that*/ 1280) as u32, + motion_event.absolute_y_transformed( + /*FIXME: global.get_focused_output().height() or something like that*/ 800) as u32, + ); + if let Some(ref mut handler) = self.handler { + handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer); + } + }, + PointerEvent::Axis(axis_event) => { + if let Some(ref mut handler) = self.handler { + let device_seat = axis_event.device().seat(); + let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); + if axis_event.has_axis(Axis::Vertical) { + handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Vertical, + axis_event.axis_source().into(), match axis_event.axis_source() { + AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Vertical), + AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Vertical).unwrap(), + }); + } + if axis_event.has_axis(Axis::Horizontal) { + handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Horizontal, + axis_event.axis_source().into(), match axis_event.axis_source() { + AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Horizontal), + AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Horizontal).unwrap(), + }); + } + } + }, + PointerEvent::Button(button_event) => { + + } + } + }, _ => {}, //FIXME: What to do with the rest. } }; @@ -176,3 +233,14 @@ impl From<::input::event::keyboard::KeyState> for ::backend::input::KeyState { } } } + +impl From<::input::event::pointer::AxisSource> for ::backend::input::AxisSource { + fn from(libinput: ::input::event::pointer::AxisSource) -> Self { + match libinput { + ::input::event::pointer::AxisSource::Finger => ::backend::input::AxisSource::Finger, + ::input::event::pointer::AxisSource::Continuous => ::backend::input::AxisSource::Continuous, + ::input::event::pointer::AxisSource::Wheel => ::backend::input::AxisSource::Wheel, + ::input::event::pointer::AxisSource::WheelTilt => ::backend::input::AxisSource::WheelTilt, + } + } +} From 2cc401594da99ad1080a76231ea3715cc7afbe19 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:02:44 +0200 Subject: [PATCH 11/30] Add pointer button event passing --- src/backend/libinput.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index fcb5729..6a34800 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -1,7 +1,7 @@ //! Implementation of input backend trait for types provided by `libinput` use backend::SeatInternal; -use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities}; +use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities, MouseButton}; use input::{Libinput, Device, Seat as LibinputSeat, DeviceCapability}; use input::event::*; @@ -214,7 +214,16 @@ impl InputBackend for LibinputInputBackend { } }, PointerEvent::Button(button_event) => { - + if let Some(ref mut handler) = self.handler { + let device_seat = button_event.device().seat(); + let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); + handler.on_pointer_button(&desc.seat, button_event.time(), match button_event.button() { + 0x110 => MouseButton::Left, + 0x111 => MouseButton::Right, + 0x112 => MouseButton::Middle, + x => MouseButton::Other(x as u8), + }, button_event.button_state().into()); + } } } }, @@ -244,3 +253,12 @@ impl From<::input::event::pointer::AxisSource> for ::backend::input::AxisSource } } } + +impl From<::input::event::pointer::ButtonState> for ::backend::input::MouseButtonState { + fn from(libinput: ::input::event::pointer::ButtonState) -> Self { + match libinput { + ::input::event::pointer::ButtonState::Pressed => ::backend::input::MouseButtonState::Pressed, + ::input::event::pointer::ButtonState::Released => ::backend::input::MouseButtonState::Released, + } + } +} From da93b4ac67d772a9f81384b52349c5021e236d47 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:20:11 +0200 Subject: [PATCH 12/30] Add touch event passing --- src/backend/libinput.rs | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 6a34800..69bc8c4 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -155,7 +155,14 @@ impl InputBackend for LibinputInputBackend { handler.on_input_config_changed(&mut self.devices); } }, - Event::Touch(touch_event) => {}, + Event::Touch(touch_event) => { + use ::input::event::touch::*; + if let Some(ref mut handler) = self.handler { + let device_seat = touch_event.device().seat(); + handler.on_touch(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat, + touch_event.time(), touch_event.into()) + } + }, Event::Keyboard(keyboard_event) => { use ::input::event::keyboard::*; match keyboard_event { @@ -185,9 +192,9 @@ impl InputBackend for LibinputInputBackend { let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); desc.pointer = ( motion_event.absolute_x_transformed( - /*FIXME: global.get_focused_output().width() or something like that*/ 1280) as u32, + /*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280) as u32, motion_event.absolute_y_transformed( - /*FIXME: global.get_focused_output().height() or something like that*/ 800) as u32, + /*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800) as u32, ); if let Some(ref mut handler) = self.handler { handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer); @@ -262,3 +269,30 @@ impl From<::input::event::pointer::ButtonState> for ::backend::input::MouseButto } } } + +impl From<::input::event::touch::TouchEvent> for ::backend::input::TouchEvent { + fn from(libinput: ::input::event::touch::TouchEvent) -> Self { + use ::input::event::touch::{TouchEventSlot, TouchEventPosition}; + use ::backend::TouchSlotInternal; + + match libinput { + ::input::event::touch::TouchEvent::Down(down_event) => ::backend::input::TouchEvent::Down { + slot: down_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), + x: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280), + y: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800), + }, + ::input::event::touch::TouchEvent::Motion(motion_event) => ::backend::input::TouchEvent::Motion { + slot: motion_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), + x: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280), + y: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800), + }, + ::input::event::touch::TouchEvent::Up(up_event) => ::backend::input::TouchEvent::Up { + slot: up_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), + }, + ::input::event::touch::TouchEvent::Cancel(cancel_event) => ::backend::input::TouchEvent::Cancel { + slot: cancel_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), + }, + ::input::event::touch::TouchEvent::Frame(_) => ::backend::input::TouchEvent::Frame, + } + } +} From 8cbe96d1ac80dda5c4bf8205e6496c417a44456d Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:28:51 +0200 Subject: [PATCH 13/30] Add more logging --- src/backend/libinput.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 69bc8c4..5cfa336 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -159,6 +159,7 @@ impl InputBackend for LibinputInputBackend { use ::input::event::touch::*; if let Some(ref mut handler) = self.handler { let device_seat = touch_event.device().seat(); + trace!(self.logger, "Calling on_touch with {:?}", touch_event); handler.on_touch(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat, touch_event.time(), touch_event.into()) } @@ -166,11 +167,12 @@ impl InputBackend for LibinputInputBackend { Event::Keyboard(keyboard_event) => { use ::input::event::keyboard::*; match keyboard_event { - KeyboardEvent::Key(event) => { + KeyboardEvent::Key(key_event) => { if let Some(ref mut handler) = self.handler { - let device_seat = event.device().seat(); + trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event); + let device_seat = key_event.device().seat(); handler.on_keyboard_key(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat, - event.time(), event.key(), event.key_state().into(), event.seat_key_count()); + key_event.time(), key_event.key(), key_event.key_state().into(), key_event.seat_key_count()); } } } @@ -184,6 +186,7 @@ impl InputBackend for LibinputInputBackend { desc.pointer.0 += motion_event.dx() as u32; desc.pointer.1 += motion_event.dy() as u32; if let Some(ref mut handler) = self.handler { + trace!(self.logger, "Calling on_pointer_move with {:?}", desc.pointer); handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer); } }, @@ -197,6 +200,7 @@ impl InputBackend for LibinputInputBackend { /*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800) as u32, ); if let Some(ref mut handler) = self.handler { + trace!(self.logger, "Calling on_pointer_move with {:?}", desc.pointer); handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer); } }, @@ -205,18 +209,22 @@ impl InputBackend for LibinputInputBackend { let device_seat = axis_event.device().seat(); let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); if axis_event.has_axis(Axis::Vertical) { + let value = match axis_event.axis_source() { + AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Vertical), + AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Vertical).unwrap(), + }; + trace!(self.logger, "Calling on_pointer_scroll on Axis::Vertical from {:?} with {:?}", axis_event.axis_source(), value); handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Vertical, - axis_event.axis_source().into(), match axis_event.axis_source() { - AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Vertical), - AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Vertical).unwrap(), - }); + axis_event.axis_source().into(), value); } if axis_event.has_axis(Axis::Horizontal) { + let value = match axis_event.axis_source() { + AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Horizontal), + AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Horizontal).unwrap(), + }; + trace!(self.logger, "Calling on_pointer_scroll on Axis::Horizontal from {:?} with {:?}", axis_event.axis_source(), value); handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Horizontal, - axis_event.axis_source().into(), match axis_event.axis_source() { - AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Horizontal), - AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Horizontal).unwrap(), - }); + axis_event.axis_source().into(), value); } } }, @@ -224,6 +232,7 @@ impl InputBackend for LibinputInputBackend { if let Some(ref mut handler) = self.handler { let device_seat = button_event.device().seat(); let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); + trace!(self.logger, "Calling on_pointer_button with {:?}", button_event.button()); handler.on_pointer_button(&desc.seat, button_event.time(), match button_event.button() { 0x110 => MouseButton::Left, 0x111 => MouseButton::Right, From 4c591a86bdc43b1a2ddb00409262157b04ddaa31 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:34:28 +0200 Subject: [PATCH 14/30] Add initializer --- src/backend/libinput.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 5cfa336..1a5d3b2 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -22,6 +22,22 @@ pub struct LibinputInputBackend { logger: ::slog::Logger, } +impl LibinputInputBackend { + pub fn new(context: Libinput, logger: L) -> Self + where L: Into> + { + let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_libinput")); + info!(log, "Initializing a libinput backend"); + LibinputInputBackend { + context: context, + devices: Vec::new(), + seats: HashMap::new(), + handler: None, + logger: log, + } + } +} + impl InputBackend for LibinputInputBackend { type InputConfig = [Device]; type EventError = IoError; From 66ea275d71904729e4d72532c8308c36e553e518 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:42:42 +0200 Subject: [PATCH 15/30] Fixup seat implementation --- src/backend/input.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/backend/input.rs b/src/backend/input.rs index 9c2c613..6703413 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -12,8 +12,7 @@ use std::error::Error; /// separated users, all with their own focus, input and cursor available. /// /// Seats can be checked for equality and hashed for differentiation. -// FIXME: Impl PartialEq, Eq and Hash only dependant on `id`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, Eq)] pub struct Seat { id: u64, capabilities: SeatCapabilities, @@ -39,6 +38,18 @@ impl Seat { } } +impl ::std::cmp::PartialEq for Seat { + fn eq(&self, other: &Seat) -> bool { + self.id == other.id + } +} + +impl ::std::hash::Hash for Seat { + fn hash(&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 { From cc6f0c9d73951e90bd5327dc45a959b4223ff7cf Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:45:26 +0200 Subject: [PATCH 16/30] Expand `on_seat_changed` documentation --- src/backend/input.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/input.rs b/src/backend/input.rs index 6703413..09803dd 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -231,6 +231,10 @@ pub trait InputHandler { /// Called when an existing `Seat` has been destroyed. fn on_seat_destroyed(&mut self, seat: &Seat); /// Called when a `Seat`'s properties have changed. + /// + /// ## Note: + /// + /// It is not guaranteed that any change has actually happened. fn on_seat_changed(&mut self, seat: &Seat); /// Called when a new keyboard event was received. From 4afad6f93960c5a22d21ecb7d02b18f7401f8599 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:48:55 +0200 Subject: [PATCH 17/30] Expand `Seat` documentation --- src/backend/input.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backend/input.rs b/src/backend/input.rs index 09803dd..671b2c5 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -11,7 +11,10 @@ use std::error::Error; /// however multiseat configurations are possible and should be treated as /// separated users, all with their own focus, input and cursor available. /// -/// Seats can be checked for equality and hashed for differentiation. +/// 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 referr 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, Copy, Eq)] pub struct Seat { id: u64, From f95faba80f9473f4c09ef507767ce263cd5bfbed Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 15 Apr 2017 22:53:09 +0200 Subject: [PATCH 18/30] Add libinput documentation --- src/backend/libinput.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 1a5d3b2..7609d81 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -14,6 +14,10 @@ struct SeatDesc { pointer: (u32, u32), } +/// Libinput based `InputBackend`. +/// +/// Tracks input of all devices given manually or via a udev seat to a provided libinput +/// context. pub struct LibinputInputBackend { context: Libinput, devices: Vec, @@ -23,6 +27,8 @@ pub struct LibinputInputBackend { } impl LibinputInputBackend { + /// Initialize a new `LibinputInputBackend` from a given already initialized libinput + /// context. pub fn new(context: Libinput, logger: L) -> Self where L: Into> { From 109f4035e8f16d2f7af6cf720ce8421d87ddc7a5 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Tue, 18 Apr 2017 21:20:08 +0200 Subject: [PATCH 19/30] Move set_cursor_position to the graphics backend --- src/backend/glutin.rs | 28 +++++++++++++++++++--------- src/backend/graphics/mod.rs | 17 +++++++++++++++++ src/backend/graphics/opengl.rs | 4 +++- src/backend/graphics/software.rs | 4 +++- src/backend/input.rs | 7 ------- src/backend/libinput.rs | 7 ------- 6 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/backend/glutin.rs b/src/backend/glutin.rs index 5a289e5..a79bd93 100644 --- a/src/backend/glutin.rs +++ b/src/backend/glutin.rs @@ -2,6 +2,7 @@ use backend::{SeatInternal, TouchSlotInternal}; +use backend::graphics::GraphicsBackend; use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError}; use backend::input::{Axis, AxisSource, InputBackend, InputHandler, KeyState, MouseButton, MouseButtonState, Seat, SeatCapabilities, TouchEvent, TouchSlot}; @@ -79,6 +80,13 @@ impl GlutinHeadlessRenderer { } } +impl GraphicsBackend for GlutinHeadlessRenderer { + fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> { + //FIXME: Maybe save position? Is it of any use? + Ok(()) + } +} + impl OpenglGraphicsBackend for GlutinHeadlessRenderer { #[inline] fn swap_buffers(&self) -> Result<(), SwapBuffersError> { @@ -130,6 +138,17 @@ impl GlutinWindowedRenderer { } } +impl GraphicsBackend for GlutinWindowedRenderer { + fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()> { + if let Some((win_x, win_y)) = self.window.get_position() { + self.window + .set_cursor_position(win_x + x as i32, win_y + y as i32) + } else { + Err(()) + } + } +} + impl OpenglGraphicsBackend for GlutinWindowedRenderer { #[inline] fn swap_buffers(&self) -> Result<(), SwapBuffersError> { @@ -233,15 +252,6 @@ impl InputBackend for GlutinInputBackend { &mut self.input_config } - fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()> { - if let Some((win_x, win_y)) = self.window.get_position() { - self.window - .set_cursor_position(win_x + x as i32, win_y + y as i32) - } else { - Err(()) - } - } - /// Processes new events of the underlying event loop to drive the set `InputHandler`. /// /// You need to periodically call this function to keep the underlying event loop and diff --git a/src/backend/graphics/mod.rs b/src/backend/graphics/mod.rs index 75b2ee6..9d1cdde 100644 --- a/src/backend/graphics/mod.rs +++ b/src/backend/graphics/mod.rs @@ -2,5 +2,22 @@ //! //! Note: Not every api may be supported by every backend +/// General functions any graphics backend should support independently from it's rendering +/// techique. +pub trait GraphicsBackend { + /// Sets the cursor position and therefor updates the drawn cursors position. + /// Useful as well for e.g. pointer wrapping. + /// + /// Not guaranteed to be supported on every backend. The result usually + /// depends on the backend, the cursor might be "owned" by another more priviledged + /// compositor (running nested). + /// + /// In these cases setting the position is actually not required, as movement is done + /// by the higher compositor and not by the backend. It is still good practice to update + /// the position after every recieved event, but don't rely on pointer wrapping working. + /// + fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()>; +} + pub mod software; pub mod opengl; diff --git a/src/backend/graphics/opengl.rs b/src/backend/graphics/opengl.rs index a03f93b..d0457aa 100644 --- a/src/backend/graphics/opengl.rs +++ b/src/backend/graphics/opengl.rs @@ -2,6 +2,8 @@ use nix::c_void; +use super::GraphicsBackend; + /// Error that can happen when swapping buffers. #[derive(Debug, Clone)] pub enum SwapBuffersError { @@ -61,7 +63,7 @@ pub struct PixelFormat { /// Trait that describes objects that have an OpenGl context /// and can be used to render upon -pub trait OpenglGraphicsBackend { +pub trait OpenglGraphicsBackend: GraphicsBackend { /// Swaps buffers at the end of a frame. fn swap_buffers(&self) -> Result<(), SwapBuffersError>; diff --git a/src/backend/graphics/software.rs b/src/backend/graphics/software.rs index 278885a..7e9d474 100644 --- a/src/backend/graphics/software.rs +++ b/src/backend/graphics/software.rs @@ -3,8 +3,10 @@ use std::error::Error; use wayland_server::protocol::wl_shm::Format; +use super::GraphicsBackend; + /// Trait that describes objects providing a software rendering implementation -pub trait CpuGraphicsBackend { +pub trait CpuGraphicsBackend: GraphicsBackend { /// Render a given buffer of a given format at a specified place in the framebuffer /// /// # Error diff --git a/src/backend/input.rs b/src/backend/input.rs index 671b2c5..6251682 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -218,13 +218,6 @@ pub trait InputBackend: Sized { /// Processes new events of the underlying backend and drives the `InputHandler`. fn dispatch_new_events(&mut self) -> Result<(), Self::EventError>; - - /// Sets the cursor position, useful for e.g. pointer wrapping. - /// - /// Not guaranteed to be supported on every backend. The result usually - /// depends on the capability of the backend, but may also fail for certain - /// specific actions. See the backends documentation. - fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()>; } /// Implement to receive input events from any `InputBackend`. diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 7609d81..f65097e 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -80,13 +80,6 @@ impl InputBackend for LibinputInputBackend { &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 - warn!(self.logger, "Setting the cursor position is currently unsupported by the libinput backend"); - Err(()) - } - fn dispatch_new_events(&mut self) -> Result<(), IoError> { self.context.dispatch()?; for event in &mut self.context { From 9b6273f2971c4faaa77719c4193e649c42530262 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Tue, 18 Apr 2017 21:57:53 +0200 Subject: [PATCH 20/30] Add set_output_metadata --- src/backend/glutin.rs | 4 ++- src/backend/input.rs | 19 ++++++++++- src/backend/libinput.rs | 74 +++++++++++++++++++++-------------------- 3 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/backend/glutin.rs b/src/backend/glutin.rs index a79bd93..e635f7e 100644 --- a/src/backend/glutin.rs +++ b/src/backend/glutin.rs @@ -5,7 +5,7 @@ use backend::{SeatInternal, TouchSlotInternal}; use backend::graphics::GraphicsBackend; use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError}; use backend::input::{Axis, AxisSource, InputBackend, InputHandler, KeyState, MouseButton, MouseButtonState, - Seat, SeatCapabilities, TouchEvent, TouchSlot}; + Seat, SeatCapabilities, TouchEvent, TouchSlot, Output}; use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, PixelFormat as GlutinPixelFormat}; use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext, HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder}; @@ -376,6 +376,8 @@ impl InputBackend for GlutinInputBackend { } Ok(()) } + + fn set_output_metadata(&mut self, seat: &Seat, output: &Output) {} } impl GlutinInputBackend { diff --git a/src/backend/input.rs b/src/backend/input.rs index 6251682..a0be819 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -3,6 +3,7 @@ use backend::{SeatInternal, TouchSlotInternal}; use std::error::Error; +use std::hash::Hash; /// A seat describes a group of input devices and at least one /// graphics device belonging together. @@ -64,6 +65,20 @@ pub struct SeatCapabilities { pub touch: bool, } +// FIXME: Maybe refactor this into a struct or move to a more appropriate +// module once fleshed out + +/// Describes a general output that can be focused by a `Seat`. +pub trait Output { + /// Returns size in pixels (width, height) + fn size(&self) -> (u32, u32); + + /// Returns width in pixels + fn width(&self) -> u32; + /// Returns height in pixels + fn height(&self) -> u32; +} + /// State of key on a keyboard. Either pressed or released #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum KeyState { @@ -216,6 +231,9 @@ pub trait InputBackend: Sized { /// Get current `InputConfig` fn input_config(&mut self) -> &mut Self::InputConfig; + /// Called to inform the Input backend about a new focused Output for a `Seat` + fn set_output_metadata(&mut self, seat: &Seat, output: &Output); + /// Processes new events of the underlying backend and drives the `InputHandler`. fn dispatch_new_events(&mut self) -> Result<(), Self::EventError>; } @@ -232,7 +250,6 @@ pub trait InputHandler { /// /// It is not guaranteed that any change has actually happened. fn on_seat_changed(&mut self, seat: &Seat); - /// Called when a new keyboard event was received. /// /// # Arguments diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index f65097e..63c29e9 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -1,7 +1,7 @@ //! Implementation of input backend trait for types provided by `libinput` -use backend::SeatInternal; -use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities, MouseButton}; +use backend::{SeatInternal, TouchSlotInternal}; +use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities, MouseButton, TouchEvent as BackendTouchEvent, TouchSlot as BackendTouchSlot, Output}; use input::{Libinput, Device, Seat as LibinputSeat, DeviceCapability}; use input::event::*; @@ -12,6 +12,7 @@ use std::hash::{Hash, Hasher}; struct SeatDesc { seat: Seat, pointer: (u32, u32), + size: (u32, u32), } /// Libinput based `InputBackend`. @@ -118,7 +119,8 @@ impl InputBackend for LibinputInputBackend { seat_entry.key().hash(&mut hasher); let desc = seat_entry.insert(SeatDesc { seat: Seat::new(hasher.finish(), new_caps), - pointer: (0, 0) //FIXME: What position to assume? Maybe center of the screen instead. Probably call `set_cursor_position` after this. + pointer: (0, 0), //FIXME: We should not assume a position. Some backends might force a position on us. + size: (1280, 800), //FIXME: Document the requirement of calling `set_output_metadata` on `on_seat_created`. }); if let Some(ref mut handler) = self.handler { trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat); @@ -174,9 +176,28 @@ impl InputBackend for LibinputInputBackend { use ::input::event::touch::*; if let Some(ref mut handler) = self.handler { let device_seat = touch_event.device().seat(); + let desc = self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); trace!(self.logger, "Calling on_touch with {:?}", touch_event); - handler.on_touch(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat, - touch_event.time(), touch_event.into()) + handler.on_touch(&desc.seat, touch_event.time(), + match touch_event { + TouchEvent::Down(down_event) => BackendTouchEvent::Down { + slot: down_event.slot().map(|x| BackendTouchSlot::new(x)), + x: down_event.x_transformed(desc.size.0), + y: down_event.x_transformed(desc.size.1), + }, + TouchEvent::Motion(motion_event) => BackendTouchEvent::Motion { + slot: motion_event.slot().map(|x| BackendTouchSlot::new(x)), + x: motion_event.x_transformed(desc.size.0), + y: motion_event.x_transformed(desc.size.1), + }, + TouchEvent::Up(up_event) => BackendTouchEvent::Up { + slot: up_event.slot().map(|x| BackendTouchSlot::new(x)), + }, + TouchEvent::Cancel(cancel_event) => BackendTouchEvent::Cancel { + slot: cancel_event.slot().map(|x| BackendTouchSlot::new(x)), + }, + TouchEvent::Frame(_) => ::backend::input::TouchEvent::Frame, + }) } }, Event::Keyboard(keyboard_event) => { @@ -209,10 +230,8 @@ impl InputBackend for LibinputInputBackend { let device_seat = motion_event.device().seat(); let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); desc.pointer = ( - motion_event.absolute_x_transformed( - /*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280) as u32, - motion_event.absolute_y_transformed( - /*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800) as u32, + motion_event.absolute_x_transformed(desc.size.0) as u32, + motion_event.absolute_y_transformed(desc.size.1) as u32, ); if let Some(ref mut handler) = self.handler { trace!(self.logger, "Calling on_pointer_move with {:?}", desc.pointer); @@ -263,6 +282,16 @@ impl InputBackend for LibinputInputBackend { }; Ok(()) } + + fn set_output_metadata(&mut self, seat: &Seat, output: &Output) { + for desc in self.seats.values_mut() { + if desc.seat == *seat { + desc.size = output.size(); + return; + } + } + panic!("Got metadata for non-existant seat"); + } } impl From<::input::event::keyboard::KeyState> for ::backend::input::KeyState { @@ -293,30 +322,3 @@ impl From<::input::event::pointer::ButtonState> for ::backend::input::MouseButto } } } - -impl From<::input::event::touch::TouchEvent> for ::backend::input::TouchEvent { - fn from(libinput: ::input::event::touch::TouchEvent) -> Self { - use ::input::event::touch::{TouchEventSlot, TouchEventPosition}; - use ::backend::TouchSlotInternal; - - match libinput { - ::input::event::touch::TouchEvent::Down(down_event) => ::backend::input::TouchEvent::Down { - slot: down_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), - x: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280), - y: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800), - }, - ::input::event::touch::TouchEvent::Motion(motion_event) => ::backend::input::TouchEvent::Motion { - slot: motion_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), - x: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280), - y: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800), - }, - ::input::event::touch::TouchEvent::Up(up_event) => ::backend::input::TouchEvent::Up { - slot: up_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), - }, - ::input::event::touch::TouchEvent::Cancel(cancel_event) => ::backend::input::TouchEvent::Cancel { - slot: cancel_event.slot().map(|x| ::backend::input::TouchSlot::new(x)), - }, - ::input::event::touch::TouchEvent::Frame(_) => ::backend::input::TouchEvent::Frame, - } - } -} From 056ce6312ca49a66106d505fea122b8acc7cc896 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Fri, 21 Apr 2017 22:21:19 +0200 Subject: [PATCH 21/30] Add set_cursor_representation --- src/backend/glutin.rs | 12 +++++++++++- src/backend/graphics/mod.rs | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/backend/glutin.rs b/src/backend/glutin.rs index e635f7e..7bc4048 100644 --- a/src/backend/glutin.rs +++ b/src/backend/glutin.rs @@ -6,7 +6,7 @@ use backend::graphics::GraphicsBackend; use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError}; use backend::input::{Axis, AxisSource, InputBackend, InputHandler, KeyState, MouseButton, MouseButtonState, Seat, SeatCapabilities, TouchEvent, TouchSlot, Output}; -use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, PixelFormat as GlutinPixelFormat}; +use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, PixelFormat as GlutinPixelFormat, MouseCursor}; use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext, HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder}; use nix::c_void; @@ -81,10 +81,14 @@ impl GlutinHeadlessRenderer { } impl GraphicsBackend for GlutinHeadlessRenderer { + type CursorFormat = (); + fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> { //FIXME: Maybe save position? Is it of any use? Ok(()) } + + fn set_cursor_representation(&mut self, cursor: ()) {} } impl OpenglGraphicsBackend for GlutinHeadlessRenderer { @@ -139,6 +143,8 @@ impl GlutinWindowedRenderer { } impl GraphicsBackend for GlutinWindowedRenderer { + type CursorFormat = MouseCursor; + fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()> { if let Some((win_x, win_y)) = self.window.get_position() { self.window @@ -147,6 +153,10 @@ impl GraphicsBackend for GlutinWindowedRenderer { Err(()) } } + + fn set_cursor_representation(&mut self, cursor: MouseCursor) { + self.window.set_cursor(cursor); + } } impl OpenglGraphicsBackend for GlutinWindowedRenderer { diff --git a/src/backend/graphics/mod.rs b/src/backend/graphics/mod.rs index 9d1cdde..4ad08f8 100644 --- a/src/backend/graphics/mod.rs +++ b/src/backend/graphics/mod.rs @@ -5,6 +5,9 @@ /// General functions any graphics backend should support independently from it's rendering /// techique. pub trait GraphicsBackend { + /// Format representing the image drawn for the cursor. + type CursorFormat; + /// Sets the cursor position and therefor updates the drawn cursors position. /// Useful as well for e.g. pointer wrapping. /// @@ -17,6 +20,13 @@ pub trait GraphicsBackend { /// the position after every recieved event, but don't rely on pointer wrapping working. /// fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()>; + + /// Set the cursor drawn on the `GraphicsBackend`. + /// + /// The format is entirely dictated by the concrete implementation and might range + /// from raw image buffers over a fixed list of possible cursor types to simply the + /// void type () to represent no possible customization of the cursor itself. + fn set_cursor_representation(&mut self, cursor: Self::CursorFormat); } pub mod software; From d62f4918015b1bfd536f2ea88c4608a953d80632 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Fri, 21 Apr 2017 23:41:28 +0200 Subject: [PATCH 22/30] Refactor `InputBackend` to use events. --- src/backend/input.rs | 320 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 257 insertions(+), 63 deletions(-) diff --git a/src/backend/input.rs b/src/backend/input.rs index a0be819..f98242c 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -65,18 +65,15 @@ pub struct SeatCapabilities { pub touch: bool, } -// FIXME: Maybe refactor this into a struct or move to a more appropriate -// module once fleshed out - -/// Describes a general output that can be focused by a `Seat`. -pub trait Output { - /// Returns size in pixels (width, height) - fn size(&self) -> (u32, u32); - - /// Returns width in pixels - fn width(&self) -> u32; - /// Returns height in pixels - fn height(&self) -> u32; +/// Trait for generic functions every input event does provide/ +pub trait Event { + /// Returns an upward counting variable useful for event ordering. + /// + /// Makes no gurantees about actual time passed between events. + // # TODO: + // - check if events can even arrive out of order. + // - Make stronger time guarantees, if possible + fn time(&self) -> u32; } /// State of key on a keyboard. Either pressed or released @@ -88,6 +85,16 @@ pub enum KeyState { Pressed, } +/// Trait for keyboard event +pub trait KeyboardKeyEvent: Event { + /// Code of the pressed key. See linux/input-event-codes.h + fn key_code(&self) -> u32; + /// State of the key + fn state(&self) -> KeyState; + /// Total number of keys pressed on all devices on the associated `Seat` + fn count(&self) -> u32; +} + /// A particular mouse button #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum MouseButton { @@ -110,6 +117,14 @@ pub enum MouseButtonState { Pressed, } +/// Common methods pointer event generated by pressed buttons do implement +pub trait PointerButtonEvent: Event { + /// Pressed button of the event + fn button(&self) -> MouseButton; + /// State of the button + fn state(&self) -> MouseButtonState; +} + /// Axis when scrolling #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Axis { @@ -152,6 +167,63 @@ pub enum AxisSource { WheelTilt, } +/// Trait for pointer events generated by scrolling on an axis. +pub trait PointerAxisEvent: Event { + /// `Axis` this event was generated for. + fn axis(&self) -> Axis; + /// Source of the scroll event. Important for interpretation of `amount`. + fn source(&self) -> AxisSource; + /// Amount of scrolling on the given `Axis`. See `source` for interpretation. + fn amount(&self) -> f64; +} + +/// Trait for pointer events generated by relative device movement. +pub trait PointerMotionEvent: Event { + /// Delta between the last and new pointer device position interpreted as pixel movement + fn delta(&self) -> (u32, u32) { + (self.delta_x(), self.delta_y()) + } + + /// Delta on the x axis between the last and new pointer device position interpreted as pixel movement + fn delta_x(&self) -> u32; + /// Delta on the y axis between the last and new pointer device position interpreted as pixel movement + fn delta_y(&self) -> u32; +} + +/// Trait for pointer events generated by absolute device positioning. +pub trait PointerMotionAbsoluteEvent: Event { + /// Device position in it's original coordinate space. + /// + /// The format is defined by the backend implementation. + fn position(&self) -> (f64, f64) { + (self.x(), self.y()) + } + + /// Device x position in it's original coordinate space. + /// + /// The format is defined by the backend implementation. + fn x(&self) -> f64; + + /// Device y position in it's original coordinate space. + /// + /// The format is defined by the backend implementation. + fn y(&self) -> f64; + + /// Device position converted to the targets coordinate space. + /// E.g. the focused output's resolution. + fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { + (self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1)) + } + + /// Device x position converted to the targets coordinate space's width. + /// E.g. the focused output's width. + fn x_transformed(&self, width: u32) -> u32; + + /// Device y position converted to the targets coordinate space's height. + /// E.g. the focused output's height. + fn y_transformed(&self, height: u32) -> u32; +} + /// Slot of a different touch event. /// /// Touch events are groubed by slots, usually to identify different @@ -168,6 +240,91 @@ impl TouchSlotInternal for TouchSlot { } } +/// Trait for touch events starting at a given position. +pub trait TouchDownEvent: Event { + /// `TouchSlot`, if the device has multi-touch capabilities + fn slot(&self) -> Option; + + /// Touch position in the device's native coordinate space + /// + /// The actual format is defined by the implementation. + fn position(&self) -> (f64, f64) { + (self.x(), self.y()) + } + + /// Touch position converted into the target coordinate space. + /// E.g. the focused output's resolution. + fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { + (self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1)) + } + + /// Touch event's x-coordinate in the device's native coordinate space + /// + /// The actual format is defined by the implementation. + fn x(&self) -> f64; + + /// Touch event's x-coordinate in the device's native coordinate space + /// + /// The actual format is defined by the implementation. + fn y(&self) -> f64; + + /// Touch event's x position converted to the targets coordinate space's width. + /// E.g. the focused output's width. + fn x_transformed(&self, width: u32) -> u32; + + /// Touch event's y position converted to the targets coordinate space's width. + /// E.g. the focused output's width. + fn y_transformed(&self, height: u32) -> u32; +} + +pub trait TouchMotionEvent: Event { + /// `TouchSlot`, if the device has multi-touch capabilities + fn slot(&self) -> Option; + + /// Touch position in the device's native coordinate space + /// + /// The actual format is defined by the implementation. + fn position(&self) -> (f64, f64) { + (self.x(), self.y()) + } + + /// Touch position converted into the target coordinate space. + /// E.g. the focused output's resolution. + fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { + (self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1)) + } + + /// Touch event's x-coordinate in the device's native coordinate space + /// + /// The actual format is defined by the implementation. + fn x(&self) -> f64; + + /// Touch event's x-coordinate in the device's native coordinate space + /// + /// The actual format is defined by the implementation. + fn y(&self) -> f64; + + /// Touch event's x position converted to the targets coordinate space's width. + /// E.g. the focused output's width. + fn x_transformed(&self, width: u32) -> u32; + + /// Touch event's y position converted to the targets coordinate space's width. + /// E.g. the focused output's width. + fn y_transformed(&self, height: u32) -> u32; +} + +pub trait TouchUpEvent: Event { + /// `TouchSlot`, if the device has multi-touch capabilities + fn slot(&self) -> Option; +} + +pub trait TouchCancelEvent: Event { + /// `TouchSlot`, if the device has multi-touch capabilities + fn slot(&self) -> Option; +} + +pub trait TouchFrameEvent: Event {} + /// Touch event #[derive(Debug, PartialEq, Clone, Copy)] pub enum TouchEvent { @@ -221,6 +378,17 @@ pub trait InputBackend: Sized { /// Type representing errors that may be returned when processing events type EventError: Error; + type KeyboardKeyEvent: KeyboardKeyEvent; + type PointerAxisEvent: PointerAxisEvent; + type PointerButtonEvent: PointerButtonEvent; + type PointerMotionEvent: PointerMotionEvent; + type PointerMotionAbsoluteEvent: PointerMotionAbsoluteEvent; + type TouchDownEvent: TouchDownEvent; + type TouchUpEvent: TouchUpEvent; + type TouchMotionEvent: TouchMotionEvent; + type TouchCancelEvent: TouchCancelEvent; + type TouchFrameEvent: TouchFrameEvent; + /// Sets a new handler for this `InputBackend` fn set_handler + 'static>(&mut self, handler: H); /// Get a reference to the currently set handler, if any @@ -231,9 +399,6 @@ pub trait InputBackend: Sized { /// Get current `InputConfig` fn input_config(&mut self) -> &mut Self::InputConfig; - /// Called to inform the Input backend about a new focused Output for a `Seat` - fn set_output_metadata(&mut self, seat: &Seat, output: &Output); - /// Processes new events of the underlying backend and drives the `InputHandler`. fn dispatch_new_events(&mut self) -> Result<(), Self::EventError>; } @@ -250,71 +415,80 @@ pub trait InputHandler { /// /// It is not guaranteed that any change has actually happened. fn on_seat_changed(&mut self, seat: &Seat); + /// Called when a new keyboard event was received. /// /// # Arguments /// /// - `seat` - The `Seat` the event belongs to - /// - `time` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events. - /// - `key_code` - Code of the pressed key. See linux/input-event-codes.h - /// - `state` - `KeyState` of the event - /// - `count` - Total number of keys pressed on all devices on the associated `Seat` + /// - `event` - The keyboard event /// - /// # TODO: - /// - check if events can arrive out of order. - /// - Make stronger time guarantees - fn on_keyboard_key(&mut self, seat: &Seat, time: u32, key_code: u32, state: KeyState, count: u32); + fn on_keyboard_key(&mut self, seat: &Seat, event: B::KeyboardKeyEvent); + /// Called when a new pointer movement event was received. /// /// # Arguments /// /// - `seat` - The `Seat` the event belongs to - /// - `time` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events. - /// - `to` - Absolute screen coordinates of the pointer moved to. + /// - `event` - The pointer movement event + fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent); + /// Called when a new pointer absolute movement event was received. /// - /// # TODO: - /// - check if events can arrive out of order. - /// - Make stronger time guarantees - fn on_pointer_move(&mut self, seat: &Seat, time: u32, to: (u32, u32)); + /// # Arguments + /// + /// - `seat` - The `Seat` the event belongs to + /// - `event` - The pointer absolute movement event + fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent); /// Called when a new pointer button event was received. /// /// # Arguments /// /// - `seat` - The `Seat` the event belongs to - /// - `time` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events. - /// - `button` - Which button was pressed.. - /// - `state` - `MouseButtonState` of the event - /// - /// # TODO: - /// - check if events can arrive out of order. - /// - Make stronger time guarantees - fn on_pointer_button(&mut self, seat: &Seat, time: u32, button: MouseButton, state: MouseButtonState); + /// - `event` - The pointer button event + fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent); /// Called when a new pointer scroll event was received. /// /// # Arguments /// /// - `seat` - The `Seat` the event belongs to - /// - `time` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events. - /// - `axis` - `Axis` this event was generated for. - /// - `source` - Source of the scroll event. Important for interpretation of `amount`. - /// - `amount` - Amount of scrolling on the given `Axis`. See `source` for interpretation. - /// - /// # TODO: - /// - check if events can arrive out of order. - /// - Make stronger time guarantees - fn on_pointer_scroll(&mut self, seat: &Seat, time: u32, axis: Axis, source: AxisSource, amount: f64); - /// Called when a new touch event was received. + /// - `event` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events. + fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent); + + /// Called when a new touch down event was received. /// /// # Arguments /// /// - `seat` - The `Seat` the event belongs to - /// - `time` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events. - /// - `event` - Touch event recieved. See `TouchEvent`. + /// - `event` - The touch down event + fn on_touch_down(&mut self, seat: &Seat, event: B::TouchDownEvent); + /// Called when a new touch motion event was received. /// - /// # TODO: - /// - check if events can arrive out of order. - /// - Make stronger time guarantees - fn on_touch(&mut self, seat: &Seat, time: u32, event: TouchEvent); + /// # Arguments + /// + /// - `seat` - The `Seat` the event belongs to + /// - `event` - The touch motion event. + fn on_touch_motion(&mut self, seat: &Seat, event: B::TouchMotionEvent); + /// Called when a new touch up event was received. + /// + /// # Arguments + /// + /// - `seat` - The `Seat` the event belongs to + /// - `event` - The touch up event. + fn on_touch_up(&mut self, seat: &Seat, event: B::TouchUpEvent); + /// Called when a new touch cancel event was received. + /// + /// # Arguments + /// + /// - `seat` - The `Seat` the event belongs to + /// - `event` - The touch cancel event. + fn on_touch_cancel(&mut self, seat: &Seat, event: B::TouchCancelEvent); + /// Called when a new touch frame event was received. + /// + /// # Arguments + /// + /// - `seat` - The `Seat` the event belongs to + /// - `event` - The touch frame event. + fn on_touch_frame(&mut self, seat: &Seat, event: B::TouchFrameEvent); /// Called when the `InputConfig` was changed through an external event. /// @@ -336,24 +510,44 @@ impl InputHandler for Box> { (**self).on_seat_changed(seat) } - fn on_keyboard_key(&mut self, seat: &Seat, time: u32, key_code: u32, state: KeyState, count: u32) { - (**self).on_keyboard_key(seat, time, key_code, state, count) + fn on_keyboard_key(&mut self, seat: &Seat, event: B::KeyboardKeyEvent) { + (**self).on_keyboard_key(seat, event) } - fn on_pointer_move(&mut self, seat: &Seat, time: u32, to: (u32, u32)) { - (**self).on_pointer_move(seat, time, to) + fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent) { + (**self).on_pointer_move(seat, event) } - fn on_pointer_button(&mut self, seat: &Seat, time: u32, button: MouseButton, state: MouseButtonState) { - (**self).on_pointer_button(seat, time, button, state) + fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent) { + (**self).on_pointer_move_absolute(seat, event) } - fn on_pointer_scroll(&mut self, seat: &Seat, time: u32, axis: Axis, source: AxisSource, amount: f64) { - (**self).on_pointer_scroll(seat, time, axis, source, amount) + fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent) { + (**self).on_pointer_button(seat, event) } - fn on_touch(&mut self, seat: &Seat, time: u32, event: TouchEvent) { - (**self).on_touch(seat, time, event) + fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent) { + (**self).on_pointer_axis(seat, event) + } + + fn on_touch_down(&mut self, seat: &Seat, event: B::TouchDownEvent) { + (**self).on_touch_down(seat, event) + } + + fn on_touch_motion(&mut self, seat: &Seat, event: B::TouchMotionEvent) { + (**self).on_touch_motion(seat, event) + } + + fn on_touch_up(&mut self, seat: &Seat, event: B::TouchUpEvent) { + (**self).on_touch_up(seat, event) + } + + fn on_touch_cancel(&mut self, seat: &Seat, event: B::TouchCancelEvent) { + (**self).on_touch_cancel(seat, event) + } + + fn on_touch_frame(&mut self, seat: &Seat, event: B::TouchFrameEvent) { + (**self).on_touch_frame(seat, event) } fn on_input_config_changed(&mut self, config: &mut B::InputConfig) { From 4fc595f68a7a0ad4dca99d53dc1539684e86c0d1 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sun, 23 Apr 2017 19:55:43 +0200 Subject: [PATCH 23/30] Fixup libinput backend to use new event api --- src/backend/libinput.rs | 452 ++++++++++++++++++++++++++++------------ 1 file changed, 319 insertions(+), 133 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 63c29e9..224889b 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -1,18 +1,17 @@ //! Implementation of input backend trait for types provided by `libinput` use backend::{SeatInternal, TouchSlotInternal}; -use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities, MouseButton, TouchEvent as BackendTouchEvent, TouchSlot as BackendTouchSlot, Output}; -use input::{Libinput, Device, Seat as LibinputSeat, DeviceCapability}; -use input::event::*; +use backend::input as backend; +use input as libinput; +use input::event; use std::io::Error as IoError; use std::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::hash::{Hash, Hasher}; struct SeatDesc { - seat: Seat, + seat: backend::Seat, pointer: (u32, u32), - size: (u32, u32), } /// Libinput based `InputBackend`. @@ -20,17 +19,17 @@ struct SeatDesc { /// Tracks input of all devices given manually or via a udev seat to a provided libinput /// context. pub struct LibinputInputBackend { - context: Libinput, - devices: Vec, - seats: HashMap, - handler: Option + 'static>>, + context: libinput::Libinput, + devices: Vec, + seats: HashMap, + handler: Option + 'static>>, logger: ::slog::Logger, } impl LibinputInputBackend { /// Initialize a new `LibinputInputBackend` from a given already initialized libinput /// context. - pub fn new(context: Libinput, logger: L) -> Self + pub fn new(context: libinput::Libinput, logger: L) -> Self where L: Into> { let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_libinput")); @@ -45,11 +44,223 @@ impl LibinputInputBackend { } } -impl InputBackend for LibinputInputBackend { - type InputConfig = [Device]; +impl backend::Event for event::keyboard::KeyboardKeyEvent { + fn time(&self) -> u32 { + self.time() + } +} + +impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent { + fn key_code(&self) -> u32 { + use ::input::event::keyboard::KeyboardEventTrait; + self.key() + } + + fn state(&self) -> backend::KeyState { + use ::input::event::keyboard::KeyboardEventTrait; + self.key_state().into() + } + + fn count(&self) -> u32 { + self.seat_key_count() + } +} + +pub struct PointerAxisEvent { + axis: event::pointer::Axis, + event: event::pointer::PointerAxisEvent, +} + +impl<'a> backend::Event for PointerAxisEvent { + fn time(&self) -> u32 { + use ::input::event::pointer::PointerEventTrait; + self.event.time() + } +} + +impl<'a> backend::PointerAxisEvent for PointerAxisEvent { + fn axis(&self) -> backend::Axis { + self.axis.into() + } + + fn source(&self) -> backend::AxisSource { + self.event.axis_source().into() + } + + fn amount(&self) -> f64 { + match self.source() { + backend::AxisSource::Finger | backend::AxisSource::Continuous => + self.event.axis_value(self.axis), + backend::AxisSource::Wheel | backend::AxisSource::WheelTilt => + self.event.axis_value_discrete(self.axis).unwrap(), + } + } +} + +impl backend::Event for event::pointer::PointerButtonEvent { + fn time(&self) -> u32 { + self.time() + } +} + +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 { + self.state().into() + } +} + +impl backend::Event for event::pointer::PointerMotionEvent { + fn time(&self) -> u32 { + self.time() + } +} + +impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent { + fn delta_x(&self) -> u32 { + self.dx() as u32 + } + fn delta_y(&self) -> u32 { + self.dy() as u32 + } +} + +impl backend::Event for event::pointer::PointerMotionAbsoluteEvent { + fn time(&self) -> u32 { + self.time() + } +} + +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 { + self.time() + } +} + +impl backend::TouchDownEvent for event::touch::TouchDownEvent { + fn slot(&self) -> Option { + self.slot().into() + } + + fn x(&self) -> f64 { + self.x() + } + + fn y(&self) -> f64 { + self.y() + } + + fn x_transformed(&self, width: u32) -> u32 { + self.x_transformed(width) as u32 + } + + fn y_transformed(&self, height: u32) -> u32 { + self.y_transformed(height) as u32 + } +} + +impl backend::Event for event::touch::TouchMotionEvent { + fn time(&self) -> u32 { + self.time() + } +} + +impl backend::TouchMotionEvent for event::touch::TouchMotionEvent { + fn slot(&self) -> Option { + self.slot().into() + } + + fn x(&self) -> f64 { + self.x() + } + + fn y(&self) -> f64 { + self.y() + } + + fn x_transformed(&self, width: u32) -> u32 { + self.x_transformed(width) as u32 + } + + fn y_transformed(&self, height: u32) -> u32 { + self.y_transformed(height) as u32 + } +} + +impl backend::Event for event::touch::TouchUpEvent { + fn time(&self) -> u32 { + self.time() + } +} + +impl backend::TouchUpEvent for event::touch::TouchUpEvent { + fn slot(&self) -> Option { + self.slot().into() + } +} + +impl backend::Event for event::touch::TouchCancelEvent { + fn time(&self) -> u32 { + self.time() + } +} + +impl backend::TouchCancelEvent for event::touch::TouchCancelEvent { + fn slot(&self) -> Option { + self.slot().into() + } +} + +impl backend::Event for event::touch::TouchFrameEvent { + fn time(&self) -> u32 { + self.time() + } +} + +impl backend::TouchFrameEvent for event::touch::TouchFrameEvent {} + +impl backend::InputBackend for LibinputInputBackend { + type InputConfig = [libinput::Device]; type EventError = IoError; - fn set_handler + 'static>(&mut self, mut handler: H) { + type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent; + type PointerAxisEvent = PointerAxisEvent; + 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; + + fn set_handler + 'static>(&mut self, mut handler: H) { if self.handler.is_some() { self.clear_handler(); } @@ -61,10 +272,10 @@ impl InputBackend for LibinputInputBackend { self.handler = Some(Box::new(handler)); } - fn get_handler(&mut self) -> Option<&mut InputHandler> { + fn get_handler(&mut self) -> Option<&mut backend::InputHandler> { self.handler .as_mut() - .map(|handler| handler as &mut InputHandler) + .map(|handler| handler as &mut backend::InputHandler) } fn clear_handler(&mut self) { @@ -82,19 +293,22 @@ impl InputBackend for LibinputInputBackend { } fn dispatch_new_events(&mut self) -> Result<(), IoError> { + use input::event::EventTrait; + self.context.dispatch()?; + for event in &mut self.context { match event { - Event::Device(device_event) => { + libinput::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 added = device_added_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 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(); @@ -118,9 +332,8 @@ impl InputBackend for LibinputInputBackend { let mut hasher = DefaultHasher::default(); seat_entry.key().hash(&mut hasher); let desc = seat_entry.insert(SeatDesc { - seat: Seat::new(hasher.finish(), new_caps), + seat: backend::Seat::new(hasher.finish(), new_caps), pointer: (0, 0), //FIXME: We should not assume a position. Some backends might force a position on us. - size: (1280, 800), //FIXME: Document the requirement of calling `set_output_metadata` on `on_seat_created`. }); if let Some(ref mut handler) = self.handler { trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat); @@ -130,7 +343,7 @@ impl InputBackend for LibinputInputBackend { } }, DeviceEvent::Removed(device_removed_event) => { - let removed = device_removed_event.into_event().device(); + let removed = device_removed_event.device(); // remove device self.devices.retain(|dev| *dev == removed); @@ -140,9 +353,9 @@ impl InputBackend for LibinputInputBackend { // update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`. if let Some(desc) = self.seats.get_mut(&device_seat) { let caps = desc.seat.capabilities_mut(); - caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Pointer)); - caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Keyboard)); - caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Touch)); + caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Pointer)); + caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Keyboard)); + caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Touch)); } else { panic!("Seat changed that was never created") } @@ -172,107 +385,81 @@ impl InputBackend for LibinputInputBackend { handler.on_input_config_changed(&mut self.devices); } }, - Event::Touch(touch_event) => { + libinput::Event::Touch(touch_event) => { use ::input::event::touch::*; if let Some(ref mut handler) = self.handler { let device_seat = touch_event.device().seat(); - let desc = self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); - trace!(self.logger, "Calling on_touch with {:?}", touch_event); - handler.on_touch(&desc.seat, touch_event.time(), - match touch_event { - TouchEvent::Down(down_event) => BackendTouchEvent::Down { - slot: down_event.slot().map(|x| BackendTouchSlot::new(x)), - x: down_event.x_transformed(desc.size.0), - y: down_event.x_transformed(desc.size.1), - }, - TouchEvent::Motion(motion_event) => BackendTouchEvent::Motion { - slot: motion_event.slot().map(|x| BackendTouchSlot::new(x)), - x: motion_event.x_transformed(desc.size.0), - y: motion_event.x_transformed(desc.size.1), - }, - TouchEvent::Up(up_event) => BackendTouchEvent::Up { - slot: up_event.slot().map(|x| BackendTouchSlot::new(x)), - }, - TouchEvent::Cancel(cancel_event) => BackendTouchEvent::Cancel { - slot: cancel_event.slot().map(|x| BackendTouchSlot::new(x)), - }, - TouchEvent::Frame(_) => ::backend::input::TouchEvent::Frame, - }) + let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat; + match touch_event { + TouchEvent::Down(down_event) => { + trace!(self.logger, "Calling on_touch_down with {:?}", down_event); + handler.on_touch_down(seat, down_event) + }, + TouchEvent::Motion(motion_event) => { + trace!(self.logger, "Calling on_touch_motion with {:?}", motion_event); + handler.on_touch_motion(seat, motion_event) + }, + TouchEvent::Up(up_event) => { + trace!(self.logger, "Calling on_touch_up with {:?}", up_event); + handler.on_touch_up(seat, up_event) + }, + TouchEvent::Cancel(cancel_event) => { + trace!(self.logger, "Calling on_touch_cancel with {:?}", cancel_event); + handler.on_touch_cancel(seat, cancel_event) + }, + TouchEvent::Frame(frame_event) => { + trace!(self.logger, "Calling on_touch_frame with {:?}", frame_event); + handler.on_touch_frame(seat, frame_event) + }, + } } }, - Event::Keyboard(keyboard_event) => { + libinput::Event::Keyboard(keyboard_event) => { use ::input::event::keyboard::*; match keyboard_event { KeyboardEvent::Key(key_event) => { if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event); let device_seat = key_event.device().seat(); - handler.on_keyboard_key(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat, - key_event.time(), key_event.key(), key_event.key_state().into(), key_event.seat_key_count()); + let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat; + trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event); + handler.on_keyboard_key(seat, key_event); } } } }, - Event::Pointer(pointer_event) => { + libinput::Event::Pointer(pointer_event) => { use ::input::event::pointer::*; - match pointer_event { - PointerEvent::Motion(motion_event) => { - let device_seat = motion_event.device().seat(); - let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); - desc.pointer.0 += motion_event.dx() as u32; - desc.pointer.1 += motion_event.dy() as u32; - if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_pointer_move with {:?}", desc.pointer); - handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer); - } - }, - PointerEvent::MotionAbsolute(motion_event) => { - let device_seat = motion_event.device().seat(); - let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); - desc.pointer = ( - motion_event.absolute_x_transformed(desc.size.0) as u32, - motion_event.absolute_y_transformed(desc.size.1) as u32, - ); - if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_pointer_move with {:?}", desc.pointer); - handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer); - } - }, - PointerEvent::Axis(axis_event) => { - if let Some(ref mut handler) = self.handler { - let device_seat = axis_event.device().seat(); - let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); + if let Some(ref mut handler) = self.handler { + let device_seat = pointer_event.device().seat(); + let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat; + match pointer_event { + PointerEvent::Motion(motion_event) => { + trace!(self.logger, "Calling on_pointer_move with {:?}", motion_event); + handler.on_pointer_move(seat, motion_event); + }, + PointerEvent::MotionAbsolute(motion_abs_event) => { + trace!(self.logger, "Calling on_pointer_move_absolute with {:?}", motion_abs_event); + handler.on_pointer_move_absolute(seat, motion_abs_event); + }, + PointerEvent::Axis(axis_event) => { if axis_event.has_axis(Axis::Vertical) { - let value = match axis_event.axis_source() { - AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Vertical), - AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Vertical).unwrap(), - }; - trace!(self.logger, "Calling on_pointer_scroll on Axis::Vertical from {:?} with {:?}", axis_event.axis_source(), value); - handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Vertical, - axis_event.axis_source().into(), value); + trace!(self.logger, "Calling on_pointer_axis for Axis::Vertical with {:?}", axis_event); + handler.on_pointer_axis(seat, self::PointerAxisEvent { + axis: Axis::Vertical, + event: axis_event.clone() + }); } if axis_event.has_axis(Axis::Horizontal) { - let value = match axis_event.axis_source() { - AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Horizontal), - AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Horizontal).unwrap(), - }; - trace!(self.logger, "Calling on_pointer_scroll on Axis::Horizontal from {:?} with {:?}", axis_event.axis_source(), value); - handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Horizontal, - axis_event.axis_source().into(), value); + trace!(self.logger, "Calling on_pointer_axis for Axis::Horizontal with {:?}", axis_event); + handler.on_pointer_axis(seat, self::PointerAxisEvent { + axis: Axis::Horizontal, + event: axis_event.clone() + }); } - } - }, - PointerEvent::Button(button_event) => { - if let Some(ref mut handler) = self.handler { - let device_seat = button_event.device().seat(); - let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat"); - trace!(self.logger, "Calling on_pointer_button with {:?}", button_event.button()); - handler.on_pointer_button(&desc.seat, button_event.time(), match button_event.button() { - 0x110 => MouseButton::Left, - 0x111 => MouseButton::Right, - 0x112 => MouseButton::Middle, - x => MouseButton::Other(x as u8), - }, button_event.button_state().into()); + }, + PointerEvent::Button(button_event) => { + trace!(self.logger, "Calling on_pointer_button with {:?}", button_event); + handler.on_pointer_button(seat, button_event); } } } @@ -282,43 +469,42 @@ impl InputBackend for LibinputInputBackend { }; Ok(()) } - - fn set_output_metadata(&mut self, seat: &Seat, output: &Output) { - for desc in self.seats.values_mut() { - if desc.seat == *seat { - desc.size = output.size(); - return; - } - } - panic!("Got metadata for non-existant seat"); - } } -impl From<::input::event::keyboard::KeyState> for ::backend::input::KeyState { - fn from(libinput: ::input::event::keyboard::KeyState) -> Self { +impl From for backend::KeyState { + fn from(libinput: event::keyboard::KeyState) -> Self { match libinput { - ::input::event::keyboard::KeyState::Pressed => ::backend::input::KeyState::Pressed, - ::input::event::keyboard::KeyState::Released => ::backend::input::KeyState::Released, + event::keyboard::KeyState::Pressed => backend::KeyState::Pressed, + event::keyboard::KeyState::Released => backend::KeyState::Released, } } } -impl From<::input::event::pointer::AxisSource> for ::backend::input::AxisSource { - fn from(libinput: ::input::event::pointer::AxisSource) -> Self { +impl From for backend::Axis { + fn from(libinput: event::pointer::Axis) -> Self { match libinput { - ::input::event::pointer::AxisSource::Finger => ::backend::input::AxisSource::Finger, - ::input::event::pointer::AxisSource::Continuous => ::backend::input::AxisSource::Continuous, - ::input::event::pointer::AxisSource::Wheel => ::backend::input::AxisSource::Wheel, - ::input::event::pointer::AxisSource::WheelTilt => ::backend::input::AxisSource::WheelTilt, + event::pointer::Axis::Vertical => backend::Axis::Vertical, + event::pointer::Axis::Horizontal => backend::Axis::Horizontal, } } } -impl From<::input::event::pointer::ButtonState> for ::backend::input::MouseButtonState { - fn from(libinput: ::input::event::pointer::ButtonState) -> Self { +impl From for backend::AxisSource { + fn from(libinput: event::pointer::AxisSource) -> Self { match libinput { - ::input::event::pointer::ButtonState::Pressed => ::backend::input::MouseButtonState::Pressed, - ::input::event::pointer::ButtonState::Released => ::backend::input::MouseButtonState::Released, + 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, + } + } +} + +impl From for backend::MouseButtonState { + fn from(libinput: event::pointer::ButtonState) -> Self { + match libinput { + event::pointer::ButtonState::Pressed => backend::MouseButtonState::Pressed, + event::pointer::ButtonState::Released => backend::MouseButtonState::Released, } } } From 092fc198c319e7a7257f62769b778d80b1ccdbbb Mon Sep 17 00:00:00 2001 From: Drakulix Date: Mon, 24 Apr 2017 00:30:02 +0200 Subject: [PATCH 24/30] Fixup glutin backend and more bugfixes --- src/backend/glutin.rs | 372 +++++++++++++++++++++++++++++++++------- src/backend/input.rs | 190 +++++++++++++++----- src/backend/libinput.rs | 101 +++++------ src/backend/mod.rs | 2 +- 4 files changed, 501 insertions(+), 164 deletions(-) diff --git a/src/backend/glutin.rs b/src/backend/glutin.rs index 7bc4048..88a5780 100644 --- a/src/backend/glutin.rs +++ b/src/backend/glutin.rs @@ -5,11 +5,12 @@ use backend::{SeatInternal, TouchSlotInternal}; use backend::graphics::GraphicsBackend; use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError}; use backend::input::{Axis, AxisSource, InputBackend, InputHandler, KeyState, MouseButton, MouseButtonState, - Seat, SeatCapabilities, TouchEvent, TouchSlot, Output}; + Seat, SeatCapabilities, TouchSlot, Event as BackendEvent, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, TouchDownEvent, TouchUpEvent, TouchMotionEvent, TouchCancelEvent}; use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, PixelFormat as GlutinPixelFormat, MouseCursor}; use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext, HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder}; use nix::c_void; +use std::cmp; use std::error::Error; use std::fmt; use std::rc::Rc; @@ -88,7 +89,7 @@ impl GraphicsBackend for GlutinHeadlessRenderer { Ok(()) } - fn set_cursor_representation(&mut self, cursor: ()) {} + fn set_cursor_representation(&mut self, _cursor: ()) {} } impl OpenglGraphicsBackend for GlutinHeadlessRenderer { @@ -229,15 +230,259 @@ impl fmt::Display for GlutinInputError { pub struct GlutinInputBackend { window: Rc, time_counter: u32, + key_counter: u32, seat: Seat, input_config: (), handler: Option + 'static>>, } +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `KeyboardKeyEvent` +pub struct GlutinKeyboardInputEvent { + time: u32, + key: u8, + count: u32, + state: ElementState, +} + +impl BackendEvent for GlutinKeyboardInputEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl KeyboardKeyEvent for GlutinKeyboardInputEvent { + fn key_code(&self) -> u32 { + self.key as u32 + } + + fn state(&self) -> KeyState { + self.state.into() + } + + fn count(&self) -> u32 { + self.count + } +} + +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `PointerMotionAbsoluteEvent` +pub struct GlutinMouseMovedEvent { + window: Rc, + time: u32, + x: i32, + y: i32, +} + +impl BackendEvent for GlutinMouseMovedEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl PointerMotionAbsoluteEvent for GlutinMouseMovedEvent { + fn x(&self) -> f64 { + self.x as f64 + } + + fn y(&self) -> f64 { + self.y as f64 + } + + fn x_transformed(&self, width: u32) -> u32 { + cmp::min(self.x * width as i32 / self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, 0) as u32 + } + + fn y_transformed(&self, height: u32) -> u32 { + cmp::min(self.y * height as i32 / self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, 0) as u32 + } +} + +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `PointerAxisEvent` +pub struct GlutinMouseWheelEvent { + axis: Axis, + time: u32, + delta: MouseScrollDelta, +} + +impl BackendEvent for GlutinMouseWheelEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl PointerAxisEvent for GlutinMouseWheelEvent { + fn axis(&self) -> Axis { + self.axis + } + + fn source(&self) -> AxisSource { + match self.delta { + MouseScrollDelta::LineDelta(_, _) => AxisSource::Wheel, + MouseScrollDelta::PixelDelta(_, _) => AxisSource::Continuous, + } + } + + fn amount(&self) -> f64 { + match (self.axis, self.delta) { + (Axis::Horizontal, MouseScrollDelta::LineDelta(x, _)) | (Axis::Horizontal, MouseScrollDelta::PixelDelta(x, _)) => x as f64, + (Axis::Vertical, MouseScrollDelta::LineDelta(_, y)) | (Axis::Vertical, MouseScrollDelta::PixelDelta(_, y)) => y as f64, + } + } +} + +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `PointerButtonEvent` +pub struct GlutinMouseInputEvent { + time: u32, + button: GlutinMouseButton, + state: ElementState, +} + +impl BackendEvent for GlutinMouseInputEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl PointerButtonEvent for GlutinMouseInputEvent { + fn button(&self) -> MouseButton { + self.button.into() + } + + fn state(&self) -> MouseButtonState { + self.state.into() + } +} + +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `TouchDownEvent` +pub struct GlutinTouchStartedEvent { + window: Rc, + time: u32, + location: (f64, f64), + id: u64, +} + +impl BackendEvent for GlutinTouchStartedEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl TouchDownEvent for GlutinTouchStartedEvent { + fn slot(&self) -> Option { + Some(TouchSlot::new(self.id)) + } + + fn x(&self) -> f64 { + self.location.0 + } + + fn y(&self) -> f64 { + self.location.1 + } + + fn x_transformed(&self, width: u32) -> u32 { + cmp::min(self.location.0 as i32 * width as i32 / self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, 0) as u32 + } + + fn y_transformed(&self, height: u32) -> u32 { + cmp::min(self.location.1 as i32 * height as i32 / self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, 0) as u32 + } +} + +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `TouchMotionEvent` +pub struct GlutinTouchMovedEvent { + window: Rc, + time: u32, + location: (f64, f64), + id: u64, +} + +impl BackendEvent for GlutinTouchMovedEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl TouchMotionEvent for GlutinTouchMovedEvent { + fn slot(&self) -> Option { + Some(TouchSlot::new(self.id)) + } + + fn x(&self) -> f64 { + self.location.0 + } + + fn y(&self) -> f64 { + self.location.1 + } + + fn x_transformed(&self, width: u32) -> u32 { + self.location.0 as u32 * width / self.window.get_inner_size_points().unwrap_or((width, 0)).0 + } + + fn y_transformed(&self, height: u32) -> u32 { + self.location.1 as u32 * height / self.window.get_inner_size_points().unwrap_or((0, height)).1 + } +} + +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `TouchUpEvent` +pub struct GlutinTouchEndedEvent { + time: u32, + id: u64, +} + +impl BackendEvent for GlutinTouchEndedEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl TouchUpEvent for GlutinTouchEndedEvent { + fn slot(&self) -> Option { + Some(TouchSlot::new(self.id)) + } +} + +#[derive(Clone)] +/// Glutin-Backend internal event wrapping glutin's types into a `TouchCancelEvent` +pub struct GlutinTouchCancelledEvent { + time: u32, + id: u64, +} + +impl BackendEvent for GlutinTouchCancelledEvent { + fn time(&self) -> u32 { + self.time + } +} + +impl TouchCancelEvent for GlutinTouchCancelledEvent { + fn slot(&self) -> Option { + Some(TouchSlot::new(self.id)) + } +} + impl InputBackend for GlutinInputBackend { type InputConfig = (); type EventError = GlutinInputError; + type KeyboardKeyEvent = GlutinKeyboardInputEvent; + type PointerAxisEvent = GlutinMouseWheelEvent; + type PointerButtonEvent = GlutinMouseInputEvent; + type PointerMotionEvent = (); + type PointerMotionAbsoluteEvent = GlutinMouseMovedEvent; + type TouchDownEvent = GlutinTouchStartedEvent; + type TouchUpEvent = GlutinTouchEndedEvent; + type TouchMotionEvent = GlutinTouchMovedEvent; + type TouchCancelEvent = GlutinTouchCancelledEvent; + type TouchFrameEvent = (); + fn set_handler + 'static>(&mut self, mut handler: H) { if self.handler.is_some() { self.clear_handler(); @@ -279,104 +524,104 @@ impl InputBackend for GlutinInputBackend { if let Some(ref mut handler) = self.handler { match event { Event::KeyboardInput(state, key_code, _) => { + match state { + ElementState::Pressed => self.key_counter += 1, + ElementState::Released => self.key_counter = self.key_counter.checked_sub(1).unwrap_or(0), + }; handler.on_keyboard_key(&self.seat, - self.time_counter, - key_code as u32, - state.into(), - 1) + GlutinKeyboardInputEvent { + time: self.time_counter, + key: key_code, + count: self.key_counter, + state: state, + }) } Event::MouseMoved(x, y) => { - handler.on_pointer_move(&self.seat, self.time_counter, (x as u32, y as u32)) + handler.on_pointer_move_absolute(&self.seat, GlutinMouseMovedEvent { + window: self.window.clone(), + time: self.time_counter, + x: x, + y: y, + }) } Event::MouseWheel(delta, _) => { + let event = GlutinMouseWheelEvent { + axis: Axis::Horizontal, + time: self.time_counter, + delta: delta, + }; match delta { - MouseScrollDelta::LineDelta(x, y) => { + MouseScrollDelta::LineDelta(x, y) | MouseScrollDelta::PixelDelta(x, y) => { if x != 0.0 { - handler.on_pointer_scroll(&self.seat, - self.time_counter, - Axis::Horizontal, - AxisSource::Wheel, - x as f64); + handler.on_pointer_axis(&self.seat, event.clone()); } if y != 0.0 { - handler.on_pointer_scroll(&self.seat, - self.time_counter, - Axis::Vertical, - AxisSource::Wheel, - y as f64); - } - } - MouseScrollDelta::PixelDelta(x, y) => { - if x != 0.0 { - handler.on_pointer_scroll(&self.seat, - self.time_counter, - Axis::Vertical, - AxisSource::Continuous, - x as f64); - } - if y != 0.0 { - handler.on_pointer_scroll(&self.seat, - self.time_counter, - Axis::Horizontal, - AxisSource::Continuous, - y as f64); + handler.on_pointer_axis(&self.seat, event); } } } } Event::MouseInput(state, button) => { - handler.on_pointer_button(&self.seat, self.time_counter, button.into(), state.into()) + handler.on_pointer_button(&self.seat, GlutinMouseInputEvent { + time: self.time_counter, + button: button, + state: state, + }) } Event::Touch(Touch { phase: TouchPhase::Started, location: (x, y), id, }) => { - handler.on_touch(&self.seat, - self.time_counter, - TouchEvent::Down { - slot: Some(TouchSlot::new(id as u32)), - x: x, - y: y, - }) + handler.on_touch_down(&self.seat, + GlutinTouchStartedEvent { + window: self.window.clone(), + time: self.time_counter, + location: (x, y), + id: id, + }) } Event::Touch(Touch { phase: TouchPhase::Moved, location: (x, y), id, }) => { - handler.on_touch(&self.seat, - self.time_counter, - TouchEvent::Motion { - slot: Some(TouchSlot::new(id as u32)), - x: x, - y: y, - }) + handler.on_touch_motion(&self.seat, + GlutinTouchMovedEvent { + window: self.window.clone(), + time: self.time_counter, + location: (x, y), + id: id, + }) } Event::Touch(Touch { phase: TouchPhase::Ended, location: (x, y), id, }) => { - handler.on_touch(&self.seat, - self.time_counter, - TouchEvent::Motion { - slot: Some(TouchSlot::new(id as u32)), - x: x, - y: y, - }); - handler.on_touch(&self.seat, - self.time_counter, - TouchEvent::Up { slot: Some(TouchSlot::new(id as u32)) }); + handler.on_touch_motion(&self.seat, + GlutinTouchMovedEvent { + window: self.window.clone(), + time: self.time_counter, + location: (x, y), + id: id, + }); + handler.on_touch_up(&self.seat, + GlutinTouchEndedEvent { + time: self.time_counter, + id: id, + }); } Event::Touch(Touch { phase: TouchPhase::Cancelled, id, .. }) => { - handler.on_touch(&self.seat, - self.time_counter, - TouchEvent::Cancel { slot: Some(TouchSlot::new(id as u32)) }) + handler.on_touch_cancel(&self.seat, + GlutinTouchCancelledEvent { + time: self.time_counter, + id: id, + }) } Event::Closed => return Err(GlutinInputError::WindowClosed), _ => {} @@ -386,8 +631,6 @@ impl InputBackend for GlutinInputBackend { } Ok(()) } - - fn set_output_metadata(&mut self, seat: &Seat, output: &Output) {} } impl GlutinInputBackend { @@ -395,6 +638,7 @@ impl GlutinInputBackend { GlutinInputBackend { window: window, time_counter: 0, + key_counter: 0, seat: Seat::new(0, SeatCapabilities { pointer: true, diff --git a/src/backend/input.rs b/src/backend/input.rs index f98242c..701db44 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -3,7 +3,6 @@ use backend::{SeatInternal, TouchSlotInternal}; use std::error::Error; -use std::hash::Hash; /// A seat describes a group of input devices and at least one /// graphics device belonging together. @@ -76,6 +75,12 @@ pub trait Event { fn time(&self) -> u32; } +impl Event for () { + fn time(&self) -> u32 { + unreachable!() + } +} + /// State of key on a keyboard. Either pressed or released #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum KeyState { @@ -95,6 +100,20 @@ pub trait KeyboardKeyEvent: Event { fn count(&self) -> u32; } +impl KeyboardKeyEvent for () { + fn key_code(&self) -> u32 { + unreachable!() + } + + fn state(&self) -> KeyState { + unreachable!() + } + + fn count(&self) -> u32 { + unreachable!() + } +} + /// A particular mouse button #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum MouseButton { @@ -125,6 +144,16 @@ pub trait PointerButtonEvent: Event { fn state(&self) -> MouseButtonState; } +impl PointerButtonEvent for () { + fn button(&self) -> MouseButton { + unreachable!() + } + + fn state(&self) -> MouseButtonState { + unreachable!() + } +} + /// Axis when scrolling #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Axis { @@ -177,6 +206,20 @@ pub trait PointerAxisEvent: Event { fn amount(&self) -> f64; } +impl PointerAxisEvent for () { + fn axis(&self) -> Axis { + unreachable!() + } + + fn source(&self) -> AxisSource { + unreachable!() + } + + fn amount(&self) -> f64 { + unreachable!() + } +} + /// Trait for pointer events generated by relative device movement. pub trait PointerMotionEvent: Event { /// Delta between the last and new pointer device position interpreted as pixel movement @@ -190,6 +233,16 @@ pub trait PointerMotionEvent: Event { fn delta_y(&self) -> u32; } +impl PointerMotionEvent for () { + fn delta_x(&self) -> u32 { + unreachable!() + } + + fn delta_y(&self) -> u32 { + unreachable!() + } +} + /// Trait for pointer events generated by absolute device positioning. pub trait PointerMotionAbsoluteEvent: Event { /// Device position in it's original coordinate space. @@ -224,6 +277,24 @@ pub trait PointerMotionAbsoluteEvent: Event { fn y_transformed(&self, height: u32) -> u32; } +impl PointerMotionAbsoluteEvent for () { + fn x(&self) -> f64 { + unreachable!() + } + + fn y(&self) -> f64 { + unreachable!() + } + + fn x_transformed(&self, _width: u32) -> u32 { + unreachable!() + } + + fn y_transformed(&self, _height: u32) -> u32 { + unreachable!() + } +} + /// Slot of a different touch event. /// /// Touch events are groubed by slots, usually to identify different @@ -231,11 +302,11 @@ pub trait PointerMotionAbsoluteEvent: Event { /// be interpreted in the context of other events on the same slot. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TouchSlot { - id: u32, + id: u64, } impl TouchSlotInternal for TouchSlot { - fn new(id: u32) -> Self { + fn new(id: u64) -> Self { TouchSlot { id: id } } } @@ -277,6 +348,29 @@ pub trait TouchDownEvent: Event { fn y_transformed(&self, height: u32) -> u32; } +impl TouchDownEvent for () { + fn slot(&self) -> Option { + unreachable!() + } + + fn x(&self) -> f64 { + unreachable!() + } + + fn y(&self) -> f64 { + unreachable!() + } + + fn x_transformed(&self, _width: u32) -> u32 { + unreachable!() + } + + fn y_transformed(&self, _height: u32) -> u32 { + unreachable!() + } +} + +/// Trait for touch events regarding movement on the screen pub trait TouchMotionEvent: Event { /// `TouchSlot`, if the device has multi-touch capabilities fn slot(&self) -> Option; @@ -313,60 +407,56 @@ pub trait TouchMotionEvent: Event { fn y_transformed(&self, height: u32) -> u32; } +impl TouchMotionEvent for () { + fn slot(&self) -> Option { + unreachable!() + } + + fn x(&self) -> f64 { + unreachable!() + } + + fn y(&self) -> f64 { + unreachable!() + } + + fn x_transformed(&self, _width: u32) -> u32 { + unreachable!() + } + + fn y_transformed(&self, _height: u32) -> u32 { + unreachable!() + } +} + +/// Trait for touch events finishing. pub trait TouchUpEvent: Event { /// `TouchSlot`, if the device has multi-touch capabilities fn slot(&self) -> Option; } +impl TouchUpEvent for () { + fn slot(&self) -> Option { + unreachable!() + } +} + +/// Trait for touch events cancelling the chain pub trait TouchCancelEvent: Event { /// `TouchSlot`, if the device has multi-touch capabilities fn slot(&self) -> Option; } +impl TouchCancelEvent for () { + fn slot(&self) -> Option { + unreachable!() + } +} + +/// Trait for touch frame events pub trait TouchFrameEvent: Event {} -/// Touch event -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum TouchEvent { - /// The start of an event at a given position (x, y). - /// - /// If the device has multi-touch capabilities a slot is given. - Down { - /// `TouchSlot`, if the device has multi-touch capabilities - slot: Option, - /// Absolute x-coordinate of the touch position. - x: f64, - /// Absolute y-coordinate of the touch position. - y: f64, - }, - /// Movement of a touch on the device surface to a given position (x, y). - /// - /// If the device has multi-touch capabilities a slot is given. - Motion { - /// `TouchSlot`, if the device has multi-touch capabilities - slot: Option, - /// Absolute x-coordinate of the final touch position after the motion. - x: f64, - /// Absolute y-coordinate of the final touch position after the motion. - y: f64, - }, - /// Stop of an event chain. - /// - /// If the device has multi-touch capabilities a slot is given. - Up { - /// `TouchSlot`, if the device has multi-touch capabilities - slot: Option, - }, - /// Cancel of an event chain. All previous events in the chain should be ignored. - /// - /// If the device has multi-touch capabilities a slot is given. - Cancel { - /// `TouchSlot`, if the device has multi-touch capabilities - slot: Option, - }, - /// Signals the end of a set of touchpoints at one device sample time. - Frame, -} +impl TouchFrameEvent for () {} /// Trait that describes objects providing a source of input events. All input backends /// need to implemenent this and provide the same base gurantees about the presicion of @@ -378,15 +468,25 @@ pub trait InputBackend: Sized { /// Type representing errors that may be returned when processing events type EventError: Error; + /// Type representing keyboard events type KeyboardKeyEvent: KeyboardKeyEvent; + /// Type representing axis events on pointer devices type PointerAxisEvent: PointerAxisEvent; + /// Type representing button events on pointer devices type PointerButtonEvent: PointerButtonEvent; + /// Type representing motion events of pointer devices type PointerMotionEvent: PointerMotionEvent; + /// Type representing motion events of pointer devices type PointerMotionAbsoluteEvent: PointerMotionAbsoluteEvent; + /// Type representing touch events starting type TouchDownEvent: TouchDownEvent; + /// Type representing touch events ending type TouchUpEvent: TouchUpEvent; + /// Type representing touch events from moving type TouchMotionEvent: TouchMotionEvent; + /// Type representing cancelling of touch events type TouchCancelEvent: TouchCancelEvent; + /// Type representing touch frame events type TouchFrameEvent: TouchFrameEvent; /// Sets a new handler for this `InputBackend` diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 224889b..80008a8 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -9,11 +9,6 @@ use std::io::Error as IoError; use std::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::hash::{Hash, Hasher}; -struct SeatDesc { - seat: backend::Seat, - pointer: (u32, u32), -} - /// Libinput based `InputBackend`. /// /// Tracks input of all devices given manually or via a udev seat to a provided libinput @@ -21,7 +16,7 @@ struct SeatDesc { pub struct LibinputInputBackend { context: libinput::Libinput, devices: Vec, - seats: HashMap, + seats: HashMap, handler: Option + 'static>>, logger: ::slog::Logger, } @@ -46,7 +41,7 @@ impl LibinputInputBackend { impl backend::Event for event::keyboard::KeyboardKeyEvent { fn time(&self) -> u32 { - self.time() + event::keyboard::KeyboardEventTrait::time(self) } } @@ -66,6 +61,7 @@ impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent { } } +/// Wrapper for libinput pointer axis events to implement `backend::input::PointerAxisEvent` pub struct PointerAxisEvent { axis: event::pointer::Axis, event: event::pointer::PointerAxisEvent, @@ -99,7 +95,7 @@ impl<'a> backend::PointerAxisEvent for PointerAxisEvent { impl backend::Event for event::pointer::PointerButtonEvent { fn time(&self) -> u32 { - self.time() + event::pointer::PointerEventTrait::time(self) } } @@ -114,13 +110,13 @@ impl backend::PointerButtonEvent for event::pointer::PointerButtonEvent { } fn state(&self) -> backend::MouseButtonState { - self.state().into() + self.button_state().into() } } impl backend::Event for event::pointer::PointerMotionEvent { fn time(&self) -> u32 { - self.time() + event::pointer::PointerEventTrait::time(self) } } @@ -135,7 +131,7 @@ impl backend::PointerMotionEvent for event::pointer::PointerMotionEvent { impl backend::Event for event::pointer::PointerMotionAbsoluteEvent { fn time(&self) -> u32 { - self.time() + event::pointer::PointerEventTrait::time(self) } } @@ -159,87 +155,87 @@ impl backend::PointerMotionAbsoluteEvent for event::pointer::PointerMotionAbsolu impl backend::Event for event::touch::TouchDownEvent { fn time(&self) -> u32 { - self.time() + event::touch::TouchEventTrait::time(self) } } impl backend::TouchDownEvent for event::touch::TouchDownEvent { fn slot(&self) -> Option { - self.slot().into() + event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) } fn x(&self) -> f64 { - self.x() + event::touch::TouchEventPosition::x(self) } fn y(&self) -> f64 { - self.y() + event::touch::TouchEventPosition::y(self) } fn x_transformed(&self, width: u32) -> u32 { - self.x_transformed(width) as u32 + event::touch::TouchEventPosition::x_transformed(self, width) as u32 } fn y_transformed(&self, height: u32) -> u32 { - self.y_transformed(height) as u32 + event::touch::TouchEventPosition::y_transformed(self, height) as u32 } } impl backend::Event for event::touch::TouchMotionEvent { fn time(&self) -> u32 { - self.time() + event::touch::TouchEventTrait::time(self) } } impl backend::TouchMotionEvent for event::touch::TouchMotionEvent { fn slot(&self) -> Option { - self.slot().into() + event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) } fn x(&self) -> f64 { - self.x() + event::touch::TouchEventPosition::x(self) } fn y(&self) -> f64 { - self.y() + event::touch::TouchEventPosition::y(self) } fn x_transformed(&self, width: u32) -> u32 { - self.x_transformed(width) as u32 + event::touch::TouchEventPosition::x_transformed(self, width) as u32 } fn y_transformed(&self, height: u32) -> u32 { - self.y_transformed(height) as u32 + event::touch::TouchEventPosition::y_transformed(self, height) as u32 } } impl backend::Event for event::touch::TouchUpEvent { fn time(&self) -> u32 { - self.time() + event::touch::TouchEventTrait::time(self) } } impl backend::TouchUpEvent for event::touch::TouchUpEvent { fn slot(&self) -> Option { - self.slot().into() + event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) } } impl backend::Event for event::touch::TouchCancelEvent { fn time(&self) -> u32 { - self.time() + event::touch::TouchEventTrait::time(self) } } impl backend::TouchCancelEvent for event::touch::TouchCancelEvent { fn slot(&self) -> Option { - self.slot().into() + event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64)) } } impl backend::Event for event::touch::TouchFrameEvent { fn time(&self) -> u32 { - self.time() + event::touch::TouchEventTrait::time(self) } } @@ -265,9 +261,9 @@ impl backend::InputBackend for LibinputInputBackend { self.clear_handler(); } info!(self.logger, "New input handler set."); - for desc in self.seats.values() { - trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat); - handler.on_seat_created(&desc.seat); + for seat in self.seats.values() { + trace!(self.logger, "Calling on_seat_created with {:?}", seat); + handler.on_seat_created(&seat); } self.handler = Some(Box::new(handler)); } @@ -280,9 +276,9 @@ impl backend::InputBackend for LibinputInputBackend { fn clear_handler(&mut self) { if let Some(mut handler) = self.handler.take() { - for desc in self.seats.values() { - trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat); - handler.on_seat_destroyed(&desc.seat); + for seat in self.seats.values() { + trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat); + handler.on_seat_destroyed(&seat); } info!(self.logger, "Removing input handler"); } @@ -318,26 +314,23 @@ impl backend::InputBackend for LibinputInputBackend { Entry::Occupied(mut seat_entry) => { let old_seat = seat_entry.get_mut(); { - let caps = old_seat.seat.capabilities_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; } if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat.seat); - handler.on_seat_changed(&old_seat.seat); + trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat); + handler.on_seat_changed(&old_seat); } }, Entry::Vacant(seat_entry) => { let mut hasher = DefaultHasher::default(); seat_entry.key().hash(&mut hasher); - let desc = seat_entry.insert(SeatDesc { - seat: backend::Seat::new(hasher.finish(), new_caps), - pointer: (0, 0), //FIXME: We should not assume a position. Some backends might force a position on us. - }); + let seat = seat_entry.insert(backend::Seat::new(hasher.finish(), new_caps)); if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat); - handler.on_seat_created(&desc.seat); + trace!(self.logger, "Calling on_seat_created with {:?}", seat); + handler.on_seat_created(&seat); } } } @@ -351,8 +344,8 @@ impl backend::InputBackend for LibinputInputBackend { let device_seat = removed.seat(); // update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`. - if let Some(desc) = self.seats.get_mut(&device_seat) { - let caps = desc.seat.capabilities_mut(); + if let Some(seat) = self.seats.get_mut(&device_seat) { + let caps = seat.capabilities_mut(); caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Pointer)); caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Keyboard)); caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Touch)); @@ -363,10 +356,10 @@ impl backend::InputBackend for LibinputInputBackend { // 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(desc) = self.seats.remove(&device_seat) { + if let Some(seat) = self.seats.remove(&device_seat) { if let Some(ref mut handler) = self.handler { - trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat); - handler.on_seat_destroyed(&desc.seat); + trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat); + handler.on_seat_destroyed(&seat); } } else { panic!("Seat destroyed that was never created"); @@ -374,9 +367,9 @@ impl backend::InputBackend for LibinputInputBackend { } else { // it has, notify about updates if let Some(ref mut handler) = self.handler { - let desc = self.seats.get(&device_seat).unwrap(); - trace!(self.logger, "Calling on_seat_changed with {:?}", desc.seat); - handler.on_seat_changed(&desc.seat); + let seat = self.seats.get(&device_seat).unwrap(); + trace!(self.logger, "Calling on_seat_changed with {:?}", seat); + handler.on_seat_changed(&seat); } } }, @@ -389,7 +382,7 @@ impl backend::InputBackend for LibinputInputBackend { use ::input::event::touch::*; if let Some(ref mut handler) = self.handler { let device_seat = touch_event.device().seat(); - let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat; + let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); match touch_event { TouchEvent::Down(down_event) => { trace!(self.logger, "Calling on_touch_down with {:?}", down_event); @@ -420,7 +413,7 @@ impl backend::InputBackend for LibinputInputBackend { KeyboardEvent::Key(key_event) => { if let Some(ref mut handler) = self.handler { let device_seat = key_event.device().seat(); - let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat; + let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event); handler.on_keyboard_key(seat, key_event); } @@ -431,7 +424,7 @@ impl backend::InputBackend for LibinputInputBackend { use ::input::event::pointer::*; if let Some(ref mut handler) = self.handler { let device_seat = pointer_event.device().seat(); - let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat; + let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); match pointer_event { PointerEvent::Motion(motion_event) => { trace!(self.logger, "Calling on_pointer_move with {:?}", motion_event); diff --git a/src/backend/mod.rs b/src/backend/mod.rs index bf235bb..c91fc91 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -33,5 +33,5 @@ trait SeatInternal { } trait TouchSlotInternal { - fn new(id: u32) -> Self; + fn new(id: u64) -> Self; } From 29ac97b4a73364096bb457a8a6bd0f979cf60f9f Mon Sep 17 00:00:00 2001 From: Drakulix Date: Wed, 26 Apr 2017 19:48:15 +0200 Subject: [PATCH 25/30] Added libudev to travis for buildings libinput --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 26e07a2..65c23e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ addons: apt: packages: - libwayland-dev + - libudev-dev branches: only: @@ -59,4 +60,3 @@ notifications: on_success: change on_failure: always on_start: never - From 4c5e2be11e8bb90a4a753db0069d256a57bfc44d Mon Sep 17 00:00:00 2001 From: Drakulix Date: Wed, 26 Apr 2017 20:09:57 +0200 Subject: [PATCH 26/30] Update libinput to v0.1.1 --- Cargo.toml | 2 +- src/backend/libinput.rs | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a72b80a..3527288 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ slog = { version = "2.0.0" } slog-stdlog = "2.0.0-0.2" glutin = { version = "~0.7.4", optional = true } glium = { version = "~0.16.0", optional = true } -input = { version = "0.1", optional = true } +input = { version = "~0.1.1", optional = true } clippy = { version = "*", optional = true } [dev-dependencies] diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 80008a8..aa4a5f5 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -8,6 +8,7 @@ use input::event; use std::io::Error as IoError; use std::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::hash::{Hash, Hasher}; +use std::rc::Rc; /// Libinput based `InputBackend`. /// @@ -64,7 +65,7 @@ impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent { /// Wrapper for libinput pointer axis events to implement `backend::input::PointerAxisEvent` pub struct PointerAxisEvent { axis: event::pointer::Axis, - event: event::pointer::PointerAxisEvent, + event: Rc, } impl<'a> backend::Event for PointerAxisEvent { @@ -435,18 +436,19 @@ impl backend::InputBackend for LibinputInputBackend { handler.on_pointer_move_absolute(seat, motion_abs_event); }, PointerEvent::Axis(axis_event) => { - if axis_event.has_axis(Axis::Vertical) { - trace!(self.logger, "Calling on_pointer_axis for Axis::Vertical with {:?}", axis_event); + let rc_axis_event = Rc::new(axis_event); + if rc_axis_event.has_axis(Axis::Vertical) { + trace!(self.logger, "Calling on_pointer_axis for Axis::Vertical with {:?}", *rc_axis_event); handler.on_pointer_axis(seat, self::PointerAxisEvent { axis: Axis::Vertical, - event: axis_event.clone() + event: rc_axis_event.clone() }); } - if axis_event.has_axis(Axis::Horizontal) { - trace!(self.logger, "Calling on_pointer_axis for Axis::Horizontal with {:?}", axis_event); + if rc_axis_event.has_axis(Axis::Horizontal) { + trace!(self.logger, "Calling on_pointer_axis for Axis::Horizontal with {:?}", *rc_axis_event); handler.on_pointer_axis(seat, self::PointerAxisEvent { axis: Axis::Horizontal, - event: axis_event.clone() + event: rc_axis_event.clone() }); } }, From f7d3b3dee3bc44a526ede18b42930619e9b758e2 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Wed, 26 Apr 2017 20:10:22 +0200 Subject: [PATCH 27/30] Fix formatting --- src/backend/glutin.rs | 148 +++++++++++++++++++------------ src/backend/graphics/opengl.rs | 2 +- src/backend/graphics/software.rs | 4 +- src/backend/input.rs | 4 +- src/backend/libinput.rs | 139 ++++++++++++++++++----------- 5 files changed, 186 insertions(+), 111 deletions(-) diff --git a/src/backend/glutin.rs b/src/backend/glutin.rs index 88a5780..88cb398 100644 --- a/src/backend/glutin.rs +++ b/src/backend/glutin.rs @@ -4,9 +4,12 @@ use backend::{SeatInternal, TouchSlotInternal}; use backend::graphics::GraphicsBackend; use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError}; -use backend::input::{Axis, AxisSource, InputBackend, InputHandler, KeyState, MouseButton, MouseButtonState, - Seat, SeatCapabilities, TouchSlot, Event as BackendEvent, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, TouchDownEvent, TouchUpEvent, TouchMotionEvent, TouchCancelEvent}; -use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, PixelFormat as GlutinPixelFormat, MouseCursor}; +use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, + KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, + PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, + TouchMotionEvent, TouchSlot, TouchUpEvent}; +use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, MouseCursor, + PixelFormat as GlutinPixelFormat}; use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext, HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder}; use nix::c_void; @@ -85,7 +88,7 @@ impl GraphicsBackend for GlutinHeadlessRenderer { type CursorFormat = (); fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> { - //FIXME: Maybe save position? Is it of any use? + // FIXME: Maybe save position? Is it of any use? Ok(()) } @@ -290,11 +293,21 @@ impl PointerMotionAbsoluteEvent for GlutinMouseMovedEvent { } fn x_transformed(&self, width: u32) -> u32 { - cmp::min(self.x * width as i32 / self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, 0) as u32 + cmp::min(self.x * width as i32 / + self.window + .get_inner_size_points() + .unwrap_or((width, 0)) + .0 as i32, + 0) as u32 } fn y_transformed(&self, height: u32) -> u32 { - cmp::min(self.y * height as i32 / self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, 0) as u32 + cmp::min(self.y * height as i32 / + self.window + .get_inner_size_points() + .unwrap_or((0, height)) + .1 as i32, + 0) as u32 } } @@ -326,8 +339,10 @@ impl PointerAxisEvent for GlutinMouseWheelEvent { fn amount(&self) -> f64 { match (self.axis, self.delta) { - (Axis::Horizontal, MouseScrollDelta::LineDelta(x, _)) | (Axis::Horizontal, MouseScrollDelta::PixelDelta(x, _)) => x as f64, - (Axis::Vertical, MouseScrollDelta::LineDelta(_, y)) | (Axis::Vertical, MouseScrollDelta::PixelDelta(_, y)) => y as f64, + (Axis::Horizontal, MouseScrollDelta::LineDelta(x, _)) | + (Axis::Horizontal, MouseScrollDelta::PixelDelta(x, _)) => x as f64, + (Axis::Vertical, MouseScrollDelta::LineDelta(_, y)) | + (Axis::Vertical, MouseScrollDelta::PixelDelta(_, y)) => y as f64, } } } @@ -385,11 +400,21 @@ impl TouchDownEvent for GlutinTouchStartedEvent { } fn x_transformed(&self, width: u32) -> u32 { - cmp::min(self.location.0 as i32 * width as i32 / self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, 0) as u32 + cmp::min(self.location.0 as i32 * width as i32 / + self.window + .get_inner_size_points() + .unwrap_or((width, 0)) + .0 as i32, + 0) as u32 } fn y_transformed(&self, height: u32) -> u32 { - cmp::min(self.location.1 as i32 * height as i32 / self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, 0) as u32 + cmp::min(self.location.1 as i32 * height as i32 / + self.window + .get_inner_size_points() + .unwrap_or((0, height)) + .1 as i32, + 0) as u32 } } @@ -422,11 +447,19 @@ impl TouchMotionEvent for GlutinTouchMovedEvent { } fn x_transformed(&self, width: u32) -> u32 { - self.location.0 as u32 * width / self.window.get_inner_size_points().unwrap_or((width, 0)).0 + self.location.0 as u32 * width / + self.window + .get_inner_size_points() + .unwrap_or((width, 0)) + .0 } fn y_transformed(&self, height: u32) -> u32 { - self.location.1 as u32 * height / self.window.get_inner_size_points().unwrap_or((0, height)).1 + self.location.1 as u32 * height / + self.window + .get_inner_size_points() + .unwrap_or((0, height)) + .1 } } @@ -526,7 +559,9 @@ impl InputBackend for GlutinInputBackend { Event::KeyboardInput(state, key_code, _) => { match state { ElementState::Pressed => self.key_counter += 1, - ElementState::Released => self.key_counter = self.key_counter.checked_sub(1).unwrap_or(0), + ElementState::Released => { + self.key_counter = self.key_counter.checked_sub(1).unwrap_or(0) + } }; handler.on_keyboard_key(&self.seat, GlutinKeyboardInputEvent { @@ -537,21 +572,23 @@ impl InputBackend for GlutinInputBackend { }) } Event::MouseMoved(x, y) => { - handler.on_pointer_move_absolute(&self.seat, GlutinMouseMovedEvent { - window: self.window.clone(), - time: self.time_counter, - x: x, - y: y, - }) + handler.on_pointer_move_absolute(&self.seat, + GlutinMouseMovedEvent { + window: self.window.clone(), + time: self.time_counter, + x: x, + y: y, + }) } Event::MouseWheel(delta, _) => { let event = GlutinMouseWheelEvent { - axis: Axis::Horizontal, - time: self.time_counter, - delta: delta, - }; + axis: Axis::Horizontal, + time: self.time_counter, + delta: delta, + }; match delta { - MouseScrollDelta::LineDelta(x, y) | MouseScrollDelta::PixelDelta(x, y) => { + MouseScrollDelta::LineDelta(x, y) | + MouseScrollDelta::PixelDelta(x, y) => { if x != 0.0 { handler.on_pointer_axis(&self.seat, event.clone()); } @@ -562,11 +599,12 @@ impl InputBackend for GlutinInputBackend { } } Event::MouseInput(state, button) => { - handler.on_pointer_button(&self.seat, GlutinMouseInputEvent { - time: self.time_counter, - button: button, - state: state, - }) + handler.on_pointer_button(&self.seat, + GlutinMouseInputEvent { + time: self.time_counter, + button: button, + state: state, + }) } Event::Touch(Touch { phase: TouchPhase::Started, @@ -574,12 +612,12 @@ impl InputBackend for GlutinInputBackend { id, }) => { handler.on_touch_down(&self.seat, - GlutinTouchStartedEvent { - window: self.window.clone(), - time: self.time_counter, - location: (x, y), - id: id, - }) + GlutinTouchStartedEvent { + window: self.window.clone(), + time: self.time_counter, + location: (x, y), + id: id, + }) } Event::Touch(Touch { phase: TouchPhase::Moved, @@ -587,12 +625,12 @@ impl InputBackend for GlutinInputBackend { id, }) => { handler.on_touch_motion(&self.seat, - GlutinTouchMovedEvent { - window: self.window.clone(), - time: self.time_counter, - location: (x, y), - id: id, - }) + GlutinTouchMovedEvent { + window: self.window.clone(), + time: self.time_counter, + location: (x, y), + id: id, + }) } Event::Touch(Touch { phase: TouchPhase::Ended, @@ -600,17 +638,17 @@ impl InputBackend for GlutinInputBackend { id, }) => { handler.on_touch_motion(&self.seat, - GlutinTouchMovedEvent { - window: self.window.clone(), - time: self.time_counter, - location: (x, y), - id: id, - }); + GlutinTouchMovedEvent { + window: self.window.clone(), + time: self.time_counter, + location: (x, y), + id: id, + }); handler.on_touch_up(&self.seat, - GlutinTouchEndedEvent { - time: self.time_counter, - id: id, - }); + GlutinTouchEndedEvent { + time: self.time_counter, + id: id, + }); } Event::Touch(Touch { phase: TouchPhase::Cancelled, @@ -618,10 +656,10 @@ impl InputBackend for GlutinInputBackend { .. }) => { handler.on_touch_cancel(&self.seat, - GlutinTouchCancelledEvent { - time: self.time_counter, - id: id, - }) + GlutinTouchCancelledEvent { + time: self.time_counter, + id: id, + }) } Event::Closed => return Err(GlutinInputError::WindowClosed), _ => {} diff --git a/src/backend/graphics/opengl.rs b/src/backend/graphics/opengl.rs index d0457aa..e5884f5 100644 --- a/src/backend/graphics/opengl.rs +++ b/src/backend/graphics/opengl.rs @@ -1,8 +1,8 @@ //! Common traits and types for opengl rendering on graphics backends -use nix::c_void; use super::GraphicsBackend; +use nix::c_void; /// Error that can happen when swapping buffers. #[derive(Debug, Clone)] diff --git a/src/backend/graphics/software.rs b/src/backend/graphics/software.rs index 7e9d474..e053c77 100644 --- a/src/backend/graphics/software.rs +++ b/src/backend/graphics/software.rs @@ -1,9 +1,9 @@ //! Common traits and types used for software rendering on graphics backends -use std::error::Error; -use wayland_server::protocol::wl_shm::Format; use super::GraphicsBackend; +use std::error::Error; +use wayland_server::protocol::wl_shm::Format; /// Trait that describes objects providing a software rendering implementation pub trait CpuGraphicsBackend: GraphicsBackend { diff --git a/src/backend/input.rs b/src/backend/input.rs index 701db44..df13bfa 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -48,7 +48,9 @@ impl ::std::cmp::PartialEq for Seat { } impl ::std::hash::Hash for Seat { - fn hash(&self, state: &mut H) where H: ::std::hash::Hasher { + fn hash(&self, state: &mut H) + where H: ::std::hash::Hasher + { self.id.hash(state); } } diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index aa4a5f5..f197660 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -4,10 +4,10 @@ use backend::{SeatInternal, TouchSlotInternal}; use backend::input as backend; use input as libinput; use input::event; - -use std::io::Error as IoError; use std::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::hash::{Hash, Hasher}; + +use std::io::Error as IoError; use std::rc::Rc; /// Libinput based `InputBackend`. @@ -48,12 +48,12 @@ impl backend::Event for event::keyboard::KeyboardKeyEvent { impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent { fn key_code(&self) -> u32 { - use ::input::event::keyboard::KeyboardEventTrait; + use input::event::keyboard::KeyboardEventTrait; self.key() } fn state(&self) -> backend::KeyState { - use ::input::event::keyboard::KeyboardEventTrait; + use input::event::keyboard::KeyboardEventTrait; self.key_state().into() } @@ -70,7 +70,7 @@ pub struct PointerAxisEvent { impl<'a> backend::Event for PointerAxisEvent { fn time(&self) -> u32 { - use ::input::event::pointer::PointerEventTrait; + use input::event::pointer::PointerEventTrait; self.event.time() } } @@ -86,10 +86,10 @@ impl<'a> backend::PointerAxisEvent for PointerAxisEvent { fn amount(&self) -> f64 { match self.source() { - backend::AxisSource::Finger | backend::AxisSource::Continuous => - self.event.axis_value(self.axis), - backend::AxisSource::Wheel | backend::AxisSource::WheelTilt => - self.event.axis_value_discrete(self.axis).unwrap(), + backend::AxisSource::Finger | + backend::AxisSource::Continuous => self.event.axis_value(self.axis), + backend::AxisSource::Wheel | + backend::AxisSource::WheelTilt => self.event.axis_value_discrete(self.axis).unwrap(), } } } @@ -324,18 +324,19 @@ impl backend::InputBackend for LibinputInputBackend { trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat); handler.on_seat_changed(&old_seat); } - }, + } 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(), new_caps)); + let seat = seat_entry.insert(backend::Seat::new(hasher.finish(), + new_caps)); if let Some(ref mut handler) = self.handler { trace!(self.logger, "Calling on_seat_created with {:?}", seat); handler.on_seat_created(&seat); } } } - }, + } DeviceEvent::Removed(device_removed_event) => { let removed = device_removed_event.device(); @@ -347,9 +348,21 @@ impl backend::InputBackend for LibinputInputBackend { // 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().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Pointer)); - caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Keyboard)); - caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Touch)); + caps.pointer = + self.devices + .iter() + .filter(|x| x.seat() == device_seat) + .any(|x| x.has_capability(libinput::DeviceCapability::Pointer)); + caps.keyboard = + self.devices + .iter() + .filter(|x| x.seat() == device_seat) + .any(|x| x.has_capability(libinput::DeviceCapability::Keyboard)); + caps.touch = + self.devices + .iter() + .filter(|x| x.seat() == device_seat) + .any(|x| x.has_capability(libinput::DeviceCapability::Touch)); } else { panic!("Seat changed that was never created") } @@ -373,95 +386,117 @@ impl backend::InputBackend for LibinputInputBackend { handler.on_seat_changed(&seat); } } - }, + } } if let Some(ref mut handler) = self.handler { - handler.on_input_config_changed(&mut self.devices); + handler.on_input_config_changed(&mut self.devices); } - }, + } libinput::Event::Touch(touch_event) => { - use ::input::event::touch::*; + use input::event::touch::*; if let Some(ref mut handler) = self.handler { let device_seat = touch_event.device().seat(); - let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); + let seat = &self.seats + .get(&device_seat) + .expect("Recieved key event of non existing Seat"); match touch_event { TouchEvent::Down(down_event) => { trace!(self.logger, "Calling on_touch_down with {:?}", down_event); handler.on_touch_down(seat, down_event) - }, + } TouchEvent::Motion(motion_event) => { - trace!(self.logger, "Calling on_touch_motion with {:?}", motion_event); + trace!(self.logger, + "Calling on_touch_motion with {:?}", + motion_event); handler.on_touch_motion(seat, motion_event) - }, + } TouchEvent::Up(up_event) => { trace!(self.logger, "Calling on_touch_up with {:?}", up_event); handler.on_touch_up(seat, up_event) - }, + } TouchEvent::Cancel(cancel_event) => { - trace!(self.logger, "Calling on_touch_cancel with {:?}", cancel_event); + trace!(self.logger, + "Calling on_touch_cancel with {:?}", + cancel_event); handler.on_touch_cancel(seat, cancel_event) - }, + } TouchEvent::Frame(frame_event) => { trace!(self.logger, "Calling on_touch_frame with {:?}", frame_event); handler.on_touch_frame(seat, frame_event) - }, + } } } - }, + } libinput::Event::Keyboard(keyboard_event) => { - use ::input::event::keyboard::*; + use input::event::keyboard::*; match keyboard_event { KeyboardEvent::Key(key_event) => { if let Some(ref mut handler) = self.handler { let device_seat = key_event.device().seat(); - let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); + let seat = &self.seats + .get(&device_seat) + .expect("Recieved key event of non existing Seat"); trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event); handler.on_keyboard_key(seat, key_event); } } } - }, + } libinput::Event::Pointer(pointer_event) => { - use ::input::event::pointer::*; + use input::event::pointer::*; if let Some(ref mut handler) = self.handler { let device_seat = pointer_event.device().seat(); - let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); + let seat = &self.seats + .get(&device_seat) + .expect("Recieved key event of non existing Seat"); match pointer_event { PointerEvent::Motion(motion_event) => { - trace!(self.logger, "Calling on_pointer_move with {:?}", motion_event); + trace!(self.logger, + "Calling on_pointer_move with {:?}", + motion_event); handler.on_pointer_move(seat, motion_event); - }, + } PointerEvent::MotionAbsolute(motion_abs_event) => { - trace!(self.logger, "Calling on_pointer_move_absolute with {:?}", motion_abs_event); + trace!(self.logger, + "Calling on_pointer_move_absolute with {:?}", + motion_abs_event); handler.on_pointer_move_absolute(seat, motion_abs_event); - }, + } PointerEvent::Axis(axis_event) => { let rc_axis_event = Rc::new(axis_event); if rc_axis_event.has_axis(Axis::Vertical) { - trace!(self.logger, "Calling on_pointer_axis for Axis::Vertical with {:?}", *rc_axis_event); - handler.on_pointer_axis(seat, self::PointerAxisEvent { - axis: Axis::Vertical, - event: rc_axis_event.clone() - }); + trace!(self.logger, + "Calling on_pointer_axis for Axis::Vertical with {:?}", + *rc_axis_event); + handler.on_pointer_axis(seat, + self::PointerAxisEvent { + axis: Axis::Vertical, + event: rc_axis_event.clone(), + }); } if rc_axis_event.has_axis(Axis::Horizontal) { - trace!(self.logger, "Calling on_pointer_axis for Axis::Horizontal with {:?}", *rc_axis_event); - handler.on_pointer_axis(seat, self::PointerAxisEvent { - axis: Axis::Horizontal, - event: rc_axis_event.clone() - }); + trace!(self.logger, + "Calling on_pointer_axis for Axis::Horizontal with {:?}", + *rc_axis_event); + handler.on_pointer_axis(seat, + self::PointerAxisEvent { + axis: Axis::Horizontal, + event: rc_axis_event.clone(), + }); } - }, + } PointerEvent::Button(button_event) => { - trace!(self.logger, "Calling on_pointer_button with {:?}", button_event); + trace!(self.logger, + "Calling on_pointer_button with {:?}", + button_event); handler.on_pointer_button(seat, button_event); } } } - }, - _ => {}, //FIXME: What to do with the rest. + } + _ => {} //FIXME: What to do with the rest. } - }; + } Ok(()) } } From a2f3b2a303f7beec8ec4ed38afbc26ba361ca2c7 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Wed, 26 Apr 2017 20:19:57 +0200 Subject: [PATCH 28/30] Fix some clippy warnings --- src/backend/libinput.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index f197660..62d46f5 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -264,7 +264,7 @@ impl backend::InputBackend for LibinputInputBackend { info!(self.logger, "New input handler set."); for seat in self.seats.values() { trace!(self.logger, "Calling on_seat_created with {:?}", seat); - handler.on_seat_created(&seat); + handler.on_seat_created(seat); } self.handler = Some(Box::new(handler)); } @@ -279,7 +279,7 @@ impl backend::InputBackend for LibinputInputBackend { if let Some(mut handler) = self.handler.take() { for seat in self.seats.values() { trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat); - handler.on_seat_destroyed(&seat); + handler.on_seat_destroyed(seat); } info!(self.logger, "Removing input handler"); } @@ -322,7 +322,7 @@ impl backend::InputBackend for LibinputInputBackend { } if let Some(ref mut handler) = self.handler { trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat); - handler.on_seat_changed(&old_seat); + handler.on_seat_changed(old_seat); } } Entry::Vacant(seat_entry) => { @@ -332,7 +332,7 @@ impl backend::InputBackend for LibinputInputBackend { new_caps)); if let Some(ref mut handler) = self.handler { trace!(self.logger, "Calling on_seat_created with {:?}", seat); - handler.on_seat_created(&seat); + handler.on_seat_created(seat); } } } @@ -378,13 +378,11 @@ impl backend::InputBackend for LibinputInputBackend { } else { panic!("Seat destroyed that was never created"); } - } else { // it has, notify about updates - if let Some(ref mut handler) = self.handler { - let seat = self.seats.get(&device_seat).unwrap(); - trace!(self.logger, "Calling on_seat_changed with {:?}", seat); - handler.on_seat_changed(&seat); - } + } else if let Some(ref mut handler) = self.handler { + let seat = self.seats[&device_seat]; + trace!(self.logger, "Calling on_seat_changed with {:?}", seat); + handler.on_seat_changed(&seat); } } } From 3bd25011b09c0a6a5a76c3e38a062ebce23bf805 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Thu, 27 Apr 2017 16:12:06 +0200 Subject: [PATCH 29/30] Replace `()` with `UnusedEvent` --- src/backend/glutin.rs | 6 +++--- src/backend/input.rs | 32 +++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/backend/glutin.rs b/src/backend/glutin.rs index 88cb398..d09401a 100644 --- a/src/backend/glutin.rs +++ b/src/backend/glutin.rs @@ -7,7 +7,7 @@ use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuf use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, - TouchMotionEvent, TouchSlot, TouchUpEvent}; + TouchMotionEvent, TouchSlot, TouchUpEvent, UnusedEvent}; use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, MouseCursor, PixelFormat as GlutinPixelFormat}; use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext, @@ -508,13 +508,13 @@ impl InputBackend for GlutinInputBackend { type KeyboardKeyEvent = GlutinKeyboardInputEvent; type PointerAxisEvent = GlutinMouseWheelEvent; type PointerButtonEvent = GlutinMouseInputEvent; - type PointerMotionEvent = (); + type PointerMotionEvent = UnusedEvent; type PointerMotionAbsoluteEvent = GlutinMouseMovedEvent; type TouchDownEvent = GlutinTouchStartedEvent; type TouchUpEvent = GlutinTouchEndedEvent; type TouchMotionEvent = GlutinTouchMovedEvent; type TouchCancelEvent = GlutinTouchCancelledEvent; - type TouchFrameEvent = (); + type TouchFrameEvent = UnusedEvent; fn set_handler + 'static>(&mut self, mut handler: H) { if self.handler.is_some() { diff --git a/src/backend/input.rs b/src/backend/input.rs index df13bfa..edf8bf3 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -77,7 +77,17 @@ pub trait Event { fn time(&self) -> u32; } -impl Event for () { +/// Struct to mark events never emitted by an `InputBackend` implementation. +/// +/// Implements all event types and can be used in place for any `Event` type, +/// that is not used by an `InputBackend` implementation. Initialization is not +/// possible, making accidential use impossible and enabling a lot of possible +/// compiler optimizations. +pub struct UnusedEvent { + _hidden_field: (), +} + +impl Event for UnusedEvent { fn time(&self) -> u32 { unreachable!() } @@ -102,7 +112,7 @@ pub trait KeyboardKeyEvent: Event { fn count(&self) -> u32; } -impl KeyboardKeyEvent for () { +impl KeyboardKeyEvent for UnusedEvent { fn key_code(&self) -> u32 { unreachable!() } @@ -146,7 +156,7 @@ pub trait PointerButtonEvent: Event { fn state(&self) -> MouseButtonState; } -impl PointerButtonEvent for () { +impl PointerButtonEvent for UnusedEvent { fn button(&self) -> MouseButton { unreachable!() } @@ -208,7 +218,7 @@ pub trait PointerAxisEvent: Event { fn amount(&self) -> f64; } -impl PointerAxisEvent for () { +impl PointerAxisEvent for UnusedEvent { fn axis(&self) -> Axis { unreachable!() } @@ -235,7 +245,7 @@ pub trait PointerMotionEvent: Event { fn delta_y(&self) -> u32; } -impl PointerMotionEvent for () { +impl PointerMotionEvent for UnusedEvent { fn delta_x(&self) -> u32 { unreachable!() } @@ -279,7 +289,7 @@ pub trait PointerMotionAbsoluteEvent: Event { fn y_transformed(&self, height: u32) -> u32; } -impl PointerMotionAbsoluteEvent for () { +impl PointerMotionAbsoluteEvent for UnusedEvent { fn x(&self) -> f64 { unreachable!() } @@ -350,7 +360,7 @@ pub trait TouchDownEvent: Event { fn y_transformed(&self, height: u32) -> u32; } -impl TouchDownEvent for () { +impl TouchDownEvent for UnusedEvent { fn slot(&self) -> Option { unreachable!() } @@ -409,7 +419,7 @@ pub trait TouchMotionEvent: Event { fn y_transformed(&self, height: u32) -> u32; } -impl TouchMotionEvent for () { +impl TouchMotionEvent for UnusedEvent { fn slot(&self) -> Option { unreachable!() } @@ -437,7 +447,7 @@ pub trait TouchUpEvent: Event { fn slot(&self) -> Option; } -impl TouchUpEvent for () { +impl TouchUpEvent for UnusedEvent { fn slot(&self) -> Option { unreachable!() } @@ -449,7 +459,7 @@ pub trait TouchCancelEvent: Event { fn slot(&self) -> Option; } -impl TouchCancelEvent for () { +impl TouchCancelEvent for UnusedEvent { fn slot(&self) -> Option { unreachable!() } @@ -458,7 +468,7 @@ impl TouchCancelEvent for () { /// Trait for touch frame events pub trait TouchFrameEvent: Event {} -impl TouchFrameEvent for () {} +impl TouchFrameEvent for UnusedEvent {} /// Trait that describes objects providing a source of input events. All input backends /// need to implemenent this and provide the same base gurantees about the presicion of From 196b48041befd1e8f57e2f5781452beba1872fdd Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 29 Apr 2017 16:09:30 +0200 Subject: [PATCH 30/30] Use an enum instead of a struct for `UnusedEvent` --- src/backend/input.rs | 60 +++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/src/backend/input.rs b/src/backend/input.rs index edf8bf3..c1e7874 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -77,19 +77,17 @@ pub trait Event { fn time(&self) -> u32; } -/// Struct to mark events never emitted by an `InputBackend` implementation. +/// Used to mark events never emitted by an `InputBackend` implementation. /// /// Implements all event types and can be used in place for any `Event` type, /// that is not used by an `InputBackend` implementation. Initialization is not /// possible, making accidential use impossible and enabling a lot of possible /// compiler optimizations. -pub struct UnusedEvent { - _hidden_field: (), -} +pub enum UnusedEvent {} impl Event for UnusedEvent { fn time(&self) -> u32 { - unreachable!() + match *self {} } } @@ -114,15 +112,15 @@ pub trait KeyboardKeyEvent: Event { impl KeyboardKeyEvent for UnusedEvent { fn key_code(&self) -> u32 { - unreachable!() + match *self {} } fn state(&self) -> KeyState { - unreachable!() + match *self {} } fn count(&self) -> u32 { - unreachable!() + match *self {} } } @@ -158,11 +156,11 @@ pub trait PointerButtonEvent: Event { impl PointerButtonEvent for UnusedEvent { fn button(&self) -> MouseButton { - unreachable!() + match *self {} } fn state(&self) -> MouseButtonState { - unreachable!() + match *self {} } } @@ -220,15 +218,15 @@ pub trait PointerAxisEvent: Event { impl PointerAxisEvent for UnusedEvent { fn axis(&self) -> Axis { - unreachable!() + match *self {} } fn source(&self) -> AxisSource { - unreachable!() + match *self {} } fn amount(&self) -> f64 { - unreachable!() + match *self {} } } @@ -247,11 +245,11 @@ pub trait PointerMotionEvent: Event { impl PointerMotionEvent for UnusedEvent { fn delta_x(&self) -> u32 { - unreachable!() + match *self {} } fn delta_y(&self) -> u32 { - unreachable!() + match *self {} } } @@ -291,19 +289,19 @@ pub trait PointerMotionAbsoluteEvent: Event { impl PointerMotionAbsoluteEvent for UnusedEvent { fn x(&self) -> f64 { - unreachable!() + match *self {} } fn y(&self) -> f64 { - unreachable!() + match *self {} } fn x_transformed(&self, _width: u32) -> u32 { - unreachable!() + match *self {} } fn y_transformed(&self, _height: u32) -> u32 { - unreachable!() + match *self {} } } @@ -362,23 +360,23 @@ pub trait TouchDownEvent: Event { impl TouchDownEvent for UnusedEvent { fn slot(&self) -> Option { - unreachable!() + match *self {} } fn x(&self) -> f64 { - unreachable!() + match *self {} } fn y(&self) -> f64 { - unreachable!() + match *self {} } fn x_transformed(&self, _width: u32) -> u32 { - unreachable!() + match *self {} } fn y_transformed(&self, _height: u32) -> u32 { - unreachable!() + match *self {} } } @@ -421,23 +419,23 @@ pub trait TouchMotionEvent: Event { impl TouchMotionEvent for UnusedEvent { fn slot(&self) -> Option { - unreachable!() + match *self {} } fn x(&self) -> f64 { - unreachable!() + match *self {} } fn y(&self) -> f64 { - unreachable!() + match *self {} } fn x_transformed(&self, _width: u32) -> u32 { - unreachable!() + match *self {} } fn y_transformed(&self, _height: u32) -> u32 { - unreachable!() + match *self {} } } @@ -449,7 +447,7 @@ pub trait TouchUpEvent: Event { impl TouchUpEvent for UnusedEvent { fn slot(&self) -> Option { - unreachable!() + match *self {} } } @@ -461,7 +459,7 @@ pub trait TouchCancelEvent: Event { impl TouchCancelEvent for UnusedEvent { fn slot(&self) -> Option { - unreachable!() + match *self {} } }