commit
f04b1ff275
|
@ -22,6 +22,7 @@ addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
- libwayland-dev
|
- libwayland-dev
|
||||||
|
- libudev-dev
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
@ -59,4 +60,3 @@ notifications:
|
||||||
on_success: change
|
on_success: change
|
||||||
on_failure: always
|
on_failure: always
|
||||||
on_start: never
|
on_start: never
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,14 @@ slog = { version = "2.0.0" }
|
||||||
slog-stdlog = "2.0.0-0.2"
|
slog-stdlog = "2.0.0-0.2"
|
||||||
glutin = { version = "~0.7.4", optional = true }
|
glutin = { version = "~0.7.4", optional = true }
|
||||||
glium = { version = "~0.16.0", optional = true }
|
glium = { version = "~0.16.0", optional = true }
|
||||||
|
input = { version = "~0.1.1", optional = true }
|
||||||
clippy = { version = "*", optional = true }
|
clippy = { version = "*", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
slog-term = "~1.5"
|
slog-term = "~1.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["backend_glutin", "renderer_glium"]
|
default = ["backend_glutin", "backend_libinput", "renderer_glium"]
|
||||||
backend_glutin = ["glutin", "wayland-server/dlopen"]
|
backend_glutin = ["glutin", "wayland-server/dlopen"]
|
||||||
renderer_glium = ["glium"]
|
renderer_glium = ["glium"]
|
||||||
|
backend_libinput = ["input"]
|
||||||
|
|
|
@ -2,13 +2,18 @@
|
||||||
|
|
||||||
|
|
||||||
use backend::{SeatInternal, TouchSlotInternal};
|
use backend::{SeatInternal, TouchSlotInternal};
|
||||||
|
use backend::graphics::GraphicsBackend;
|
||||||
use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError};
|
use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError};
|
||||||
use backend::input::{Axis, AxisSource, InputBackend, InputHandler, KeyState, MouseButton, MouseButtonState,
|
use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState,
|
||||||
Seat, SeatCapabilities, TouchEvent, TouchSlot};
|
KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
|
||||||
use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, PixelFormat as GlutinPixelFormat};
|
PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent,
|
||||||
|
TouchMotionEvent, TouchSlot, TouchUpEvent, UnusedEvent};
|
||||||
|
use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, MouseCursor,
|
||||||
|
PixelFormat as GlutinPixelFormat};
|
||||||
use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext,
|
use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext,
|
||||||
HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder};
|
HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder};
|
||||||
use nix::c_void;
|
use nix::c_void;
|
||||||
|
use std::cmp;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -79,6 +84,17 @@ 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 {
|
impl OpenglGraphicsBackend for GlutinHeadlessRenderer {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
|
fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
|
||||||
|
@ -130,6 +146,23 @@ 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
|
||||||
|
.set_cursor_position(win_x + x as i32, win_y + y as i32)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_cursor_representation(&mut self, cursor: MouseCursor) {
|
||||||
|
self.window.set_cursor(cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl OpenglGraphicsBackend for GlutinWindowedRenderer {
|
impl OpenglGraphicsBackend for GlutinWindowedRenderer {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
|
fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
|
||||||
|
@ -200,15 +233,289 @@ impl fmt::Display for GlutinInputError {
|
||||||
pub struct GlutinInputBackend {
|
pub struct GlutinInputBackend {
|
||||||
window: Rc<Window>,
|
window: Rc<Window>,
|
||||||
time_counter: u32,
|
time_counter: u32,
|
||||||
|
key_counter: u32,
|
||||||
seat: Seat,
|
seat: Seat,
|
||||||
input_config: (),
|
input_config: (),
|
||||||
handler: Option<Box<InputHandler<GlutinInputBackend> + 'static>>,
|
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 {
|
impl InputBackend for GlutinInputBackend {
|
||||||
type InputConfig = ();
|
type InputConfig = ();
|
||||||
type EventError = GlutinInputError;
|
type EventError = GlutinInputError;
|
||||||
|
|
||||||
|
type KeyboardKeyEvent = GlutinKeyboardInputEvent;
|
||||||
|
type PointerAxisEvent = GlutinMouseWheelEvent;
|
||||||
|
type PointerButtonEvent = GlutinMouseInputEvent;
|
||||||
|
type PointerMotionEvent = UnusedEvent;
|
||||||
|
type PointerMotionAbsoluteEvent = GlutinMouseMovedEvent;
|
||||||
|
type TouchDownEvent = GlutinTouchStartedEvent;
|
||||||
|
type TouchUpEvent = GlutinTouchEndedEvent;
|
||||||
|
type TouchMotionEvent = GlutinTouchMovedEvent;
|
||||||
|
type TouchCancelEvent = GlutinTouchCancelledEvent;
|
||||||
|
type TouchFrameEvent = UnusedEvent;
|
||||||
|
|
||||||
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
|
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
|
||||||
if self.handler.is_some() {
|
if self.handler.is_some() {
|
||||||
self.clear_handler();
|
self.clear_handler();
|
||||||
|
@ -233,15 +540,6 @@ impl InputBackend for GlutinInputBackend {
|
||||||
&mut self.input_config
|
&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`.
|
/// 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
|
/// You need to periodically call this function to keep the underlying event loop and
|
||||||
|
@ -259,104 +557,109 @@ impl InputBackend for GlutinInputBackend {
|
||||||
if let Some(ref mut handler) = self.handler {
|
if let Some(ref mut handler) = self.handler {
|
||||||
match event {
|
match event {
|
||||||
Event::KeyboardInput(state, key_code, _) => {
|
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,
|
handler.on_keyboard_key(&self.seat,
|
||||||
self.time_counter,
|
GlutinKeyboardInputEvent {
|
||||||
key_code as u32,
|
time: self.time_counter,
|
||||||
state.into(),
|
key: key_code,
|
||||||
1)
|
count: self.key_counter,
|
||||||
|
state: state,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Event::MouseMoved(x, y) => {
|
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, _) => {
|
Event::MouseWheel(delta, _) => {
|
||||||
|
let event = GlutinMouseWheelEvent {
|
||||||
|
axis: Axis::Horizontal,
|
||||||
|
time: self.time_counter,
|
||||||
|
delta: delta,
|
||||||
|
};
|
||||||
match delta {
|
match delta {
|
||||||
MouseScrollDelta::LineDelta(x, y) => {
|
MouseScrollDelta::LineDelta(x, y) |
|
||||||
if x != 0.0 {
|
|
||||||
handler.on_pointer_scroll(&self.seat,
|
|
||||||
self.time_counter,
|
|
||||||
Axis::Horizontal,
|
|
||||||
AxisSource::Wheel,
|
|
||||||
x as f64);
|
|
||||||
}
|
|
||||||
if y != 0.0 {
|
|
||||||
handler.on_pointer_scroll(&self.seat,
|
|
||||||
self.time_counter,
|
|
||||||
Axis::Vertical,
|
|
||||||
AxisSource::Wheel,
|
|
||||||
y as f64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MouseScrollDelta::PixelDelta(x, y) => {
|
MouseScrollDelta::PixelDelta(x, y) => {
|
||||||
if x != 0.0 {
|
if x != 0.0 {
|
||||||
handler.on_pointer_scroll(&self.seat,
|
handler.on_pointer_axis(&self.seat, event.clone());
|
||||||
self.time_counter,
|
|
||||||
Axis::Vertical,
|
|
||||||
AxisSource::Continous,
|
|
||||||
x as f64);
|
|
||||||
}
|
}
|
||||||
if y != 0.0 {
|
if y != 0.0 {
|
||||||
handler.on_pointer_scroll(&self.seat,
|
handler.on_pointer_axis(&self.seat, event);
|
||||||
self.time_counter,
|
|
||||||
Axis::Horizontal,
|
|
||||||
AxisSource::Continous,
|
|
||||||
y as f64);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::MouseInput(state, button) => {
|
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 {
|
Event::Touch(Touch {
|
||||||
phase: TouchPhase::Started,
|
phase: TouchPhase::Started,
|
||||||
location: (x, y),
|
location: (x, y),
|
||||||
id,
|
id,
|
||||||
}) => {
|
}) => {
|
||||||
handler.on_touch(&self.seat,
|
handler.on_touch_down(&self.seat,
|
||||||
self.time_counter,
|
GlutinTouchStartedEvent {
|
||||||
TouchEvent::Down {
|
window: self.window.clone(),
|
||||||
slot: Some(TouchSlot::new(id as u32)),
|
time: self.time_counter,
|
||||||
x: x,
|
location: (x, y),
|
||||||
y: y,
|
id: id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Event::Touch(Touch {
|
Event::Touch(Touch {
|
||||||
phase: TouchPhase::Moved,
|
phase: TouchPhase::Moved,
|
||||||
location: (x, y),
|
location: (x, y),
|
||||||
id,
|
id,
|
||||||
}) => {
|
}) => {
|
||||||
handler.on_touch(&self.seat,
|
handler.on_touch_motion(&self.seat,
|
||||||
self.time_counter,
|
GlutinTouchMovedEvent {
|
||||||
TouchEvent::Motion {
|
window: self.window.clone(),
|
||||||
slot: Some(TouchSlot::new(id as u32)),
|
time: self.time_counter,
|
||||||
x: x,
|
location: (x, y),
|
||||||
y: y,
|
id: id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Event::Touch(Touch {
|
Event::Touch(Touch {
|
||||||
phase: TouchPhase::Ended,
|
phase: TouchPhase::Ended,
|
||||||
location: (x, y),
|
location: (x, y),
|
||||||
id,
|
id,
|
||||||
}) => {
|
}) => {
|
||||||
handler.on_touch(&self.seat,
|
handler.on_touch_motion(&self.seat,
|
||||||
self.time_counter,
|
GlutinTouchMovedEvent {
|
||||||
TouchEvent::Motion {
|
window: self.window.clone(),
|
||||||
slot: Some(TouchSlot::new(id as u32)),
|
time: self.time_counter,
|
||||||
x: x,
|
location: (x, y),
|
||||||
y: y,
|
id: id,
|
||||||
});
|
});
|
||||||
handler.on_touch(&self.seat,
|
handler.on_touch_up(&self.seat,
|
||||||
self.time_counter,
|
GlutinTouchEndedEvent {
|
||||||
TouchEvent::Up { slot: Some(TouchSlot::new(id as u32)) });
|
time: self.time_counter,
|
||||||
|
id: id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Event::Touch(Touch {
|
Event::Touch(Touch {
|
||||||
phase: TouchPhase::Cancelled,
|
phase: TouchPhase::Cancelled,
|
||||||
id,
|
id,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
handler.on_touch(&self.seat,
|
handler.on_touch_cancel(&self.seat,
|
||||||
self.time_counter,
|
GlutinTouchCancelledEvent {
|
||||||
TouchEvent::Cancel { slot: Some(TouchSlot::new(id as u32)) })
|
time: self.time_counter,
|
||||||
|
id: id,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Event::Closed => return Err(GlutinInputError::WindowClosed),
|
Event::Closed => return Err(GlutinInputError::WindowClosed),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -373,6 +676,7 @@ impl GlutinInputBackend {
|
||||||
GlutinInputBackend {
|
GlutinInputBackend {
|
||||||
window: window,
|
window: window,
|
||||||
time_counter: 0,
|
time_counter: 0,
|
||||||
|
key_counter: 0,
|
||||||
seat: Seat::new(0,
|
seat: Seat::new(0,
|
||||||
SeatCapabilities {
|
SeatCapabilities {
|
||||||
pointer: true,
|
pointer: true,
|
||||||
|
|
|
@ -2,5 +2,32 @@
|
||||||
//!
|
//!
|
||||||
//! Note: Not every api may be supported by every backend
|
//! 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 {
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// 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<(), ()>;
|
||||||
|
|
||||||
|
/// 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;
|
pub mod software;
|
||||||
pub mod opengl;
|
pub mod opengl;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
//! Common traits and types for opengl rendering on graphics backends
|
//! Common traits and types for opengl rendering on graphics backends
|
||||||
|
|
||||||
|
|
||||||
|
use super::GraphicsBackend;
|
||||||
use nix::c_void;
|
use nix::c_void;
|
||||||
|
|
||||||
/// Error that can happen when swapping buffers.
|
/// Error that can happen when swapping buffers.
|
||||||
|
@ -61,7 +63,7 @@ pub struct PixelFormat {
|
||||||
|
|
||||||
/// Trait that describes objects that have an OpenGl context
|
/// Trait that describes objects that have an OpenGl context
|
||||||
/// and can be used to render upon
|
/// and can be used to render upon
|
||||||
pub trait OpenglGraphicsBackend {
|
pub trait OpenglGraphicsBackend: GraphicsBackend {
|
||||||
/// Swaps buffers at the end of a frame.
|
/// Swaps buffers at the end of a frame.
|
||||||
fn swap_buffers(&self) -> Result<(), SwapBuffersError>;
|
fn swap_buffers(&self) -> Result<(), SwapBuffersError>;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
//! Common traits and types used for software rendering on graphics backends
|
//! Common traits and types used for software rendering on graphics backends
|
||||||
|
|
||||||
|
|
||||||
|
use super::GraphicsBackend;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use wayland_server::protocol::wl_shm::Format;
|
use wayland_server::protocol::wl_shm::Format;
|
||||||
|
|
||||||
/// Trait that describes objects providing a software rendering implementation
|
/// Trait that describes objects providing a software rendering implementation
|
||||||
pub trait CpuGraphicsBackend<E: Error> {
|
pub trait CpuGraphicsBackend<E: Error>: GraphicsBackend {
|
||||||
/// Render a given buffer of a given format at a specified place in the framebuffer
|
/// Render a given buffer of a given format at a specified place in the framebuffer
|
||||||
///
|
///
|
||||||
/// # Error
|
/// # Error
|
||||||
|
|
|
@ -11,20 +11,27 @@ use std::error::Error;
|
||||||
/// however multiseat configurations are possible and should be treated as
|
/// however multiseat configurations are possible and should be treated as
|
||||||
/// separated users, all with their own focus, input and cursor available.
|
/// 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
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
/// 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 {
|
pub struct Seat {
|
||||||
id: u32,
|
id: u64,
|
||||||
capabilities: SeatCapabilities,
|
capabilities: SeatCapabilities,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SeatInternal for Seat {
|
impl SeatInternal for Seat {
|
||||||
fn new(id: u32, capabilities: SeatCapabilities) -> Seat {
|
fn new(id: u64, capabilities: SeatCapabilities) -> Seat {
|
||||||
Seat {
|
Seat {
|
||||||
id: id,
|
id: id,
|
||||||
capabilities: capabilities,
|
capabilities: capabilities,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capabilities_mut(&mut self) -> &mut SeatCapabilities {
|
||||||
|
&mut self.capabilities
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Seat {
|
impl Seat {
|
||||||
|
@ -34,6 +41,20 @@ 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<H>(&self, state: &mut H)
|
||||||
|
where H: ::std::hash::Hasher
|
||||||
|
{
|
||||||
|
self.id.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Describes capabilities a `Seat` has.
|
/// Describes capabilities a `Seat` has.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct SeatCapabilities {
|
pub struct SeatCapabilities {
|
||||||
|
@ -45,6 +66,31 @@ pub struct SeatCapabilities {
|
||||||
pub touch: bool,
|
pub touch: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 enum UnusedEvent {}
|
||||||
|
|
||||||
|
impl Event for UnusedEvent {
|
||||||
|
fn time(&self) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// State of key on a keyboard. Either pressed or released
|
/// State of key on a keyboard. Either pressed or released
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum KeyState {
|
pub enum KeyState {
|
||||||
|
@ -54,6 +100,30 @@ pub enum KeyState {
|
||||||
Pressed,
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyboardKeyEvent for UnusedEvent {
|
||||||
|
fn key_code(&self) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state(&self) -> KeyState {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count(&self) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A particular mouse button
|
/// A particular mouse button
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum MouseButton {
|
pub enum MouseButton {
|
||||||
|
@ -76,6 +146,24 @@ pub enum MouseButtonState {
|
||||||
Pressed,
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerButtonEvent for UnusedEvent {
|
||||||
|
fn button(&self) -> MouseButton {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state(&self) -> MouseButtonState {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Axis when scrolling
|
/// Axis when scrolling
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum Axis {
|
pub enum Axis {
|
||||||
|
@ -105,7 +193,7 @@ pub enum AxisSource {
|
||||||
/// The coordinate system is identical to
|
/// The coordinate system is identical to
|
||||||
/// the cursor movement, i.e. a scroll value of 1 represents the equivalent relative
|
/// the cursor movement, i.e. a scroll value of 1 represents the equivalent relative
|
||||||
/// motion of 1.
|
/// motion of 1.
|
||||||
Continous,
|
Continuous,
|
||||||
/// Scroll wheel.
|
/// Scroll wheel.
|
||||||
///
|
///
|
||||||
/// No terminating event is guaranteed (though it may happen). Scrolling is in
|
/// No terminating event is guaranteed (though it may happen). Scrolling is in
|
||||||
|
@ -118,6 +206,105 @@ pub enum AxisSource {
|
||||||
WheelTilt,
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerAxisEvent for UnusedEvent {
|
||||||
|
fn axis(&self) -> Axis {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> AxisSource {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn amount(&self) -> f64 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerMotionEvent for UnusedEvent {
|
||||||
|
fn delta_x(&self) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delta_y(&self) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerMotionAbsoluteEvent for UnusedEvent {
|
||||||
|
fn x(&self) -> f64 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y(&self) -> f64 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x_transformed(&self, _width: u32) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y_transformed(&self, _height: u32) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Slot of a different touch event.
|
/// Slot of a different touch event.
|
||||||
///
|
///
|
||||||
/// Touch events are groubed by slots, usually to identify different
|
/// Touch events are groubed by slots, usually to identify different
|
||||||
|
@ -125,68 +312,193 @@ pub enum AxisSource {
|
||||||
/// be interpreted in the context of other events on the same slot.
|
/// be interpreted in the context of other events on the same slot.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct TouchSlot {
|
pub struct TouchSlot {
|
||||||
id: u32,
|
id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TouchSlotInternal for TouchSlot {
|
impl TouchSlotInternal for TouchSlot {
|
||||||
fn new(id: u32) -> Self {
|
fn new(id: u64) -> Self {
|
||||||
TouchSlot { id: id }
|
TouchSlot { id: id }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Touch event
|
/// Trait for touch events starting at a given position.
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
pub trait TouchDownEvent: Event {
|
||||||
pub enum TouchEvent {
|
/// `TouchSlot`, if the device has multi-touch capabilities
|
||||||
/// The start of an event at a given position (x, y).
|
fn slot(&self) -> Option<TouchSlot>;
|
||||||
|
|
||||||
|
/// Touch position in the device's native coordinate space
|
||||||
///
|
///
|
||||||
/// If the device has multi-touch capabilities a slot is given.
|
/// The actual format is defined by the implementation.
|
||||||
Down {
|
fn position(&self) -> (f64, f64) {
|
||||||
/// `TouchSlot`, if the device has multi-touch capabilities
|
(self.x(), self.y())
|
||||||
slot: Option<TouchSlot>,
|
}
|
||||||
/// Absolute x-coordinate of the touch position.
|
|
||||||
x: f64,
|
/// Touch position converted into the target coordinate space.
|
||||||
/// Absolute y-coordinate of the touch position.
|
/// E.g. the focused output's resolution.
|
||||||
y: f64,
|
fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) {
|
||||||
},
|
(self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1))
|
||||||
/// Movement of a touch on the device surface to a given position (x, y).
|
}
|
||||||
|
|
||||||
|
/// Touch event's x-coordinate in the device's native coordinate space
|
||||||
///
|
///
|
||||||
/// If the device has multi-touch capabilities a slot is given.
|
/// The actual format is defined by the implementation.
|
||||||
Motion {
|
fn x(&self) -> f64;
|
||||||
/// `TouchSlot`, if the device has multi-touch capabilities
|
|
||||||
slot: Option<TouchSlot>,
|
/// Touch event's x-coordinate in the device's native coordinate space
|
||||||
/// 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.
|
/// The actual format is defined by the implementation.
|
||||||
Up {
|
fn y(&self) -> f64;
|
||||||
/// `TouchSlot`, if the device has multi-touch capabilities
|
|
||||||
slot: Option<TouchSlot>,
|
/// Touch event's x position converted to the targets coordinate space's width.
|
||||||
},
|
/// E.g. the focused output's width.
|
||||||
/// Cancel of an event chain. All previous events in the chain should be ignored.
|
fn x_transformed(&self, width: u32) -> u32;
|
||||||
///
|
|
||||||
/// If the device has multi-touch capabilities a slot is given.
|
/// Touch event's y position converted to the targets coordinate space's width.
|
||||||
Cancel {
|
/// E.g. the focused output's width.
|
||||||
/// `TouchSlot`, if the device has multi-touch capabilities
|
fn y_transformed(&self, height: u32) -> u32;
|
||||||
slot: Option<TouchSlot>,
|
|
||||||
},
|
|
||||||
/// Signals the end of a set of touchpoints at one device sample time.
|
|
||||||
Frame,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TouchDownEvent for UnusedEvent {
|
||||||
|
fn slot(&self) -> Option<TouchSlot> {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x(&self) -> f64 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y(&self) -> f64 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x_transformed(&self, _width: u32) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y_transformed(&self, _height: u32) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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>;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TouchMotionEvent for UnusedEvent {
|
||||||
|
fn slot(&self) -> Option<TouchSlot> {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x(&self) -> f64 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y(&self) -> f64 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x_transformed(&self, _width: u32) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y_transformed(&self, _height: u32) -> u32 {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 UnusedEvent {
|
||||||
|
fn slot(&self) -> Option<TouchSlot> {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 UnusedEvent {
|
||||||
|
fn slot(&self) -> Option<TouchSlot> {
|
||||||
|
match *self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for touch frame events
|
||||||
|
pub trait TouchFrameEvent: Event {}
|
||||||
|
|
||||||
|
impl TouchFrameEvent for UnusedEvent {}
|
||||||
|
|
||||||
/// Trait that describes objects providing a source of input events. All input backends
|
/// 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
|
/// need to implemenent this and provide the same base gurantees about the presicion of
|
||||||
/// given events.
|
/// given events.
|
||||||
pub trait InputBackend: Sized {
|
pub trait InputBackend: Sized {
|
||||||
/// Type of input device associated with the backend
|
/// Type of input device associated with the backend
|
||||||
type InputConfig;
|
type InputConfig: ?Sized;
|
||||||
|
|
||||||
/// Type representing errors that may be returned when processing events
|
/// Type representing errors that may be returned when processing events
|
||||||
type EventError: Error;
|
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`
|
/// Sets a new handler for this `InputBackend`
|
||||||
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, handler: H);
|
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, handler: H);
|
||||||
/// Get a reference to the currently set handler, if any
|
/// Get a reference to the currently set handler, if any
|
||||||
|
@ -199,13 +511,6 @@ pub trait InputBackend: Sized {
|
||||||
|
|
||||||
/// Processes new events of the underlying backend and drives the `InputHandler`.
|
/// Processes new events of the underlying backend and drives the `InputHandler`.
|
||||||
fn dispatch_new_events(&mut self) -> Result<(), Self::EventError>;
|
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`.
|
/// Implement to receive input events from any `InputBackend`.
|
||||||
|
@ -215,6 +520,10 @@ pub trait InputHandler<B: InputBackend> {
|
||||||
/// Called when an existing `Seat` has been destroyed.
|
/// Called when an existing `Seat` has been destroyed.
|
||||||
fn on_seat_destroyed(&mut self, seat: &Seat);
|
fn on_seat_destroyed(&mut self, seat: &Seat);
|
||||||
/// Called when a `Seat`'s properties have changed.
|
/// 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);
|
fn on_seat_changed(&mut self, seat: &Seat);
|
||||||
|
|
||||||
/// Called when a new keyboard event was received.
|
/// Called when a new keyboard event was received.
|
||||||
|
@ -222,66 +531,74 @@ pub trait InputHandler<B: InputBackend> {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `seat` - The `Seat` the event belongs to
|
/// - `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` - The keyboard event
|
||||||
/// - `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`
|
|
||||||
///
|
///
|
||||||
/// # TODO:
|
fn on_keyboard_key(&mut self, seat: &Seat, event: B::KeyboardKeyEvent);
|
||||||
/// - 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);
|
|
||||||
/// Called when a new pointer movement event was received.
|
/// Called when a new pointer movement event was received.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `seat` - The `Seat` the event belongs to
|
/// - `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` - The pointer movement event
|
||||||
/// - `to` - Absolute screen coordinates of the pointer moved to.
|
fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent);
|
||||||
|
/// Called when a new pointer absolute movement event was received.
|
||||||
///
|
///
|
||||||
/// # TODO:
|
/// # Arguments
|
||||||
/// - check if events can arrive out of order.
|
///
|
||||||
/// - Make stronger time guarantees
|
/// - `seat` - The `Seat` the event belongs to
|
||||||
fn on_pointer_move(&mut self, seat: &Seat, time: u32, to: (u32, u32));
|
/// - `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.
|
/// Called when a new pointer button event was received.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `seat` - The `Seat` the event belongs to
|
/// - `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` - The pointer button event
|
||||||
/// - `button` - Which button was pressed..
|
fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent);
|
||||||
/// - `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);
|
|
||||||
/// Called when a new pointer scroll event was received.
|
/// Called when a new pointer scroll event was received.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `seat` - The `Seat` the event belongs to
|
/// - `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` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events.
|
||||||
/// - `axis` - `Axis` this event was generated for.
|
fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent);
|
||||||
/// - `source` - Source of the scroll event. Important for interpretation of `amount`.
|
|
||||||
/// - `amount` - Amount of scrolling on the given `Axis`. See `source` for interpretation.
|
/// Called when a new touch down event was received.
|
||||||
///
|
|
||||||
/// # 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.
|
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `seat` - The `Seat` the event belongs to
|
/// - `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` - The touch down event
|
||||||
/// - `event` - Touch event recieved. See `TouchEvent`.
|
fn on_touch_down(&mut self, seat: &Seat, event: B::TouchDownEvent);
|
||||||
|
/// Called when a new touch motion event was received.
|
||||||
///
|
///
|
||||||
/// # TODO:
|
/// # Arguments
|
||||||
/// - check if events can arrive out of order.
|
///
|
||||||
/// - Make stronger time guarantees
|
/// - `seat` - The `Seat` the event belongs to
|
||||||
fn on_touch(&mut self, seat: &Seat, time: u32, event: TouchEvent);
|
/// - `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.
|
/// Called when the `InputConfig` was changed through an external event.
|
||||||
///
|
///
|
||||||
|
@ -303,24 +620,44 @@ impl<B: InputBackend> InputHandler<B> for Box<InputHandler<B>> {
|
||||||
(**self).on_seat_changed(seat)
|
(**self).on_seat_changed(seat)
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
(**self).on_keyboard_key(seat, time, key_code, state, count)
|
(**self).on_keyboard_key(seat, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_pointer_move(&mut self, seat: &Seat, time: u32, to: (u32, u32)) {
|
fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent) {
|
||||||
(**self).on_pointer_move(seat, time, to)
|
(**self).on_pointer_move(seat, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_pointer_button(&mut self, seat: &Seat, time: u32, button: MouseButton, state: MouseButtonState) {
|
fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent) {
|
||||||
(**self).on_pointer_button(seat, time, button, state)
|
(**self).on_pointer_move_absolute(seat, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_pointer_scroll(&mut self, seat: &Seat, time: u32, axis: Axis, source: AxisSource, amount: f64) {
|
fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent) {
|
||||||
(**self).on_pointer_scroll(seat, time, axis, source, amount)
|
(**self).on_pointer_button(seat, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_touch(&mut self, seat: &Seat, time: u32, event: TouchEvent) {
|
fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent) {
|
||||||
(**self).on_touch(seat, time, event)
|
(**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) {
|
fn on_input_config_changed(&mut self, config: &mut B::InputConfig) {
|
||||||
|
|
|
@ -0,0 +1,538 @@
|
||||||
|
//! Implementation of input backend trait for types provided by `libinput`
|
||||||
|
|
||||||
|
use backend::{SeatInternal, TouchSlotInternal};
|
||||||
|
use backend::input as backend;
|
||||||
|
use input as libinput;
|
||||||
|
use input::event;
|
||||||
|
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`.
|
||||||
|
///
|
||||||
|
/// Tracks input of all devices given manually or via a udev seat to a provided libinput
|
||||||
|
/// context.
|
||||||
|
pub struct LibinputInputBackend {
|
||||||
|
context: libinput::Libinput,
|
||||||
|
devices: Vec<libinput::Device>,
|
||||||
|
seats: HashMap<libinput::Seat, backend::Seat>,
|
||||||
|
handler: Option<Box<backend::InputHandler<LibinputInputBackend> + 'static>>,
|
||||||
|
logger: ::slog::Logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LibinputInputBackend {
|
||||||
|
/// Initialize a new `LibinputInputBackend` from a given already initialized libinput
|
||||||
|
/// context.
|
||||||
|
pub fn new<L>(context: libinput::Libinput, logger: L) -> Self
|
||||||
|
where L: Into<Option<::slog::Logger>>
|
||||||
|
{
|
||||||
|
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 backend::Event for event::keyboard::KeyboardKeyEvent {
|
||||||
|
fn time(&self) -> u32 {
|
||||||
|
event::keyboard::KeyboardEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for libinput pointer axis events to implement `backend::input::PointerAxisEvent`
|
||||||
|
pub struct PointerAxisEvent {
|
||||||
|
axis: event::pointer::Axis,
|
||||||
|
event: Rc<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 {
|
||||||
|
event::pointer::PointerEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.button_state().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::Event for event::pointer::PointerMotionEvent {
|
||||||
|
fn time(&self) -> u32 {
|
||||||
|
event::pointer::PointerEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
event::pointer::PointerEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
event::touch::TouchEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::TouchDownEvent for event::touch::TouchDownEvent {
|
||||||
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
||||||
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x(&self) -> f64 {
|
||||||
|
event::touch::TouchEventPosition::x(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y(&self) -> f64 {
|
||||||
|
event::touch::TouchEventPosition::y(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x_transformed(&self, width: u32) -> u32 {
|
||||||
|
event::touch::TouchEventPosition::x_transformed(self, width) as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y_transformed(&self, height: u32) -> u32 {
|
||||||
|
event::touch::TouchEventPosition::y_transformed(self, height) as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::Event for event::touch::TouchMotionEvent {
|
||||||
|
fn time(&self) -> u32 {
|
||||||
|
event::touch::TouchEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::TouchMotionEvent for event::touch::TouchMotionEvent {
|
||||||
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
||||||
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x(&self) -> f64 {
|
||||||
|
event::touch::TouchEventPosition::x(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y(&self) -> f64 {
|
||||||
|
event::touch::TouchEventPosition::y(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x_transformed(&self, width: u32) -> u32 {
|
||||||
|
event::touch::TouchEventPosition::x_transformed(self, width) as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y_transformed(&self, height: u32) -> u32 {
|
||||||
|
event::touch::TouchEventPosition::y_transformed(self, height) as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::Event for event::touch::TouchUpEvent {
|
||||||
|
fn time(&self) -> u32 {
|
||||||
|
event::touch::TouchEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::TouchUpEvent for event::touch::TouchUpEvent {
|
||||||
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
||||||
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::Event for event::touch::TouchCancelEvent {
|
||||||
|
fn time(&self) -> u32 {
|
||||||
|
event::touch::TouchEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::TouchCancelEvent for event::touch::TouchCancelEvent {
|
||||||
|
fn slot(&self) -> Option<backend::TouchSlot> {
|
||||||
|
event::touch::TouchEventSlot::slot(self).map(|x| backend::TouchSlot::new(x as u64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::Event for event::touch::TouchFrameEvent {
|
||||||
|
fn time(&self) -> u32 {
|
||||||
|
event::touch::TouchEventTrait::time(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::TouchFrameEvent for event::touch::TouchFrameEvent {}
|
||||||
|
|
||||||
|
impl backend::InputBackend for LibinputInputBackend {
|
||||||
|
type InputConfig = [libinput::Device];
|
||||||
|
type EventError = IoError;
|
||||||
|
|
||||||
|
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<H: backend::InputHandler<Self> + 'static>(&mut self, mut handler: H) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_handler(&mut self) -> Option<&mut backend::InputHandler<Self>> {
|
||||||
|
self.handler
|
||||||
|
.as_mut()
|
||||||
|
.map(|handler| handler as &mut backend::InputHandler<Self>)
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input_config(&mut self) -> &mut Self::InputConfig {
|
||||||
|
&mut self.devices
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_new_events(&mut self) -> Result<(), IoError> {
|
||||||
|
use input::event::EventTrait;
|
||||||
|
|
||||||
|
self.context.dispatch()?;
|
||||||
|
|
||||||
|
for event in &mut self.context {
|
||||||
|
match event {
|
||||||
|
libinput::Event::Device(device_event) => {
|
||||||
|
use input::event::device::*;
|
||||||
|
match device_event {
|
||||||
|
DeviceEvent::Added(device_added_event) => {
|
||||||
|
let added = device_added_event.device();
|
||||||
|
|
||||||
|
let new_caps = backend::SeatCapabilities {
|
||||||
|
pointer: added.has_capability(libinput::DeviceCapability::Pointer),
|
||||||
|
keyboard: added.has_capability(libinput::DeviceCapability::Keyboard),
|
||||||
|
touch: added.has_capability(libinput::DeviceCapability::Touch),
|
||||||
|
};
|
||||||
|
|
||||||
|
let device_seat = added.seat();
|
||||||
|
self.devices.push(added);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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));
|
||||||
|
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();
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
.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")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
trace!(self.logger, "Calling on_seat_destroyed with {:?}", seat);
|
||||||
|
handler.on_seat_destroyed(&seat);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("Seat destroyed that was never created");
|
||||||
|
}
|
||||||
|
// it has, notify about updates
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(ref mut handler) = self.handler {
|
||||||
|
handler.on_input_config_changed(&mut self.devices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 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);
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libinput::Event::Keyboard(keyboard_event) => {
|
||||||
|
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");
|
||||||
|
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::*;
|
||||||
|
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");
|
||||||
|
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) => {
|
||||||
|
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(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PointerEvent::Button(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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<event::keyboard::KeyState> for backend::KeyState {
|
||||||
|
fn from(libinput: event::keyboard::KeyState) -> Self {
|
||||||
|
match libinput {
|
||||||
|
event::keyboard::KeyState::Pressed => backend::KeyState::Pressed,
|
||||||
|
event::keyboard::KeyState::Released => backend::KeyState::Released,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<event::pointer::Axis> for backend::Axis {
|
||||||
|
fn from(libinput: event::pointer::Axis) -> Self {
|
||||||
|
match libinput {
|
||||||
|
event::pointer::Axis::Vertical => backend::Axis::Vertical,
|
||||||
|
event::pointer::Axis::Horizontal => backend::Axis::Horizontal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<event::pointer::AxisSource> for backend::AxisSource {
|
||||||
|
fn from(libinput: event::pointer::AxisSource) -> Self {
|
||||||
|
match libinput {
|
||||||
|
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<event::pointer::ButtonState> 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,8 @@ pub mod graphics;
|
||||||
|
|
||||||
#[cfg(feature = "backend_glutin")]
|
#[cfg(feature = "backend_glutin")]
|
||||||
pub mod glutin;
|
pub mod glutin;
|
||||||
|
#[cfg(feature = "backend_libinput")]
|
||||||
|
pub mod libinput;
|
||||||
|
|
||||||
#[cfg(feature = "renderer_glium")]
|
#[cfg(feature = "renderer_glium")]
|
||||||
mod glium;
|
mod glium;
|
||||||
|
@ -26,9 +28,10 @@ pub use glium::*;
|
||||||
/// Internal functions that need to be accessible by the different backend implementations
|
/// Internal functions that need to be accessible by the different backend implementations
|
||||||
|
|
||||||
trait SeatInternal {
|
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 {
|
trait TouchSlotInternal {
|
||||||
fn new(id: u32) -> Self;
|
fn new(id: u64) -> Self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ extern crate tempfile;
|
||||||
|
|
||||||
#[cfg(feature = "backend_glutin")]
|
#[cfg(feature = "backend_glutin")]
|
||||||
extern crate glutin;
|
extern crate glutin;
|
||||||
|
#[cfg(feature = "backend_libinput")]
|
||||||
|
extern crate input;
|
||||||
|
|
||||||
#[cfg(feature = "renderer_glium")]
|
#[cfg(feature = "renderer_glium")]
|
||||||
extern crate glium;
|
extern crate glium;
|
||||||
|
|
Loading…
Reference in New Issue