backend.input: rework libinput as a calloop source
This commit is contained in:
parent
5552c81a32
commit
8f543eb597
|
@ -14,7 +14,7 @@ use slog::Logger;
|
|||
use smithay::backend::session::{auto::AutoSession, Session};
|
||||
use smithay::{
|
||||
backend::input::{
|
||||
self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, PointerAxisEvent,
|
||||
self, Event, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent,
|
||||
PointerButtonEvent, PointerMotionAbsoluteEvent, PointerMotionEvent,
|
||||
},
|
||||
reexports::wayland_server::protocol::wl_pointer,
|
||||
|
@ -77,20 +77,21 @@ impl AnvilInputHandler {
|
|||
}
|
||||
}
|
||||
|
||||
impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
|
||||
fn on_seat_created(&mut self, _: &input::Seat) {
|
||||
/* currently we just create a single static one */
|
||||
impl AnvilInputHandler {
|
||||
pub fn process_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
||||
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) {
|
||||
/* 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) {
|
||||
fn on_keyboard_key<B: InputBackend>(&mut self, evt: B::KeyboardKeyEvent) {
|
||||
let keycode = evt.key_code();
|
||||
let state = evt.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 serial = SCOUNTER.next_serial();
|
||||
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());
|
||||
}
|
||||
|
||||
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:
|
||||
let (x, y) = {
|
||||
#[cfg(feature = "udev")]
|
||||
|
@ -188,7 +189,7 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
|
|||
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 button = match evt.button() {
|
||||
input::MouseButton::Left => 0x110,
|
||||
|
@ -214,7 +215,7 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
|
|||
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() {
|
||||
input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous,
|
||||
input::AxisSource::Finger => wl_pointer::AxisSource::Finger,
|
||||
|
@ -250,25 +251,6 @@ impl<B: InputBackend> InputHandler<B> for AnvilInputHandler {
|
|||
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
|
||||
|
|
|
@ -26,8 +26,7 @@ use smithay::{
|
|||
DevPath, Device, DeviceHandler, Surface,
|
||||
},
|
||||
graphics::CursorBackend,
|
||||
input::InputBackend,
|
||||
libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface},
|
||||
libinput::{LibinputInputBackend, LibinputSessionInterface},
|
||||
session::{
|
||||
auto::{auto_session_bind, AutoSession},
|
||||
notify_multiplexer, AsSessionObserver, Session, SessionNotifier,
|
||||
|
@ -202,8 +201,8 @@ pub fn run_udev(
|
|||
Libinput::new_with_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into());
|
||||
let libinput_session_id = notifier.register(libinput_context.observer());
|
||||
libinput_context.udev_assign_seat(&seat).unwrap();
|
||||
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
||||
libinput_backend.set_handler(AnvilInputHandler::new_with_session(
|
||||
let libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
||||
let mut input_handler = AnvilInputHandler::new_with_session(
|
||||
log.clone(),
|
||||
InputInitData {
|
||||
pointer,
|
||||
|
@ -214,13 +213,16 @@ pub fn run_udev(
|
|||
pointer_location,
|
||||
},
|
||||
session,
|
||||
));
|
||||
);
|
||||
|
||||
/*
|
||||
* Bind all our objects that get driven by the event loop
|
||||
*/
|
||||
let libinput_event_source = libinput_bind(libinput_backend, event_loop.handle())
|
||||
.map_err(|e| -> IoError { e.into() })
|
||||
let libinput_event_source = event_loop
|
||||
.handle()
|
||||
.insert_source(libinput_backend, move |event, _, _anvil_state| {
|
||||
input_handler.process_event(event)
|
||||
})
|
||||
.unwrap();
|
||||
let session_event_source = auto_session_bind(notifier, event_loop.handle())
|
||||
.map_err(|(e, _)| e)
|
||||
|
|
|
@ -31,7 +31,9 @@ pub fn run_winit(
|
|||
event_loop: &mut EventLoop<AnvilState>,
|
||||
log: Logger,
|
||||
) -> 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")]
|
||||
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)));
|
||||
|
||||
input.set_handler(AnvilInputHandler::new(
|
||||
let mut input_handler = AnvilInputHandler::new(
|
||||
log.clone(),
|
||||
InputInitData {
|
||||
pointer,
|
||||
|
@ -121,12 +123,14 @@ pub fn run_winit(
|
|||
running: state.running.clone(),
|
||||
pointer_location: pointer_location.clone(),
|
||||
},
|
||||
));
|
||||
);
|
||||
|
||||
info!(log, "Initialization completed, starting the main loop.");
|
||||
|
||||
while state.running.load(Ordering::SeqCst) {
|
||||
input.dispatch_new_events().unwrap();
|
||||
input
|
||||
.dispatch_new_events(|event, _| input_handler.process_event(event))
|
||||
.unwrap();
|
||||
|
||||
// drawing logic
|
||||
{
|
||||
|
|
|
@ -491,9 +491,6 @@ impl TouchFrameEvent for UnusedEvent {}
|
|||
/// need to implement this and provide the same base guarantees about the precision of
|
||||
/// given events.
|
||||
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 EventError: Error;
|
||||
|
||||
|
@ -518,168 +515,108 @@ pub trait InputBackend: Sized {
|
|||
/// Type representing touch frame events
|
||||
type TouchFrameEvent: TouchFrameEvent;
|
||||
|
||||
/// Sets a new handler for this [`InputBackend`]
|
||||
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, handler: H);
|
||||
/// 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);
|
||||
/// Special events that are custom to this backend
|
||||
type SpecialEvent;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// 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`].
|
||||
pub trait InputHandler<B: InputBackend> {
|
||||
/// Called when a new [`Seat`] has been created
|
||||
fn on_seat_created(&mut self, seat: &Seat);
|
||||
/// Called when an existing [`Seat`] has been destroyed.
|
||||
fn on_seat_destroyed(&mut self, seat: &Seat);
|
||||
/// Called when a [`Seat`]'s properties have changed.
|
||||
/// Different events that can be generated by an input backend
|
||||
pub enum InputEvent<B: InputBackend> {
|
||||
/// A new seat has been created
|
||||
NewSeat(Seat),
|
||||
/// A seat has changed
|
||||
SeatChanged(Seat),
|
||||
/// 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:
|
||||
///
|
||||
/// It is not guaranteed that any change has actually happened.
|
||||
fn on_seat_changed(&mut self, seat: &Seat);
|
||||
|
||||
/// Called when a new keyboard event was received.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `seat` - The [`Seat`] the event belongs to
|
||||
/// - `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)
|
||||
}
|
||||
/// A set of two events received on the same seat between two frames should
|
||||
/// be interpreted as an atomic event.
|
||||
TouchFrame {
|
||||
/// Seat that generated the event
|
||||
seat: Seat,
|
||||
/// The touch frame event
|
||||
event: B::TouchFrameEvent,
|
||||
},
|
||||
/// Special event specific of this backend
|
||||
Special(B::SpecialEvent),
|
||||
}
|
||||
|
|
|
@ -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::event::{
|
||||
device::DeviceEvent, keyboard::KeyboardEvent, pointer::PointerEvent, touch::TouchEvent, EventTrait,
|
||||
};
|
||||
use slog::Logger;
|
||||
|
||||
use super::LibinputInputBackend;
|
||||
use super::{LibinputConfig, LibinputEvent, LibinputInputBackend};
|
||||
use std::{
|
||||
collections::hash_map::{DefaultHasher, Entry, HashMap},
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
#[inline(always)]
|
||||
pub fn on_device_event<H>(
|
||||
handler: &mut Option<H>,
|
||||
pub fn on_device_event<F>(
|
||||
callback: &mut F,
|
||||
seats: &mut HashMap<libinput::Seat, backend::Seat>,
|
||||
devices: &mut Vec<libinput::Device>,
|
||||
config: &mut LibinputConfig,
|
||||
event: DeviceEvent,
|
||||
logger: &Logger,
|
||||
) where
|
||||
H: backend::InputHandler<LibinputInputBackend>,
|
||||
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
|
||||
{
|
||||
match event {
|
||||
DeviceEvent::Added(device_added_event) => {
|
||||
|
@ -38,7 +38,7 @@ pub fn on_device_event<H>(
|
|||
added.sysname(),
|
||||
device_seat.logical_name()
|
||||
);
|
||||
devices.push(added);
|
||||
config.devices.push(added.clone());
|
||||
|
||||
match seats.entry(device_seat.clone()) {
|
||||
Entry::Occupied(mut seat_entry) => {
|
||||
|
@ -49,10 +49,7 @@ pub fn on_device_event<H>(
|
|||
caps.keyboard = new_caps.keyboard || caps.keyboard;
|
||||
caps.touch = new_caps.touch || caps.touch;
|
||||
}
|
||||
if let Some(ref mut handler) = handler {
|
||||
trace!(logger, "Calling on_seat_changed with {:?}", old_seat);
|
||||
handler.on_seat_changed(old_seat);
|
||||
}
|
||||
callback(InputEvent::SeatChanged(old_seat.clone()), config);
|
||||
}
|
||||
Entry::Vacant(seat_entry) => {
|
||||
let mut hasher = DefaultHasher::default();
|
||||
|
@ -62,18 +59,17 @@ pub fn on_device_event<H>(
|
|||
format!("{}:{}", device_seat.physical_name(), device_seat.logical_name()),
|
||||
new_caps,
|
||||
));
|
||||
if let Some(ref mut handler) = handler {
|
||||
trace!(logger, "Calling on_seat_created with {:?}", seat);
|
||||
handler.on_seat_created(seat);
|
||||
}
|
||||
callback(InputEvent::NewSeat(seat.clone()), config);
|
||||
}
|
||||
}
|
||||
|
||||
callback(InputEvent::Special(LibinputEvent::NewDevice(added)), config);
|
||||
}
|
||||
DeviceEvent::Removed(device_removed_event) => {
|
||||
let removed = device_removed_event.device();
|
||||
|
||||
// remove device
|
||||
devices.retain(|dev| *dev != removed);
|
||||
config.devices.retain(|dev| *dev != removed);
|
||||
|
||||
let device_seat = removed.seat();
|
||||
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`.
|
||||
if let Some(seat) = seats.get_mut(&device_seat) {
|
||||
let caps = seat.capabilities_mut();
|
||||
caps.pointer = devices
|
||||
caps.pointer = config
|
||||
.devices
|
||||
.iter()
|
||||
.filter(|x| x.seat() == device_seat)
|
||||
.any(|x| x.has_capability(libinput::DeviceCapability::Pointer));
|
||||
caps.keyboard = devices
|
||||
caps.keyboard = config
|
||||
.devices
|
||||
.iter()
|
||||
.filter(|x| x.seat() == device_seat)
|
||||
.any(|x| x.has_capability(libinput::DeviceCapability::Keyboard));
|
||||
caps.touch = devices
|
||||
caps.touch = config
|
||||
.devices
|
||||
.iter()
|
||||
.filter(|x| x.seat() == device_seat)
|
||||
.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
|
||||
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
|
||||
if let Some(seat) = seats.remove(&device_seat) {
|
||||
info!(
|
||||
|
@ -112,133 +111,167 @@ pub fn on_device_event<H>(
|
|||
"Removing seat {} which no longer has any device",
|
||||
device_seat.logical_name()
|
||||
);
|
||||
if let Some(ref mut handler) = handler {
|
||||
trace!(logger, "Calling on_seat_destroyed with {:?}", seat);
|
||||
handler.on_seat_destroyed(&seat);
|
||||
}
|
||||
callback(InputEvent::SeatRemoved(seat), config);
|
||||
} else {
|
||||
warn!(logger, "Seat destroyed that was never created");
|
||||
return;
|
||||
}
|
||||
// it has, notify about updates
|
||||
} else if let Some(ref mut handler) = handler {
|
||||
if let Some(seat) = seats.get(&device_seat) {
|
||||
trace!(logger, "Calling on_seat_changed with {:?}", seat);
|
||||
handler.on_seat_changed(&seat);
|
||||
} else if let Some(seat) = seats.get(&device_seat) {
|
||||
callback(InputEvent::SeatChanged(seat.clone()), config);
|
||||
} else {
|
||||
warn!(logger, "Seat changed that was never created");
|
||||
return;
|
||||
}
|
||||
|
||||
callback(InputEvent::Special(LibinputEvent::RemovedDevice(removed)), config);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(ref mut handler) = handler {
|
||||
handler.on_input_config_changed(devices);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn on_touch_event<H>(
|
||||
handler: &mut Option<H>,
|
||||
pub fn on_touch_event<F>(
|
||||
callback: &mut F,
|
||||
seats: &HashMap<libinput::Seat, backend::Seat>,
|
||||
config: &mut LibinputConfig,
|
||||
event: TouchEvent,
|
||||
logger: &Logger,
|
||||
) where
|
||||
H: backend::InputHandler<LibinputInputBackend>,
|
||||
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
|
||||
{
|
||||
if let Some(ref mut handler) = handler {
|
||||
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 {
|
||||
TouchEvent::Down(down_event) => {
|
||||
trace!(logger, "Calling on_touch_down with {:?}", down_event);
|
||||
handler.on_touch_down(seat, down_event)
|
||||
callback(
|
||||
InputEvent::TouchDown {
|
||||
seat,
|
||||
event: down_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
TouchEvent::Motion(motion_event) => {
|
||||
trace!(logger, "Calling on_touch_motion with {:?}", motion_event);
|
||||
handler.on_touch_motion(seat, motion_event)
|
||||
callback(
|
||||
InputEvent::TouchMotion {
|
||||
seat,
|
||||
event: motion_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
TouchEvent::Up(up_event) => {
|
||||
trace!(logger, "Calling on_touch_up with {:?}", up_event);
|
||||
handler.on_touch_up(seat, up_event)
|
||||
callback(
|
||||
InputEvent::TouchUp {
|
||||
seat,
|
||||
event: up_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
TouchEvent::Cancel(cancel_event) => {
|
||||
trace!(logger, "Calling on_touch_cancel with {:?}", cancel_event);
|
||||
handler.on_touch_cancel(seat, cancel_event)
|
||||
callback(
|
||||
InputEvent::TouchCancel {
|
||||
seat,
|
||||
event: cancel_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
TouchEvent::Frame(frame_event) => {
|
||||
trace!(logger, "Calling on_touch_frame with {:?}", frame_event);
|
||||
handler.on_touch_frame(seat, frame_event)
|
||||
callback(
|
||||
InputEvent::TouchFrame {
|
||||
seat,
|
||||
event: frame_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!(logger, "Received touch event of non existing Seat");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn on_keyboard_event<H>(
|
||||
handler: &mut Option<H>,
|
||||
pub fn on_keyboard_event<F>(
|
||||
callback: &mut F,
|
||||
seats: &HashMap<libinput::Seat, backend::Seat>,
|
||||
config: &mut LibinputConfig,
|
||||
event: KeyboardEvent,
|
||||
logger: &Logger,
|
||||
) where
|
||||
H: backend::InputHandler<LibinputInputBackend>,
|
||||
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
|
||||
{
|
||||
match event {
|
||||
KeyboardEvent::Key(key_event) => {
|
||||
if let Some(ref mut handler) = handler {
|
||||
let device_seat = key_event.device().seat();
|
||||
if let Some(ref seat) = seats.get(&device_seat) {
|
||||
trace!(logger, "Calling on_keyboard_key with {:?}", key_event);
|
||||
handler.on_keyboard_key(seat, key_event);
|
||||
if let Some(seat) = seats.get(&device_seat).cloned() {
|
||||
callback(
|
||||
InputEvent::Keyboard {
|
||||
seat,
|
||||
event: key_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
} else {
|
||||
warn!(logger, "Received key event of non existing Seat");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn on_pointer_event<H>(
|
||||
handler: &mut Option<H>,
|
||||
pub fn on_pointer_event<F>(
|
||||
callback: &mut F,
|
||||
seats: &HashMap<libinput::Seat, backend::Seat>,
|
||||
config: &mut LibinputConfig,
|
||||
event: PointerEvent,
|
||||
logger: &Logger,
|
||||
) where
|
||||
H: backend::InputHandler<LibinputInputBackend>,
|
||||
F: FnMut(InputEvent<LibinputInputBackend>, &mut LibinputConfig),
|
||||
{
|
||||
if let Some(ref mut handler) = handler {
|
||||
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 {
|
||||
PointerEvent::Motion(motion_event) => {
|
||||
trace!(logger, "Calling on_pointer_move with {:?}", motion_event);
|
||||
handler.on_pointer_move(seat, motion_event);
|
||||
callback(
|
||||
InputEvent::PointerMotion {
|
||||
seat,
|
||||
event: motion_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
PointerEvent::MotionAbsolute(motion_abs_event) => {
|
||||
trace!(
|
||||
logger,
|
||||
"Calling on_pointer_move_absolute with {:?}",
|
||||
motion_abs_event
|
||||
callback(
|
||||
InputEvent::PointerMotionAbsolute {
|
||||
seat,
|
||||
event: motion_abs_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
handler.on_pointer_move_absolute(seat, motion_abs_event);
|
||||
}
|
||||
PointerEvent::Axis(axis_event) => {
|
||||
trace!(logger, "Calling on_pointer_axis with {:?}", axis_event);
|
||||
handler.on_pointer_axis(seat, axis_event);
|
||||
callback(
|
||||
InputEvent::PointerAxis {
|
||||
seat,
|
||||
event: axis_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
PointerEvent::Button(button_event) => {
|
||||
trace!(logger, "Calling on_pointer_button with {:?}", button_event);
|
||||
handler.on_pointer_button(seat, button_event);
|
||||
callback(
|
||||
InputEvent::PointerButton {
|
||||
seat,
|
||||
event: button_event,
|
||||
},
|
||||
config,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!(logger, "Received pointer event of non existing Seat");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
mod helpers;
|
||||
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")]
|
||||
use crate::backend::session::{AsErrno, Session, SessionObserver};
|
||||
use input as libinput;
|
||||
|
@ -17,7 +17,7 @@ use std::{
|
|||
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
|
||||
// Lets make this linux exclusive for now, once someone tries to build it for
|
||||
|
@ -31,9 +31,8 @@ const INPUT_MAJOR: u32 = 13;
|
|||
/// context.
|
||||
pub struct LibinputInputBackend {
|
||||
context: libinput::Libinput,
|
||||
devices: Vec<libinput::Device>,
|
||||
config: LibinputConfig,
|
||||
seats: HashMap<libinput::Seat, backend::Seat>,
|
||||
handler: Option<Box<dyn backend::InputHandler<LibinputInputBackend> + 'static>>,
|
||||
logger: ::slog::Logger,
|
||||
}
|
||||
|
||||
|
@ -48,9 +47,8 @@ impl LibinputInputBackend {
|
|||
info!(log, "Initializing a libinput backend");
|
||||
LibinputInputBackend {
|
||||
context,
|
||||
devices: Vec::new(),
|
||||
config: LibinputConfig { devices: Vec::new() },
|
||||
seats: HashMap::new(),
|
||||
handler: None,
|
||||
logger: log,
|
||||
}
|
||||
}
|
||||
|
@ -246,8 +244,30 @@ impl backend::Event 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 {
|
||||
type InputConfig = [libinput::Device];
|
||||
type EventError = IoError;
|
||||
|
||||
type KeyboardKeyEvent = event::keyboard::KeyboardKeyEvent;
|
||||
|
@ -261,60 +281,60 @@ impl InputBackend for LibinputInputBackend {
|
|||
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));
|
||||
}
|
||||
type SpecialEvent = LibinputEvent;
|
||||
type InputConfig = LibinputConfig;
|
||||
|
||||
fn get_handler(&mut self) -> Option<&mut dyn backend::InputHandler<Self>> {
|
||||
self.handler
|
||||
.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 seats(&self) -> Vec<backend::Seat> {
|
||||
self.seats.values().cloned().collect()
|
||||
}
|
||||
|
||||
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()?;
|
||||
|
||||
for event in &mut self.context {
|
||||
match event {
|
||||
libinput::Event::Device(device_event) => {
|
||||
on_device_event(
|
||||
&mut self.handler,
|
||||
&mut callback,
|
||||
&mut self.seats,
|
||||
&mut self.devices,
|
||||
&mut self.config,
|
||||
device_event,
|
||||
&self.logger,
|
||||
);
|
||||
}
|
||||
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) => {
|
||||
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) => {
|
||||
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.
|
||||
}
|
||||
|
@ -421,24 +441,27 @@ impl AsRawFd for LibinputInputBackend {
|
|||
}
|
||||
}
|
||||
|
||||
/// calloop source associated with the libinput backend
|
||||
pub type LibinputSource = Generic<LibinputInputBackend>;
|
||||
impl EventSource for LibinputInputBackend {
|
||||
type Event = InputEvent<LibinputInputBackend>;
|
||||
type Metadata = LibinputConfig;
|
||||
type Ret = ();
|
||||
|
||||
/// Binds a [`LibinputInputBackend`] to a given [`LoopHandle`].
|
||||
///
|
||||
/// Automatically feeds the backend with incoming events without any manual calls to
|
||||
/// [`dispatch_new_events`](InputBackend::dispatch_new_events). Should be used to achieve the smallest possible latency.
|
||||
pub fn libinput_bind<Data: 'static>(
|
||||
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, _| {
|
||||
if let Err(error) = backend.dispatch_new_events() {
|
||||
warn!(backend.logger, "Libinput errored: {}", error);
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::Other, Box::new(error)));
|
||||
fn process_events<F>(&mut self, _: Readiness, _: Token, callback: F) -> std::io::Result<()>
|
||||
where
|
||||
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
|
||||
{
|
||||
self.dispatch_new_events(callback)
|
||||
}
|
||||
|
||||
fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||
poll.register(self.as_raw_fd(), Interest::Readable, Mode::Level, token)
|
||||
}
|
||||
|
||||
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(())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::backend::{
|
|||
egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError, SurfaceCreationError},
|
||||
graphics::{gl::GLGraphicsBackend, CursorBackend, PixelFormat, SwapBuffersError},
|
||||
input::{
|
||||
Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
|
||||
Axis, AxisSource, Event as BackendEvent, InputBackend, InputEvent, KeyState, KeyboardKeyEvent,
|
||||
MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent,
|
||||
Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent,
|
||||
UnusedEvent,
|
||||
|
@ -94,13 +94,10 @@ pub struct WinitGraphicsBackend {
|
|||
/// periodically to receive any events.
|
||||
pub struct WinitInputBackend {
|
||||
events_loop: EventLoop<()>,
|
||||
events_handler: Option<Box<dyn WinitEventsHandler>>,
|
||||
window: Rc<Window>,
|
||||
time: Instant,
|
||||
key_counter: u32,
|
||||
seat: Seat,
|
||||
input_config: (),
|
||||
handler: Option<Box<dyn InputHandler<WinitInputBackend> + 'static>>,
|
||||
logger: ::slog::Logger,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
}
|
||||
|
@ -211,7 +208,6 @@ where
|
|||
},
|
||||
WinitInputBackend {
|
||||
events_loop,
|
||||
events_handler: None,
|
||||
window,
|
||||
time: Instant::now(),
|
||||
key_counter: 0,
|
||||
|
@ -224,24 +220,25 @@ where
|
|||
touch: true,
|
||||
},
|
||||
),
|
||||
input_config: (),
|
||||
handler: None,
|
||||
logger: log.new(o!("smithay_winit_component" => "input")),
|
||||
size,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
/// Handler trait to receive window-related events to provide a better *nested* experience.
|
||||
pub trait WinitEventsHandler {
|
||||
/// The window was resized, can be used to adjust the associated [`Output`](::wayland::output::Output)s mode.
|
||||
///
|
||||
/// Here are provided the new size (in physical pixels) and the new scale factor provided by `winit`.
|
||||
fn resized(&mut self, size: (f64, f64), scale: f64);
|
||||
/// The window gained or lost focus
|
||||
fn focus_changed(&mut self, focused: bool);
|
||||
/// The window needs to be redrawn
|
||||
fn refresh(&mut self);
|
||||
/// Specific events generated by Winit
|
||||
pub enum WinitEvent {
|
||||
/// The window has been resized
|
||||
Resized {
|
||||
/// The new physical size (in pixels)
|
||||
size: (f64, f64),
|
||||
/// The new scale factor
|
||||
scale_factor: f64,
|
||||
},
|
||||
/// The focus state of the window changed
|
||||
Focus(bool),
|
||||
/// A redraw was requested
|
||||
Refresh,
|
||||
}
|
||||
|
||||
impl WinitGraphicsBackend {
|
||||
|
@ -611,29 +608,12 @@ impl TouchCancelEvent for WinitTouchCancelledEvent {
|
|||
}
|
||||
}
|
||||
|
||||
impl WinitInputBackend {
|
||||
/// Set the events handler
|
||||
pub fn set_events_handler<H: WinitEventsHandler + 'static>(&mut self, handler: H) {
|
||||
self.events_handler = Some(Box::new(handler));
|
||||
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.");
|
||||
}
|
||||
}
|
||||
/// Input config for Winit
|
||||
///
|
||||
/// This backend does not allow any input configuration, so this type does nothing.
|
||||
pub struct WinitInputConfig;
|
||||
|
||||
impl InputBackend for WinitInputBackend {
|
||||
type InputConfig = ();
|
||||
type EventError = WinitInputError;
|
||||
|
||||
type KeyboardKeyEvent = WinitKeyboardInputEvent;
|
||||
|
@ -647,32 +627,17 @@ impl InputBackend for WinitInputBackend {
|
|||
type TouchCancelEvent = WinitTouchCancelledEvent;
|
||||
type TouchFrameEvent = UnusedEvent;
|
||||
|
||||
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
|
||||
if self.handler.is_some() {
|
||||
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));
|
||||
}
|
||||
type SpecialEvent = WinitEvent;
|
||||
type InputConfig = WinitInputConfig;
|
||||
|
||||
fn get_handler(&mut self) -> Option<&mut dyn InputHandler<Self>> {
|
||||
self.handler
|
||||
.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 seats(&self) -> Vec<Seat> {
|
||||
vec![self.seat.clone()]
|
||||
}
|
||||
|
||||
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`].
|
||||
|
@ -687,7 +652,10 @@ impl InputBackend for WinitInputBackend {
|
|||
///
|
||||
/// The linked [`WinitGraphicsBackend`] will error with a lost context and should
|
||||
/// 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;
|
||||
|
||||
{
|
||||
|
@ -701,10 +669,9 @@ impl InputBackend for WinitInputBackend {
|
|||
let time = &self.time;
|
||||
let seat = &self.seat;
|
||||
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 window_size = &self.size;
|
||||
let mut callback = move |event| callback(event, &mut WinitInputConfig);
|
||||
|
||||
self.events_loop
|
||||
.run_return(move |event, _target, control_flow| match event {
|
||||
|
@ -712,16 +679,14 @@ impl InputBackend for WinitInputBackend {
|
|||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
Event::RedrawRequested(_id) => {
|
||||
if let Some(events_handler) = events_handler.as_mut() {
|
||||
events_handler.refresh();
|
||||
}
|
||||
callback(InputEvent::Special(WinitEvent::Refresh));
|
||||
}
|
||||
Event::WindowEvent { event, .. } => {
|
||||
let duration = Instant::now().duration_since(*time);
|
||||
let nanos = duration.subsec_nanos() as u64;
|
||||
let time = ((1000 * duration.as_secs()) + (nanos / 1_000_000)) as u32;
|
||||
match (event, handler.as_mut(), events_handler.as_mut()) {
|
||||
(WindowEvent::Resized(psize), _, events_handler) => {
|
||||
match event {
|
||||
WindowEvent::Resized(psize) => {
|
||||
trace!(logger, "Resizing window to {:?}", psize);
|
||||
let scale_factor = window.window().scale_factor();
|
||||
let mut wsize = window_size.borrow_mut();
|
||||
|
@ -730,156 +695,140 @@ impl InputBackend for WinitInputBackend {
|
|||
if let Window::Wayland { ref surface, .. } = **window {
|
||||
surface.resize(psize.width as i32, psize.height as i32, 0, 0);
|
||||
}
|
||||
if let Some(events_handler) = events_handler {
|
||||
events_handler.resized(psize.into(), scale_factor);
|
||||
callback(InputEvent::Special(WinitEvent::Resized {
|
||||
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 {
|
||||
scale_factor,
|
||||
new_inner_size: new_psize,
|
||||
},
|
||||
_,
|
||||
events_handler,
|
||||
) => {
|
||||
} => {
|
||||
let mut wsize = window_size.borrow_mut();
|
||||
wsize.scale_factor = scale_factor;
|
||||
if let Window::Wayland { ref surface, .. } = **window {
|
||||
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());
|
||||
events_handler.resized(psize_f64, wsize.scale_factor);
|
||||
let psize_f64: (f64, f64) = (new_psize.width.into(), new_psize.height.into());
|
||||
callback(InputEvent::Special(WinitEvent::Resized {
|
||||
size: psize_f64,
|
||||
scale_factor: wsize.scale_factor,
|
||||
}));
|
||||
}
|
||||
}
|
||||
(
|
||||
WindowEvent::KeyboardInput {
|
||||
input: KeyboardInput { scancode, state, .. },
|
||||
..
|
||||
},
|
||||
Some(handler),
|
||||
_,
|
||||
) => {
|
||||
} => {
|
||||
match state {
|
||||
ElementState::Pressed => *key_counter += 1,
|
||||
ElementState::Released => {
|
||||
*key_counter = key_counter.checked_sub(1).unwrap_or(0)
|
||||
}
|
||||
};
|
||||
trace!(logger, "Calling on_keyboard_key with {:?}", (scancode, state));
|
||||
handler.on_keyboard_key(
|
||||
seat,
|
||||
WinitKeyboardInputEvent {
|
||||
callback(InputEvent::Keyboard {
|
||||
seat: seat.clone(),
|
||||
event: WinitKeyboardInputEvent {
|
||||
time,
|
||||
key: scancode,
|
||||
count: *key_counter,
|
||||
state,
|
||||
},
|
||||
)
|
||||
});
|
||||
}
|
||||
(WindowEvent::CursorMoved { position, .. }, Some(handler), _) => {
|
||||
trace!(logger, "Calling on_pointer_move_absolute with {:?}", position);
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let lpos = position.to_logical(window_size.borrow().scale_factor);
|
||||
handler.on_pointer_move_absolute(
|
||||
seat,
|
||||
WinitMouseMovedEvent {
|
||||
callback(InputEvent::PointerMotionAbsolute {
|
||||
seat: seat.clone(),
|
||||
event: WinitMouseMovedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
logical_position: lpos,
|
||||
},
|
||||
)
|
||||
});
|
||||
}
|
||||
(WindowEvent::MouseWheel { delta, .. }, Some(handler), _) => {
|
||||
WindowEvent::MouseWheel { delta, .. } => {
|
||||
let event = WinitMouseWheelEvent { time, delta };
|
||||
trace!(logger, "Calling on_pointer_axis with {:?}", delta);
|
||||
handler.on_pointer_axis(seat, event);
|
||||
callback(InputEvent::PointerAxis {
|
||||
seat: seat.clone(),
|
||||
event,
|
||||
});
|
||||
}
|
||||
(WindowEvent::MouseInput { state, button, .. }, Some(handler), _) => {
|
||||
trace!(logger, "Calling on_pointer_button with {:?}", (button, state));
|
||||
handler.on_pointer_button(seat, WinitMouseInputEvent { time, button, state })
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
callback(InputEvent::PointerButton {
|
||||
seat: seat.clone(),
|
||||
event: WinitMouseInputEvent { time, button, state },
|
||||
});
|
||||
}
|
||||
(
|
||||
|
||||
WindowEvent::Touch(Touch {
|
||||
phase: TouchPhase::Started,
|
||||
location,
|
||||
id,
|
||||
..
|
||||
}),
|
||||
Some(handler),
|
||||
_,
|
||||
) => {
|
||||
trace!(logger, "Calling on_touch_down at {:?}", location);
|
||||
handler.on_touch_down(
|
||||
seat,
|
||||
WinitTouchStartedEvent {
|
||||
}) => {
|
||||
callback(InputEvent::TouchDown {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchStartedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
location: location.into(),
|
||||
id,
|
||||
},
|
||||
)
|
||||
});
|
||||
}
|
||||
(
|
||||
WindowEvent::Touch(Touch {
|
||||
phase: TouchPhase::Moved,
|
||||
location,
|
||||
id,
|
||||
..
|
||||
}),
|
||||
Some(handler),
|
||||
_,
|
||||
) => {
|
||||
trace!(logger, "Calling on_touch_motion at {:?}", location);
|
||||
handler.on_touch_motion(
|
||||
seat,
|
||||
WinitTouchMovedEvent {
|
||||
}) => {
|
||||
callback(InputEvent::TouchMotion {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchMovedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
location: location.into(),
|
||||
id,
|
||||
},
|
||||
)
|
||||
});
|
||||
}
|
||||
(
|
||||
|
||||
WindowEvent::Touch(Touch {
|
||||
phase: TouchPhase::Ended,
|
||||
location,
|
||||
id,
|
||||
..
|
||||
}),
|
||||
Some(handler),
|
||||
_,
|
||||
) => {
|
||||
trace!(logger, "Calling on_touch_motion at {:?}", location);
|
||||
handler.on_touch_motion(
|
||||
seat,
|
||||
WinitTouchMovedEvent {
|
||||
}) => {
|
||||
callback(InputEvent::TouchMotion {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchMovedEvent {
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
location: location.into(),
|
||||
id,
|
||||
},
|
||||
);
|
||||
trace!(logger, "Calling on_touch_up");
|
||||
handler.on_touch_up(seat, WinitTouchEndedEvent { time, id });
|
||||
});
|
||||
callback(InputEvent::TouchUp {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchEndedEvent { time, id },
|
||||
})
|
||||
}
|
||||
(
|
||||
|
||||
WindowEvent::Touch(Touch {
|
||||
phase: TouchPhase::Cancelled,
|
||||
id,
|
||||
..
|
||||
}),
|
||||
Some(handler),
|
||||
_,
|
||||
) => {
|
||||
trace!(logger, "Calling on_touch_cancel");
|
||||
handler.on_touch_cancel(seat, WinitTouchCancelledEvent { time, id })
|
||||
}) => {
|
||||
callback(InputEvent::TouchCancel {
|
||||
seat: seat.clone(),
|
||||
event: WinitTouchCancelledEvent { time, id },
|
||||
});
|
||||
}
|
||||
(WindowEvent::CloseRequested, _, _) | (WindowEvent::Destroyed, _, _) => {
|
||||
WindowEvent::CloseRequested | WindowEvent::Destroyed => {
|
||||
warn!(logger, "Window closed");
|
||||
*closed_ptr = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue