backend.input: rework libinput as a calloop source

This commit is contained in:
Victor Berger 2020-05-04 13:03:36 +02:00 committed by Victor Berger
parent 5552c81a32
commit 8f543eb597
7 changed files with 471 additions and 541 deletions

View File

@ -14,7 +14,7 @@ use slog::Logger;
use smithay::backend::session::{auto::AutoSession, Session}; use smithay::backend::session::{auto::AutoSession, Session};
use smithay::{ use smithay::{
backend::input::{ backend::input::{
self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, PointerAxisEvent, self, Event, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent,
PointerButtonEvent, PointerMotionAbsoluteEvent, PointerMotionEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, PointerMotionEvent,
}, },
reexports::wayland_server::protocol::wl_pointer, reexports::wayland_server::protocol::wl_pointer,
@ -77,20 +77,21 @@ impl AnvilInputHandler {
} }
} }
impl<B: InputBackend> InputHandler<B> for AnvilInputHandler { impl AnvilInputHandler {
fn on_seat_created(&mut self, _: &input::Seat) { pub fn process_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
/* currently we just create a single static one */ match event {
InputEvent::Keyboard { event, .. } => self.on_keyboard_key::<B>(event),
InputEvent::PointerMotion { event, .. } => self.on_pointer_move::<B>(event),
InputEvent::PointerMotionAbsolute { event, .. } => self.on_pointer_move_absolute::<B>(event),
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
_ => {
// other events are not handled in anvil (yet)
}
}
} }
fn on_seat_destroyed(&mut self, _: &input::Seat) { fn on_keyboard_key<B: InputBackend>(&mut self, evt: B::KeyboardKeyEvent) {
/* currently we just create a single static one */
}
fn on_seat_changed(&mut self, _: &input::Seat) {
/* currently we just create a single static one */
}
fn on_keyboard_key(&mut self, _: &input::Seat, evt: B::KeyboardKeyEvent) {
let keycode = evt.key_code(); let keycode = evt.key_code();
let state = evt.state(); let state = evt.state();
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state)); debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
@ -146,7 +147,7 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
} }
} }
fn on_pointer_move(&mut self, _: &input::Seat, evt: B::PointerMotionEvent) { fn on_pointer_move<B: InputBackend>(&mut self, evt: B::PointerMotionEvent) {
let (x, y) = (evt.delta_x(), evt.delta_y()); let (x, y) = (evt.delta_x(), evt.delta_y());
let serial = SCOUNTER.next_serial(); let serial = SCOUNTER.next_serial();
let mut location = self.pointer_location.borrow_mut(); let mut location = self.pointer_location.borrow_mut();
@ -163,7 +164,7 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
self.pointer.motion(*location, under, serial, evt.time()); self.pointer.motion(*location, under, serial, evt.time());
} }
fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: B::PointerMotionAbsoluteEvent) { fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) {
// different cases depending on the context: // different cases depending on the context:
let (x, y) = { let (x, y) = {
#[cfg(feature = "udev")] #[cfg(feature = "udev")]
@ -188,7 +189,7 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
self.pointer.motion((x, y), under, serial, evt.time()); self.pointer.motion((x, y), under, serial, evt.time());
} }
fn on_pointer_button(&mut self, _: &input::Seat, evt: B::PointerButtonEvent) { fn on_pointer_button<B: InputBackend>(&mut self, evt: B::PointerButtonEvent) {
let serial = SCOUNTER.next_serial(); let serial = SCOUNTER.next_serial();
let button = match evt.button() { let button = match evt.button() {
input::MouseButton::Left => 0x110, input::MouseButton::Left => 0x110,
@ -214,7 +215,7 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
self.pointer.button(button, state, serial, evt.time()); self.pointer.button(button, state, serial, evt.time());
} }
fn on_pointer_axis(&mut self, _: &input::Seat, evt: B::PointerAxisEvent) { fn on_pointer_axis<B: InputBackend>(&mut self, evt: B::PointerAxisEvent) {
let source = match evt.source() { let source = match evt.source() {
input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous, input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous,
input::AxisSource::Finger => wl_pointer::AxisSource::Finger, input::AxisSource::Finger => wl_pointer::AxisSource::Finger,
@ -250,25 +251,6 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
self.pointer.axis(frame); self.pointer.axis(frame);
} }
} }
fn on_touch_down(&mut self, _: &input::Seat, _: B::TouchDownEvent) {
/* not done in this example */
}
fn on_touch_motion(&mut self, _: &input::Seat, _: B::TouchMotionEvent) {
/* not done in this example */
}
fn on_touch_up(&mut self, _: &input::Seat, _: B::TouchUpEvent) {
/* not done in this example */
}
fn on_touch_cancel(&mut self, _: &input::Seat, _: B::TouchCancelEvent) {
/* not done in this example */
}
fn on_touch_frame(&mut self, _: &input::Seat, _: B::TouchFrameEvent) {
/* not done in this example */
}
fn on_input_config_changed(&mut self, _: &mut B::InputConfig) {
/* not done in this example */
}
} }
/// Possible results of a keyboard action /// Possible results of a keyboard action

View File

@ -26,8 +26,7 @@ use smithay::{
DevPath, Device, DeviceHandler, Surface, DevPath, Device, DeviceHandler, Surface,
}, },
graphics::CursorBackend, graphics::CursorBackend,
input::InputBackend, libinput::{LibinputInputBackend, LibinputSessionInterface},
libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface},
session::{ session::{
auto::{auto_session_bind, AutoSession}, auto::{auto_session_bind, AutoSession},
notify_multiplexer, AsSessionObserver, Session, SessionNotifier, notify_multiplexer, AsSessionObserver, Session, SessionNotifier,
@ -202,8 +201,8 @@ pub fn run_udev(
Libinput::new_with_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into()); Libinput::new_with_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into());
let libinput_session_id = notifier.register(libinput_context.observer()); let libinput_session_id = notifier.register(libinput_context.observer());
libinput_context.udev_assign_seat(&seat).unwrap(); libinput_context.udev_assign_seat(&seat).unwrap();
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone()); let libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
libinput_backend.set_handler(AnvilInputHandler::new_with_session( let mut input_handler = AnvilInputHandler::new_with_session(
log.clone(), log.clone(),
InputInitData { InputInitData {
pointer, pointer,
@ -214,13 +213,16 @@ pub fn run_udev(
pointer_location, pointer_location,
}, },
session, session,
)); );
/* /*
* Bind all our objects that get driven by the event loop * Bind all our objects that get driven by the event loop
*/ */
let libinput_event_source = libinput_bind(libinput_backend, event_loop.handle()) let libinput_event_source = event_loop
.map_err(|e| -> IoError { e.into() }) .handle()
.insert_source(libinput_backend, move |event, _, _anvil_state| {
input_handler.process_event(event)
})
.unwrap(); .unwrap();
let session_event_source = auto_session_bind(notifier, event_loop.handle()) let session_event_source = auto_session_bind(notifier, event_loop.handle())
.map_err(|(e, _)| e) .map_err(|(e, _)| e)

View File

@ -31,7 +31,9 @@ pub fn run_winit(
event_loop: &mut EventLoop<AnvilState>, event_loop: &mut EventLoop<AnvilState>,
log: Logger, log: Logger,
) -> Result<(), ()> { ) -> Result<(), ()> {
let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?; let (renderer, mut input) = winit::init(log.clone()).map_err(|err| {
slog::crit!(log, "Failed to initialize Winit backend: {}", err);
})?;
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
let egl_buffer_reader = Rc::new(RefCell::new( let egl_buffer_reader = Rc::new(RefCell::new(
@ -111,7 +113,7 @@ pub fn run_winit(
let pointer_location = Rc::new(RefCell::new((0.0, 0.0))); let pointer_location = Rc::new(RefCell::new((0.0, 0.0)));
input.set_handler(AnvilInputHandler::new( let mut input_handler = AnvilInputHandler::new(
log.clone(), log.clone(),
InputInitData { InputInitData {
pointer, pointer,
@ -121,12 +123,14 @@ pub fn run_winit(
running: state.running.clone(), running: state.running.clone(),
pointer_location: pointer_location.clone(), pointer_location: pointer_location.clone(),
}, },
)); );
info!(log, "Initialization completed, starting the main loop."); info!(log, "Initialization completed, starting the main loop.");
while state.running.load(Ordering::SeqCst) { while state.running.load(Ordering::SeqCst) {
input.dispatch_new_events().unwrap(); input
.dispatch_new_events(|event, _| input_handler.process_event(event))
.unwrap();
// drawing logic // drawing logic
{ {

View File

@ -491,9 +491,6 @@ impl TouchFrameEvent for UnusedEvent {}
/// need to implement this and provide the same base guarantees about the precision of /// need to implement this and provide the same base guarantees about the precision of
/// given events. /// given events.
pub trait InputBackend: Sized { pub trait InputBackend: Sized {
/// Type of input device associated with the backend
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;
@ -518,168 +515,108 @@ pub trait InputBackend: Sized {
/// Type representing touch frame events /// Type representing touch frame events
type TouchFrameEvent: TouchFrameEvent; type TouchFrameEvent: TouchFrameEvent;
/// Sets a new handler for this [`InputBackend`] /// Special events that are custom to this backend
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, handler: H); type SpecialEvent;
/// Get a reference to the currently set handler, if any
fn get_handler(&mut self) -> Option<&mut dyn InputHandler<Self>>;
/// Clears the currently handler, if one is set
fn clear_handler(&mut self);
/// Get current `InputConfig` /// Backend-specific type allowing you to configure it
type InputConfig: ?Sized;
/// Get the list of currently known Seats
fn seats(&self) -> Vec<Seat>;
/// Access the input configuration interface
fn input_config(&mut self) -> &mut Self::InputConfig; fn input_config(&mut self) -> &mut Self::InputConfig;
/// 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>; ///
/// The callback can only assume its second argument to be usable if the event is
/// `InputEvent::ConfigChanged`.
fn dispatch_new_events<F>(&mut self, callback: F) -> Result<(), Self::EventError>
where
F: FnMut(InputEvent<Self>, &mut Self::InputConfig);
} }
/// Implement to receive input events from any [`InputBackend`]. /// Different events that can be generated by an input backend
pub trait InputHandler<B: InputBackend> { pub enum InputEvent<B: InputBackend> {
/// Called when a new [`Seat`] has been created /// A new seat has been created
fn on_seat_created(&mut self, seat: &Seat); NewSeat(Seat),
/// Called when an existing [`Seat`] has been destroyed. /// A seat has changed
fn on_seat_destroyed(&mut self, seat: &Seat); SeatChanged(Seat),
/// Called when a [`Seat`]'s properties have changed. /// A seat has been removed
SeatRemoved(Seat),
/// A keyboard event occured
Keyboard {
/// Seat that generated the event
seat: Seat,
/// The keyboard event
event: B::KeyboardKeyEvent,
},
/// A relative pointer motion occured
PointerMotion {
/// Seat that generated the event
seat: Seat,
/// The pointer motion event
event: B::PointerMotionEvent,
},
/// An absolute pointer motion occures
PointerMotionAbsolute {
/// Seat that generated the event
seat: Seat,
/// The absolute pointer motion event
event: B::PointerMotionAbsoluteEvent,
},
/// A pointer button was pressed or released
PointerButton {
/// Seat that generated the event
seat: Seat,
/// The pointer button event
event: B::PointerButtonEvent,
},
/// A pointer axis was actionned
PointerAxis {
/// Seat that generated the event
seat: Seat,
/// The pointer axis event
event: B::PointerAxisEvent,
},
/// A new touchpoint appeared
TouchDown {
/// Seat that generated the event
seat: Seat,
/// The touch down event
event: B::TouchDownEvent,
},
/// A touchpoint moved
TouchMotion {
/// Seat that generated the event
seat: Seat,
/// The touch motion event
event: B::TouchMotionEvent,
},
/// A touchpoint was removed
TouchUp {
/// Seat that generated the event
seat: Seat,
/// The touch up event
event: B::TouchUpEvent,
},
/// A touch sequence was cancelled
TouchCancel {
/// Seat that generated the event
seat: Seat,
/// The touch cancel event
event: B::TouchCancelEvent,
},
/// A touch frame was emmited
/// ///
/// ## Note: /// A set of two events received on the same seat between two frames should
/// /// be interpreted as an atomic event.
/// It is not guaranteed that any change has actually happened. TouchFrame {
fn on_seat_changed(&mut self, seat: &Seat); /// Seat that generated the event
seat: Seat,
/// Called when a new keyboard event was received. /// The touch frame event
/// event: B::TouchFrameEvent,
/// # Arguments },
/// /// Special event specific of this backend
/// - `seat` - The [`Seat`] the event belongs to Special(B::SpecialEvent),
/// - `event` - The keyboard event
///
fn on_keyboard_key(&mut self, seat: &Seat, event: B::KeyboardKeyEvent);
/// Called when a new pointer movement event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The pointer movement event
fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent);
/// Called when a new pointer absolute movement event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The pointer absolute movement event
fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent);
/// Called when a new pointer button event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The pointer button event
fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent);
/// Called when a new pointer scroll event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - A upward counting variable useful for event ordering. Makes no guarantees about actual time passed between events.
fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent);
/// Called when a new touch down event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The touch down event
fn on_touch_down(&mut self, seat: &Seat, event: B::TouchDownEvent);
/// Called when a new touch motion event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The touch motion event.
fn on_touch_motion(&mut self, seat: &Seat, event: B::TouchMotionEvent);
/// Called when a new touch up event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The touch up event.
fn on_touch_up(&mut self, seat: &Seat, event: B::TouchUpEvent);
/// Called when a new touch cancel event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The touch cancel event.
fn on_touch_cancel(&mut self, seat: &Seat, event: B::TouchCancelEvent);
/// Called when a new touch frame event was received.
///
/// # Arguments
///
/// - `seat` - The [`Seat`] the event belongs to
/// - `event` - The touch frame event.
fn on_touch_frame(&mut self, seat: &Seat, event: B::TouchFrameEvent);
/// Called when the `InputConfig` was changed through an external event.
///
/// What kind of events can trigger this call is completely backend dependent.
/// E.g. an input devices was attached/detached or changed it's own configuration.
fn on_input_config_changed(&mut self, config: &mut B::InputConfig);
}
impl<B: InputBackend> InputHandler<B> for Box<dyn InputHandler<B>> {
fn on_seat_created(&mut self, seat: &Seat) {
(**self).on_seat_created(seat)
}
fn on_seat_destroyed(&mut self, seat: &Seat) {
(**self).on_seat_destroyed(seat)
}
fn on_seat_changed(&mut self, seat: &Seat) {
(**self).on_seat_changed(seat)
}
fn on_keyboard_key(&mut self, seat: &Seat, event: B::KeyboardKeyEvent) {
(**self).on_keyboard_key(seat, event)
}
fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent) {
(**self).on_pointer_move(seat, event)
}
fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent) {
(**self).on_pointer_move_absolute(seat, event)
}
fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent) {
(**self).on_pointer_button(seat, event)
}
fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent) {
(**self).on_pointer_axis(seat, event)
}
fn on_touch_down(&mut self, seat: &Seat, event: B::TouchDownEvent) {
(**self).on_touch_down(seat, event)
}
fn on_touch_motion(&mut self, seat: &Seat, event: B::TouchMotionEvent) {
(**self).on_touch_motion(seat, event)
}
fn on_touch_up(&mut self, seat: &Seat, event: B::TouchUpEvent) {
(**self).on_touch_up(seat, event)
}
fn on_touch_cancel(&mut self, seat: &Seat, event: B::TouchCancelEvent) {
(**self).on_touch_cancel(seat, event)
}
fn on_touch_frame(&mut self, seat: &Seat, event: B::TouchFrameEvent) {
(**self).on_touch_frame(seat, event)
}
fn on_input_config_changed(&mut self, config: &mut B::InputConfig) {
(**self).on_input_config_changed(config)
}
} }

View File

@ -1,25 +1,25 @@
use crate::backend::input::{self as backend}; use crate::backend::input::{self as backend, InputEvent};
use input as libinput; use input as libinput;
use input::event::{ use input::event::{
device::DeviceEvent, keyboard::KeyboardEvent, pointer::PointerEvent, touch::TouchEvent, EventTrait, device::DeviceEvent, keyboard::KeyboardEvent, pointer::PointerEvent, touch::TouchEvent, EventTrait,
}; };
use slog::Logger; use slog::Logger;
use super::LibinputInputBackend; use super::{LibinputConfig, LibinputEvent, LibinputInputBackend};
use std::{ use std::{
collections::hash_map::{DefaultHasher, Entry, HashMap}, collections::hash_map::{DefaultHasher, Entry, HashMap},
hash::{Hash, Hasher}, hash::{Hash, Hasher},
}; };
#[inline(always)] #[inline(always)]
pub fn on_device_event<H>( pub fn on_device_event<F>(
handler: &mut Option<H>, callback: &mut F,
seats: &mut HashMap<libinput::Seat, backend::Seat>, seats: &mut HashMap<libinput::Seat, backend::Seat>,
devices: &mut Vec<libinput::Device>, config: &mut LibinputConfig,
event: DeviceEvent, event: DeviceEvent,
logger: &Logger, logger: &Logger,
) where ) where
H: backend::InputHandler<LibinputInputBackend>, F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{ {
match event { match event {
DeviceEvent::Added(device_added_event) => { DeviceEvent::Added(device_added_event) => {
@ -38,7 +38,7 @@ pub fn on_device_event<H>(
added.sysname(), added.sysname(),
device_seat.logical_name() device_seat.logical_name()
); );
devices.push(added); config.devices.push(added.clone());
match seats.entry(device_seat.clone()) { match seats.entry(device_seat.clone()) {
Entry::Occupied(mut seat_entry) => { Entry::Occupied(mut seat_entry) => {
@ -49,10 +49,7 @@ pub fn on_device_event<H>(
caps.keyboard = new_caps.keyboard || caps.keyboard; caps.keyboard = new_caps.keyboard || caps.keyboard;
caps.touch = new_caps.touch || caps.touch; caps.touch = new_caps.touch || caps.touch;
} }
if let Some(ref mut handler) = handler { callback(InputEvent::SeatChanged(old_seat.clone()), config);
trace!(logger, "Calling on_seat_changed with {:?}", old_seat);
handler.on_seat_changed(old_seat);
}
} }
Entry::Vacant(seat_entry) => { Entry::Vacant(seat_entry) => {
let mut hasher = DefaultHasher::default(); let mut hasher = DefaultHasher::default();
@ -62,18 +59,17 @@ pub fn on_device_event<H>(
format!("{}:{}", device_seat.physical_name(), device_seat.logical_name()), format!("{}:{}", device_seat.physical_name(), device_seat.logical_name()),
new_caps, new_caps,
)); ));
if let Some(ref mut handler) = handler { callback(InputEvent::NewSeat(seat.clone()), config);
trace!(logger, "Calling on_seat_created with {:?}", seat);
handler.on_seat_created(seat);
}
} }
} }
callback(InputEvent::Special(LibinputEvent::NewDevice(added)), config);
} }
DeviceEvent::Removed(device_removed_event) => { DeviceEvent::Removed(device_removed_event) => {
let removed = device_removed_event.device(); let removed = device_removed_event.device();
// remove device // remove device
devices.retain(|dev| *dev != removed); config.devices.retain(|dev| *dev != removed);
let device_seat = removed.seat(); let device_seat = removed.seat();
info!( info!(
@ -86,15 +82,18 @@ pub fn on_device_event<H>(
// update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`. // update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`.
if let Some(seat) = seats.get_mut(&device_seat) { if let Some(seat) = seats.get_mut(&device_seat) {
let caps = seat.capabilities_mut(); let caps = seat.capabilities_mut();
caps.pointer = devices caps.pointer = config
.devices
.iter() .iter()
.filter(|x| x.seat() == device_seat) .filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Pointer)); .any(|x| x.has_capability(libinput::DeviceCapability::Pointer));
caps.keyboard = devices caps.keyboard = config
.devices
.iter() .iter()
.filter(|x| x.seat() == device_seat) .filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Keyboard)); .any(|x| x.has_capability(libinput::DeviceCapability::Keyboard));
caps.touch = devices caps.touch = config
.devices
.iter() .iter()
.filter(|x| x.seat() == device_seat) .filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Touch)); .any(|x| x.has_capability(libinput::DeviceCapability::Touch));
@ -104,7 +103,7 @@ pub fn on_device_event<H>(
} }
// check if the seat has any other devices // check if the seat has any other devices
if !devices.iter().any(|x| x.seat() == device_seat) { if !config.devices.iter().any(|x| x.seat() == device_seat) {
// it has not, lets destroy it // it has not, lets destroy it
if let Some(seat) = seats.remove(&device_seat) { if let Some(seat) = seats.remove(&device_seat) {
info!( info!(
@ -112,133 +111,167 @@ pub fn on_device_event<H>(
"Removing seat {} which no longer has any device", "Removing seat {} which no longer has any device",
device_seat.logical_name() device_seat.logical_name()
); );
if let Some(ref mut handler) = handler { callback(InputEvent::SeatRemoved(seat), config);
trace!(logger, "Calling on_seat_destroyed with {:?}", seat);
handler.on_seat_destroyed(&seat);
}
} else { } else {
warn!(logger, "Seat destroyed that was never created"); warn!(logger, "Seat destroyed that was never created");
return; return;
} }
// it has, notify about updates // it has, notify about updates
} else if let Some(ref mut handler) = handler { } else if let Some(seat) = seats.get(&device_seat) {
if let Some(seat) = seats.get(&device_seat) { callback(InputEvent::SeatChanged(seat.clone()), config);
trace!(logger, "Calling on_seat_changed with {:?}", seat);
handler.on_seat_changed(&seat);
} else { } else {
warn!(logger, "Seat changed that was never created"); warn!(logger, "Seat changed that was never created");
return; return;
} }
callback(InputEvent::Special(LibinputEvent::RemovedDevice(removed)), config);
} }
} }
} }
if let Some(ref mut handler) = handler {
handler.on_input_config_changed(devices);
}
}
#[inline(always)] #[inline(always)]
pub fn on_touch_event<H>( pub fn on_touch_event<F>(
handler: &mut Option<H>, callback: &mut F,
seats: &HashMap<libinput::Seat, backend::Seat>, seats: &HashMap<libinput::Seat, backend::Seat>,
config: &mut LibinputConfig,
event: TouchEvent, event: TouchEvent,
logger: &Logger, logger: &Logger,
) where ) where
H: backend::InputHandler<LibinputInputBackend>, F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{ {
if let Some(ref mut handler) = handler {
let device_seat = event.device().seat(); let device_seat = event.device().seat();
if let Some(ref seat) = seats.get(&device_seat) { if let Some(seat) = seats.get(&device_seat).cloned() {
match event { match event {
TouchEvent::Down(down_event) => { TouchEvent::Down(down_event) => {
trace!(logger, "Calling on_touch_down with {:?}", down_event); callback(
handler.on_touch_down(seat, down_event) InputEvent::TouchDown {
seat,
event: down_event,
},
config,
);
} }
TouchEvent::Motion(motion_event) => { TouchEvent::Motion(motion_event) => {
trace!(logger, "Calling on_touch_motion with {:?}", motion_event); callback(
handler.on_touch_motion(seat, motion_event) InputEvent::TouchMotion {
seat,
event: motion_event,
},
config,
);
} }
TouchEvent::Up(up_event) => { TouchEvent::Up(up_event) => {
trace!(logger, "Calling on_touch_up with {:?}", up_event); callback(
handler.on_touch_up(seat, up_event) InputEvent::TouchUp {
seat,
event: up_event,
},
config,
);
} }
TouchEvent::Cancel(cancel_event) => { TouchEvent::Cancel(cancel_event) => {
trace!(logger, "Calling on_touch_cancel with {:?}", cancel_event); callback(
handler.on_touch_cancel(seat, cancel_event) InputEvent::TouchCancel {
seat,
event: cancel_event,
},
config,
);
} }
TouchEvent::Frame(frame_event) => { TouchEvent::Frame(frame_event) => {
trace!(logger, "Calling on_touch_frame with {:?}", frame_event); callback(
handler.on_touch_frame(seat, frame_event) InputEvent::TouchFrame {
seat,
event: frame_event,
},
config,
);
} }
} }
} else { } else {
warn!(logger, "Received touch event of non existing Seat"); warn!(logger, "Received touch event of non existing Seat");
return;
}
} }
} }
#[inline(always)] #[inline(always)]
pub fn on_keyboard_event<H>( pub fn on_keyboard_event<F>(
handler: &mut Option<H>, callback: &mut F,
seats: &HashMap<libinput::Seat, backend::Seat>, seats: &HashMap<libinput::Seat, backend::Seat>,
config: &mut LibinputConfig,
event: KeyboardEvent, event: KeyboardEvent,
logger: &Logger, logger: &Logger,
) where ) where
H: backend::InputHandler<LibinputInputBackend>, F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{ {
match event { match event {
KeyboardEvent::Key(key_event) => { KeyboardEvent::Key(key_event) => {
if let Some(ref mut handler) = handler {
let device_seat = key_event.device().seat(); let device_seat = key_event.device().seat();
if let Some(ref seat) = seats.get(&device_seat) { if let Some(seat) = seats.get(&device_seat).cloned() {
trace!(logger, "Calling on_keyboard_key with {:?}", key_event); callback(
handler.on_keyboard_key(seat, key_event); InputEvent::Keyboard {
seat,
event: key_event,
},
config,
);
} else { } else {
warn!(logger, "Received key event of non existing Seat"); warn!(logger, "Received key event of non existing Seat");
return;
}
} }
} }
} }
} }
#[inline(always)] #[inline(always)]
pub fn on_pointer_event<H>( pub fn on_pointer_event<F>(
handler: &mut Option<H>, callback: &mut F,
seats: &HashMap<libinput::Seat, backend::Seat>, seats: &HashMap<libinput::Seat, backend::Seat>,
config: &mut LibinputConfig,
event: PointerEvent, event: PointerEvent,
logger: &Logger, logger: &Logger,
) where ) where
H: backend::InputHandler<LibinputInputBackend>, F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
{ {
if let Some(ref mut handler) = handler {
let device_seat = event.device().seat(); let device_seat = event.device().seat();
if let Some(ref seat) = seats.get(&device_seat) { if let Some(seat) = seats.get(&device_seat).cloned() {
match event { match event {
PointerEvent::Motion(motion_event) => { PointerEvent::Motion(motion_event) => {
trace!(logger, "Calling on_pointer_move with {:?}", motion_event); callback(
handler.on_pointer_move(seat, motion_event); InputEvent::PointerMotion {
seat,
event: motion_event,
},
config,
);
} }
PointerEvent::MotionAbsolute(motion_abs_event) => { PointerEvent::MotionAbsolute(motion_abs_event) => {
trace!( callback(
logger, InputEvent::PointerMotionAbsolute {
"Calling on_pointer_move_absolute with {:?}", seat,
motion_abs_event event: motion_abs_event,
},
config,
); );
handler.on_pointer_move_absolute(seat, motion_abs_event);
} }
PointerEvent::Axis(axis_event) => { PointerEvent::Axis(axis_event) => {
trace!(logger, "Calling on_pointer_axis with {:?}", axis_event); callback(
handler.on_pointer_axis(seat, axis_event); InputEvent::PointerAxis {
seat,
event: axis_event,
},
config,
);
} }
PointerEvent::Button(button_event) => { PointerEvent::Button(button_event) => {
trace!(logger, "Calling on_pointer_button with {:?}", button_event); callback(
handler.on_pointer_button(seat, button_event); InputEvent::PointerButton {
seat,
event: button_event,
},
config,
);
} }
} }
} else { } else {
warn!(logger, "Received pointer event of non existing Seat"); warn!(logger, "Received pointer event of non existing Seat");
} }
} }
}

View File

@ -3,7 +3,7 @@
mod helpers; mod helpers;
use helpers::{on_device_event, on_keyboard_event, on_pointer_event, on_touch_event}; use helpers::{on_device_event, on_keyboard_event, on_pointer_event, on_touch_event};
use crate::backend::input::{self as backend, Axis, InputBackend}; use crate::backend::input::{self as backend, Axis, InputBackend, InputEvent};
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
use crate::backend::session::{AsErrno, Session, SessionObserver}; use crate::backend::session::{AsErrno, Session, SessionObserver};
use input as libinput; use input as libinput;
@ -17,7 +17,7 @@ use std::{
os::unix::io::{AsRawFd, RawFd}, os::unix::io::{AsRawFd, RawFd},
}; };
use calloop::{generic::Generic, InsertError, LoopHandle, Source}; use calloop::{EventSource, Interest, Mode, Poll, Readiness, Token};
// No idea if this is the same across unix platforms // No idea if this is the same across unix platforms
// Lets make this linux exclusive for now, once someone tries to build it for // Lets make this linux exclusive for now, once someone tries to build it for
@ -31,9 +31,8 @@ const INPUT_MAJOR: u32 = 13;
/// context. /// context.
pub struct LibinputInputBackend { pub struct LibinputInputBackend {
context: libinput::Libinput, context: libinput::Libinput,
devices: Vec<libinput::Device>, config: LibinputConfig,
seats: HashMap<libinput::Seat, backend::Seat>, seats: HashMap<libinput::Seat, backend::Seat>,
handler: Option<Box<dyn backend::InputHandler<LibinputInputBackend> + 'static>>,
logger: ::slog::Logger, logger: ::slog::Logger,
} }
@ -48,9 +47,8 @@ impl LibinputInputBackend {
info!(log, "Initializing a libinput backend"); info!(log, "Initializing a libinput backend");
LibinputInputBackend { LibinputInputBackend {
context, context,
devices: Vec::new(), config: LibinputConfig { devices: Vec::new() },
seats: HashMap::new(), seats: HashMap::new(),
handler: None,
logger: log, logger: log,
} }
} }
@ -246,8 +244,30 @@ impl backend::Event for event::touch::TouchFrameEvent {
impl backend::TouchFrameEvent for event::touch::TouchFrameEvent {} impl backend::TouchFrameEvent for event::touch::TouchFrameEvent {}
/// Special events generated by Libinput
pub enum LibinputEvent {
/// A new device was plugged in
NewDevice(libinput::Device),
/// A device was plugged out
RemovedDevice(libinput::Device),
}
/// Configuration handle for libinput
///
/// This type allows you to access the list of know devices to configure them
/// if relevant
pub struct LibinputConfig {
devices: Vec<libinput::Device>,
}
impl LibinputConfig {
/// Access the list of current devices
pub fn devices(&mut self) -> &mut [libinput::Device] {
&mut self.devices
}
}
impl InputBackend for LibinputInputBackend { impl InputBackend for LibinputInputBackend {
type InputConfig = [libinput::Device];
type EventError = IoError; type EventError = IoError;
type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent; type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent;
@ -261,60 +281,60 @@ impl InputBackend for LibinputInputBackend {
type TouchCancelEvent = event::touch::TouchCancelEvent; type TouchCancelEvent = event::touch::TouchCancelEvent;
type TouchFrameEvent = event::touch::TouchFrameEvent; type TouchFrameEvent = event::touch::TouchFrameEvent;
fn set_handler<H: backend::InputHandler<Self> + 'static>(&mut self, mut handler: H) { type SpecialEvent = LibinputEvent;
if self.handler.is_some() { type InputConfig = LibinputConfig;
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 dyn backend::InputHandler<Self>> { fn seats(&self) -> Vec<backend::Seat> {
self.handler self.seats.values().cloned().collect()
.as_mut()
.map(|handler| handler as &mut dyn 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 { fn input_config(&mut self) -> &mut Self::InputConfig {
&mut self.devices &mut self.config
} }
fn dispatch_new_events(&mut self) -> Result<(), IoError> { fn dispatch_new_events<F>(&mut self, mut callback: F) -> Result<(), IoError>
where
F: FnMut(InputEvent<Self>, &mut LibinputConfig),
{
self.context.dispatch()?; self.context.dispatch()?;
for event in &mut self.context { for event in &mut self.context {
match event { match event {
libinput::Event::Device(device_event) => { libinput::Event::Device(device_event) => {
on_device_event( on_device_event(
&mut self.handler, &mut callback,
&mut self.seats, &mut self.seats,
&mut self.devices, &mut self.config,
device_event, device_event,
&self.logger, &self.logger,
); );
} }
libinput::Event::Touch(touch_event) => { libinput::Event::Touch(touch_event) => {
on_touch_event(&mut self.handler, &self.seats, touch_event, &self.logger); on_touch_event(
&mut callback,
&self.seats,
&mut self.config,
touch_event,
&self.logger,
);
} }
libinput::Event::Keyboard(keyboard_event) => { libinput::Event::Keyboard(keyboard_event) => {
on_keyboard_event(&mut self.handler, &self.seats, keyboard_event, &self.logger); on_keyboard_event(
&mut callback,
&self.seats,
&mut self.config,
keyboard_event,
&self.logger,
);
} }
libinput::Event::Pointer(pointer_event) => { libinput::Event::Pointer(pointer_event) => {
on_pointer_event(&mut self.handler, &self.seats, pointer_event, &self.logger); on_pointer_event(
&mut callback,
&self.seats,
&mut self.config,
pointer_event,
&self.logger,
);
} }
_ => {} //FIXME: What to do with the rest. _ => {} //FIXME: What to do with the rest.
} }
@ -421,24 +441,27 @@ impl AsRawFd for LibinputInputBackend {
} }
} }
/// calloop source associated with the libinput backend impl EventSource for LibinputInputBackend {
pub type LibinputSource = Generic<LibinputInputBackend>; type Event = InputEvent<LibinputInputBackend>;
type Metadata = LibinputConfig;
type Ret = ();
/// Binds a [`LibinputInputBackend`] to a given [`LoopHandle`]. fn process_events<F>(&mut self, _: Readiness, _: Token, callback: F) -> std::io::Result<()>
/// where
/// Automatically feeds the backend with incoming events without any manual calls to F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
/// [`dispatch_new_events`](InputBackend::dispatch_new_events). Should be used to achieve the smallest possible latency. {
pub fn libinput_bind<Data: 'static>( self.dispatch_new_events(callback)
backend: LibinputInputBackend, }
handle: LoopHandle<Data>,
) -> Result<Source<LibinputSource>, InsertError<LibinputSource>> {
let source = Generic::new(backend, calloop::Interest::Readable, calloop::Mode::Level);
handle.insert_source(source, move |_, backend, _| { fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
if let Err(error) = backend.dispatch_new_events() { poll.register(self.as_raw_fd(), Interest::Readable, Mode::Level, token)
warn!(backend.logger, "Libinput errored: {}", error); }
return Err(std::io::Error::new(std::io::ErrorKind::Other, Box::new(error)));
fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
poll.reregister(self.as_raw_fd(), Interest::Readable, Mode::Level, token)
}
fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> {
poll.unregister(self.as_raw_fd())
} }
Ok(())
})
} }

View File

@ -6,7 +6,7 @@ use crate::backend::{
egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError, SurfaceCreationError}, egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError, SurfaceCreationError},
graphics::{gl::GLGraphicsBackend, CursorBackend, PixelFormat, SwapBuffersError}, graphics::{gl::GLGraphicsBackend, CursorBackend, PixelFormat, SwapBuffersError},
input::{ input::{
Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, Axis, AxisSource, Event as BackendEvent, InputBackend, InputEvent, KeyState, KeyboardKeyEvent,
MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent,
Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent,
UnusedEvent, UnusedEvent,
@ -94,13 +94,10 @@ pub struct WinitGraphicsBackend {
/// periodically to receive any events. /// periodically to receive any events.
pub struct WinitInputBackend { pub struct WinitInputBackend {
events_loop: EventLoop<()>, events_loop: EventLoop<()>,
events_handler: Option<Box<dyn WinitEventsHandler>>,
window: Rc<Window>, window: Rc<Window>,
time: Instant, time: Instant,
key_counter: u32, key_counter: u32,
seat: Seat, seat: Seat,
input_config: (),
handler: Option<Box<dyn InputHandler<WinitInputBackend> + 'static>>,
logger: ::slog::Logger, logger: ::slog::Logger,
size: Rc<RefCell<WindowSize>>, size: Rc<RefCell<WindowSize>>,
} }
@ -211,7 +208,6 @@ where
}, },
WinitInputBackend { WinitInputBackend {
events_loop, events_loop,
events_handler: None,
window, window,
time: Instant::now(), time: Instant::now(),
key_counter: 0, key_counter: 0,
@ -224,24 +220,25 @@ where
touch: true, touch: true,
}, },
), ),
input_config: (),
handler: None,
logger: log.new(o!("smithay_winit_component" => "input")), logger: log.new(o!("smithay_winit_component" => "input")),
size, size,
}, },
)) ))
} }
/// Handler trait to receive window-related events to provide a better *nested* experience. /// Specific events generated by Winit
pub trait WinitEventsHandler { pub enum WinitEvent {
/// The window was resized, can be used to adjust the associated [`Output`](::wayland::output::Output)s mode. /// The window has been resized
/// Resized {
/// Here are provided the new size (in physical pixels) and the new scale factor provided by `winit`. /// The new physical size (in pixels)
fn resized(&mut self, size: (f64, f64), scale: f64); size: (f64, f64),
/// The window gained or lost focus /// The new scale factor
fn focus_changed(&mut self, focused: bool); scale_factor: f64,
/// The window needs to be redrawn },
fn refresh(&mut self); /// The focus state of the window changed
Focus(bool),
/// A redraw was requested
Refresh,
} }
impl WinitGraphicsBackend { impl WinitGraphicsBackend {
@ -611,29 +608,12 @@ impl TouchCancelEvent for WinitTouchCancelledEvent {
} }
} }
impl WinitInputBackend { /// Input config for Winit
/// Set the events handler ///
pub fn set_events_handler<H: WinitEventsHandler + 'static>(&mut self, handler: H) { /// This backend does not allow any input configuration, so this type does nothing.
self.events_handler = Some(Box::new(handler)); pub struct WinitInputConfig;
info!(self.logger, "New events handler set.");
}
/// Get a reference to the set events handler, if any
pub fn get_events_handler(&mut self) -> Option<&mut dyn WinitEventsHandler> {
self.events_handler
.as_mut()
.map(|handler| &mut **handler as &mut dyn WinitEventsHandler)
}
/// Clear out the currently set events handler
pub fn clear_events_handler(&mut self) {
self.events_handler = None;
info!(self.logger, "Events handler unset.");
}
}
impl InputBackend for WinitInputBackend { impl InputBackend for WinitInputBackend {
type InputConfig = ();
type EventError = WinitInputError; type EventError = WinitInputError;
type KeyboardKeyEvent = WinitKeyboardInputEvent; type KeyboardKeyEvent = WinitKeyboardInputEvent;
@ -647,32 +627,17 @@ impl InputBackend for WinitInputBackend {
type TouchCancelEvent = WinitTouchCancelledEvent; type TouchCancelEvent = WinitTouchCancelledEvent;
type TouchFrameEvent = UnusedEvent; type TouchFrameEvent = UnusedEvent;
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) { type SpecialEvent = WinitEvent;
if self.handler.is_some() { type InputConfig = WinitInputConfig;
self.clear_handler();
}
info!(self.logger, "New input handler set.");
trace!(self.logger, "Calling on_seat_created with {:?}", self.seat);
handler.on_seat_created(&self.seat);
self.handler = Some(Box::new(handler));
}
fn get_handler(&mut self) -> Option<&mut dyn InputHandler<Self>> { fn seats(&self) -> Vec<Seat> {
self.handler vec![self.seat.clone()]
.as_mut()
.map(|handler| handler as &mut dyn InputHandler<Self>)
}
fn clear_handler(&mut self) {
if let Some(mut handler) = self.handler.take() {
trace!(self.logger, "Calling on_seat_destroyed with {:?}", self.seat);
handler.on_seat_destroyed(&self.seat);
}
info!(self.logger, "Removing input handler");
} }
fn input_config(&mut self) -> &mut Self::InputConfig { fn input_config(&mut self) -> &mut Self::InputConfig {
&mut self.input_config /// So much effort to return a useless singleton!
static mut CONFIG: WinitInputConfig = WinitInputConfig;
unsafe { &mut CONFIG }
} }
/// 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`].
@ -687,7 +652,10 @@ impl InputBackend for WinitInputBackend {
/// ///
/// The linked [`WinitGraphicsBackend`] will error with a lost context and should /// The linked [`WinitGraphicsBackend`] will error with a lost context and should
/// not be used anymore as well. /// not be used anymore as well.
fn dispatch_new_events(&mut self) -> ::std::result::Result<(), WinitInputError> { fn dispatch_new_events<F>(&mut self, mut callback: F) -> ::std::result::Result<(), WinitInputError>
where
F: FnMut(InputEvent<Self>, &mut WinitInputConfig),
{
let mut closed = false; let mut closed = false;
{ {
@ -701,10 +669,9 @@ impl InputBackend for WinitInputBackend {
let time = &self.time; let time = &self.time;
let seat = &self.seat; let seat = &self.seat;
let window = &self.window; let window = &self.window;
let mut handler = self.handler.as_mut();
let mut events_handler = self.events_handler.as_mut();
let logger = &self.logger; let logger = &self.logger;
let window_size = &self.size; let window_size = &self.size;
let mut callback = move |event| callback(event, &mut WinitInputConfig);
self.events_loop self.events_loop
.run_return(move |event, _target, control_flow| match event { .run_return(move |event, _target, control_flow| match event {
@ -712,16 +679,14 @@ impl InputBackend for WinitInputBackend {
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
} }
Event::RedrawRequested(_id) => { Event::RedrawRequested(_id) => {
if let Some(events_handler) = events_handler.as_mut() { callback(InputEvent::Special(WinitEvent::Refresh));
events_handler.refresh();
}
} }
Event::WindowEvent { event, .. } => { Event::WindowEvent { event, .. } => {
let duration = Instant::now().duration_since(*time); let duration = Instant::now().duration_since(*time);
let nanos = duration.subsec_nanos() as u64; let nanos = duration.subsec_nanos() as u64;
let time = ((1000 * duration.as_secs()) + (nanos / 1_000_000)) as u32; let time = ((1000 * duration.as_secs()) + (nanos / 1_000_000)) as u32;
match (event, handler.as_mut(), events_handler.as_mut()) { match event {
(WindowEvent::Resized(psize), _, events_handler) => { WindowEvent::Resized(psize) => {
trace!(logger, "Resizing window to {:?}", psize); trace!(logger, "Resizing window to {:?}", psize);
let scale_factor = window.window().scale_factor(); let scale_factor = window.window().scale_factor();
let mut wsize = window_size.borrow_mut(); let mut wsize = window_size.borrow_mut();
@ -730,156 +695,140 @@ impl InputBackend for WinitInputBackend {
if let Window::Wayland { ref surface, .. } = **window { if let Window::Wayland { ref surface, .. } = **window {
surface.resize(psize.width as i32, psize.height as i32, 0, 0); surface.resize(psize.width as i32, psize.height as i32, 0, 0);
} }
if let Some(events_handler) = events_handler { callback(InputEvent::Special(WinitEvent::Resized {
events_handler.resized(psize.into(), scale_factor); size: psize.into(),
scale_factor,
}));
} }
WindowEvent::Focused(focus) => {
callback(InputEvent::Special(WinitEvent::Focus(focus)));
} }
(WindowEvent::Focused(focus), _, Some(events_handler)) => {
events_handler.focus_changed(focus)
}
(
WindowEvent::ScaleFactorChanged { WindowEvent::ScaleFactorChanged {
scale_factor, scale_factor,
new_inner_size: new_psize, new_inner_size: new_psize,
}, } => {
_,
events_handler,
) => {
let mut wsize = window_size.borrow_mut(); let mut wsize = window_size.borrow_mut();
wsize.scale_factor = scale_factor; wsize.scale_factor = scale_factor;
if let Window::Wayland { ref surface, .. } = **window { if let Window::Wayland { ref surface, .. } = **window {
surface.resize(new_psize.width as i32, new_psize.height as i32, 0, 0); surface.resize(new_psize.width as i32, new_psize.height as i32, 0, 0);
} }
if let Some(events_handler) = events_handler { let psize_f64: (f64, f64) = (new_psize.width.into(), new_psize.height.into());
let psize_f64: (f64, f64) = callback(InputEvent::Special(WinitEvent::Resized {
(new_psize.width.into(), new_psize.height.into()); size: psize_f64,
events_handler.resized(psize_f64, wsize.scale_factor); scale_factor: wsize.scale_factor,
}));
} }
}
(
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
input: KeyboardInput { scancode, state, .. }, input: KeyboardInput { scancode, state, .. },
.. ..
}, } => {
Some(handler),
_,
) => {
match state { match state {
ElementState::Pressed => *key_counter += 1, ElementState::Pressed => *key_counter += 1,
ElementState::Released => { ElementState::Released => {
*key_counter = key_counter.checked_sub(1).unwrap_or(0) *key_counter = key_counter.checked_sub(1).unwrap_or(0)
} }
}; };
trace!(logger, "Calling on_keyboard_key with {:?}", (scancode, state)); callback(InputEvent::Keyboard {
handler.on_keyboard_key( seat: seat.clone(),
seat, event: WinitKeyboardInputEvent {
WinitKeyboardInputEvent {
time, time,
key: scancode, key: scancode,
count: *key_counter, count: *key_counter,
state, state,
}, },
) });
} }
(WindowEvent::CursorMoved { position, .. }, Some(handler), _) => { WindowEvent::CursorMoved { position, .. } => {
trace!(logger, "Calling on_pointer_move_absolute with {:?}", position);
let lpos = position.to_logical(window_size.borrow().scale_factor); let lpos = position.to_logical(window_size.borrow().scale_factor);
handler.on_pointer_move_absolute( callback(InputEvent::PointerMotionAbsolute {
seat, seat: seat.clone(),
WinitMouseMovedEvent { event: WinitMouseMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
logical_position: lpos, logical_position: lpos,
}, },
) });
} }
(WindowEvent::MouseWheel { delta, .. }, Some(handler), _) => { WindowEvent::MouseWheel { delta, .. } => {
let event = WinitMouseWheelEvent { time, delta }; let event = WinitMouseWheelEvent { time, delta };
trace!(logger, "Calling on_pointer_axis with {:?}", delta); callback(InputEvent::PointerAxis {
handler.on_pointer_axis(seat, event); seat: seat.clone(),
event,
});
} }
(WindowEvent::MouseInput { state, button, .. }, Some(handler), _) => { WindowEvent::MouseInput { state, button, .. } => {
trace!(logger, "Calling on_pointer_button with {:?}", (button, state)); callback(InputEvent::PointerButton {
handler.on_pointer_button(seat, WinitMouseInputEvent { time, button, state }) seat: seat.clone(),
event: WinitMouseInputEvent { time, button, state },
});
} }
(
WindowEvent::Touch(Touch { WindowEvent::Touch(Touch {
phase: TouchPhase::Started, phase: TouchPhase::Started,
location, location,
id, id,
.. ..
}), }) => {
Some(handler), callback(InputEvent::TouchDown {
_, seat: seat.clone(),
) => { event: WinitTouchStartedEvent {
trace!(logger, "Calling on_touch_down at {:?}", location);
handler.on_touch_down(
seat,
WinitTouchStartedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
location: location.into(), location: location.into(),
id, id,
}, },
) });
} }
(
WindowEvent::Touch(Touch { WindowEvent::Touch(Touch {
phase: TouchPhase::Moved, phase: TouchPhase::Moved,
location, location,
id, id,
.. ..
}), }) => {
Some(handler), callback(InputEvent::TouchMotion {
_, seat: seat.clone(),
) => { event: WinitTouchMovedEvent {
trace!(logger, "Calling on_touch_motion at {:?}", location);
handler.on_touch_motion(
seat,
WinitTouchMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
location: location.into(), location: location.into(),
id, id,
}, },
) });
} }
(
WindowEvent::Touch(Touch { WindowEvent::Touch(Touch {
phase: TouchPhase::Ended, phase: TouchPhase::Ended,
location, location,
id, id,
.. ..
}), }) => {
Some(handler), callback(InputEvent::TouchMotion {
_, seat: seat.clone(),
) => { event: WinitTouchMovedEvent {
trace!(logger, "Calling on_touch_motion at {:?}", location);
handler.on_touch_motion(
seat,
WinitTouchMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
location: location.into(), location: location.into(),
id, id,
}, },
); });
trace!(logger, "Calling on_touch_up"); callback(InputEvent::TouchUp {
handler.on_touch_up(seat, WinitTouchEndedEvent { time, id }); seat: seat.clone(),
event: WinitTouchEndedEvent { time, id },
})
} }
(
WindowEvent::Touch(Touch { WindowEvent::Touch(Touch {
phase: TouchPhase::Cancelled, phase: TouchPhase::Cancelled,
id, id,
.. ..
}), }) => {
Some(handler), callback(InputEvent::TouchCancel {
_, seat: seat.clone(),
) => { event: WinitTouchCancelledEvent { time, id },
trace!(logger, "Calling on_touch_cancel"); });
handler.on_touch_cancel(seat, WinitTouchCancelledEvent { time, id })
} }
(WindowEvent::CloseRequested, _, _) | (WindowEvent::Destroyed, _, _) => { WindowEvent::CloseRequested | WindowEvent::Destroyed => {
warn!(logger, "Window closed"); warn!(logger, "Window closed");
*closed_ptr = true; *closed_ptr = true;
} }