Fixup glutin backend and more bugfixes
This commit is contained in:
parent
4fc595f68a
commit
092fc198c3
|
@ -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<Window>,
|
||||
time_counter: u32,
|
||||
key_counter: u32,
|
||||
seat: Seat,
|
||||
input_config: (),
|
||||
handler: Option<Box<InputHandler<GlutinInputBackend> + '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<Window>,
|
||||
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<Window>,
|
||||
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<TouchSlot> {
|
||||
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<Window>,
|
||||
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<TouchSlot> {
|
||||
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<TouchSlot> {
|
||||
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<TouchSlot> {
|
||||
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<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
|
||||
if self.handler.is_some() {
|
||||
self.clear_handler();
|
||||
|
@ -279,65 +524,61 @@ 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 {
|
||||
|
@ -345,12 +586,12 @@ impl InputBackend for GlutinInputBackend {
|
|||
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 {
|
||||
|
@ -358,25 +599,29 @@ impl InputBackend for GlutinInputBackend {
|
|||
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,
|
||||
});
|
||||
handler.on_touch_up(&self.seat,
|
||||
GlutinTouchEndedEvent {
|
||||
time: self.time_counter,
|
||||
id: id,
|
||||
});
|
||||
handler.on_touch(&self.seat,
|
||||
self.time_counter,
|
||||
TouchEvent::Up { slot: Some(TouchSlot::new(id as u32)) });
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -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<TouchSlot> {
|
||||
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<TouchSlot>;
|
||||
|
@ -313,60 +407,56 @@ pub trait TouchMotionEvent: Event {
|
|||
fn y_transformed(&self, height: u32) -> u32;
|
||||
}
|
||||
|
||||
impl TouchMotionEvent for () {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
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<TouchSlot>;
|
||||
}
|
||||
|
||||
impl TouchUpEvent for () {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for touch events cancelling the chain
|
||||
pub trait TouchCancelEvent: Event {
|
||||
/// `TouchSlot`, if the device has multi-touch capabilities
|
||||
fn slot(&self) -> Option<TouchSlot>;
|
||||
}
|
||||
|
||||
impl TouchCancelEvent for () {
|
||||
fn slot(&self) -> Option<TouchSlot> {
|
||||
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<TouchSlot>,
|
||||
/// 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<TouchSlot>,
|
||||
/// 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<TouchSlot>,
|
||||
},
|
||||
/// 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<TouchSlot>,
|
||||
},
|
||||
/// 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`
|
||||
|
|
|
@ -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<libinput::Device>,
|
||||
seats: HashMap<libinput::Seat, SeatDesc>,
|
||||
seats: HashMap<libinput::Seat, backend::Seat>,
|
||||
handler: Option<Box<backend::InputHandler<LibinputInputBackend> + '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<backend::TouchSlot> {
|
||||
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<backend::TouchSlot> {
|
||||
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<backend::TouchSlot> {
|
||||
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<backend::TouchSlot> {
|
||||
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);
|
||||
|
|
|
@ -33,5 +33,5 @@ trait SeatInternal {
|
|||
}
|
||||
|
||||
trait TouchSlotInternal {
|
||||
fn new(id: u32) -> Self;
|
||||
fn new(id: u64) -> Self;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue