use smithay_client_toolkit::seat::keyboard::
{
KeyboardHandler, KeyEvent, Keysym, Modifiers, RawModifiers, RepeatInfo,
};
use smithay_client_toolkit::seat::pointer::
{
AxisScroll, PointerEvent, PointerEventKind, PointerHandler,
BTN_BACK, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE,
};
use smithay_client_toolkit::seat::touch::TouchHandler;
use smithay_client_toolkit::reexports::client::
{
protocol::
{
wl_keyboard::WlKeyboard,
wl_pointer::{ self, WlPointer },
wl_surface::WlSurface,
wl_touch::WlTouch,
},
Connection, QueueHandle,
};
use crate::app::App;
use crate::event_loop::{ AppData, SurfaceFocus };
use crate::input::event::{ Axis, AxisSource, KeyInput, PointerButton, PointerInput, PointerKind, TouchInput, TouchPhase };
fn key_input( event: KeyEvent ) -> KeyInput
{
KeyInput { keysym: event.keysym, keycode: event.raw_code, text: event.utf8 }
}
fn pointer_button( code: u32 ) -> PointerButton
{
match code
{
BTN_LEFT => PointerButton::Left,
BTN_RIGHT => PointerButton::Right,
BTN_MIDDLE => PointerButton::Middle,
BTN_SIDE | BTN_BACK => PointerButton::Back,
_ => PointerButton::Other,
}
}
fn axis( scroll: AxisScroll ) -> Axis
{
let notches = if scroll.value120 != 0
{
scroll.value120 as f32 / 120.0
} else {
scroll.discrete as f32
};
Axis { distance: scroll.absolute, notches }
}
fn axis_source( source: Option<wl_pointer::AxisSource> ) -> AxisSource
{
match source
{
Some( wl_pointer::AxisSource::Wheel ) => AxisSource::Wheel,
Some( wl_pointer::AxisSource::Finger | wl_pointer::AxisSource::Continuous ) => AxisSource::Continuous,
_ => AxisSource::Other,
}
}
impl<A: App> KeyboardHandler for AppData<A>
{
fn enter(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &WlKeyboard,
surface: &WlSurface,
_serial: u32,
_raw: &[u32],
_keysyms: &[Keysym],
)
{
let focus = self.focus_for_surface( surface ).unwrap_or( SurfaceFocus::Main );
self.keyboard_enter( focus );
}
fn leave(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &WlKeyboard,
_surface: &WlSurface,
_serial: u32,
)
{
self.keyboard_leave();
}
fn press_key(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &WlKeyboard,
serial: u32,
event: KeyEvent,
)
{
self.platform.last_input_serial = serial;
self.key_press( key_input( event ) );
}
fn release_key(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &WlKeyboard,
_serial: u32,
event: KeyEvent,
)
{
self.key_release( &key_input( event ) );
}
fn update_modifiers(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &WlKeyboard,
_serial: u32,
modifiers: Modifiers,
_raw_modifiers: RawModifiers,
_layout: u32,
)
{
self.modifiers_changed( modifiers.ctrl, modifiers.shift, modifiers.alt );
}
fn update_repeat_info(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &WlKeyboard,
info: RepeatInfo,
)
{
match info
{
RepeatInfo::Repeat { rate, delay } => self.set_repeat_info( rate.get(), delay ),
RepeatInfo::Disable => self.set_repeat_info( 0, 0 ),
}
}
fn repeat_key(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_keyboard: &WlKeyboard,
_serial: u32,
event: KeyEvent,
)
{
self.key_repeated( key_input( event ) );
}
}
impl<A: App> PointerHandler for AppData<A>
{
fn pointer_frame(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_pointer: &WlPointer,
events: &[PointerEvent],
)
{
for event in events
{
if self.is_secondary_surface( &event.surface ) { continue; }
let focus = self.focus_for_surface( &event.surface ).unwrap_or( SurfaceFocus::Main );
let kind = match event.kind
{
PointerEventKind::Enter { serial } =>
{
self.platform.last_pointer_enter_serial = serial;
PointerKind::Enter
}
PointerEventKind::Leave { .. } => PointerKind::Leave,
PointerEventKind::Motion { .. } => PointerKind::Motion,
PointerEventKind::Press { button, serial, .. } =>
{
let button = pointer_button( button );
if matches!( button, PointerButton::Left | PointerButton::Middle )
{
self.platform.last_pointer_serial = serial;
self.platform.last_input_serial = serial;
}
PointerKind::Press( button )
}
PointerEventKind::Release { button, .. } => PointerKind::Release( pointer_button( button ) ),
PointerEventKind::Axis { horizontal, vertical, source, .. } => PointerKind::Axis
{
horizontal: axis( horizontal ),
vertical: axis( vertical ),
source: axis_source( source ),
},
};
self.pointer_input( &PointerInput { focus, position: event.position, kind } );
}
}
}
impl<A: App> TouchHandler for AppData<A>
{
fn down(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_touch: &WlTouch,
serial: u32,
time: u32,
surface: WlSurface,
id: i32,
position: ( f64, f64 ),
)
{
self.platform.last_input_serial = serial;
if self.is_secondary_surface( &surface ) { return; }
let focus = self.focus_for_surface( &surface ).unwrap_or( SurfaceFocus::Main );
self.touch_input( &TouchInput { id, time, phase: TouchPhase::Down { focus, position } } );
}
fn up(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_touch: &WlTouch,
_serial: u32,
time: u32,
id: i32,
)
{
self.touch_input( &TouchInput { id, time, phase: TouchPhase::Up } );
}
fn motion(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_touch: &WlTouch,
time: u32,
id: i32,
position: ( f64, f64 ),
)
{
self.touch_input( &TouchInput { id, time, phase: TouchPhase::Motion { position } } );
}
fn shape(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_touch: &WlTouch,
_id: i32,
_major: f64,
_minor: f64,
) {}
fn orientation(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
_touch: &WlTouch,
_id: i32,
_orientation: f64,
) {}
fn cancel( &mut self, _conn: &Connection, _qh: &QueueHandle<Self>, _touch: &WlTouch )
{
self.reset_touch_state();
}
}
#[ cfg( test ) ]
mod tests
{
use super::*;
#[ test ]
fn evdev_buttons_are_named()
{
assert_eq!( pointer_button( 0x110 ), PointerButton::Left );
assert_eq!( pointer_button( 0x111 ), PointerButton::Right );
assert_eq!( pointer_button( 0x112 ), PointerButton::Middle );
assert_eq!( pointer_button( 0x113 ), PointerButton::Back );
assert_eq!( pointer_button( 0x116 ), PointerButton::Back );
assert_eq!( pointer_button( 0x114 ), PointerButton::Other );
}
#[ test ]
fn high_resolution_detents_win()
{
let scroll = AxisScroll { absolute: 15.0, discrete: 1, value120: 60, ..AxisScroll::default() };
assert_eq!( axis( scroll ), Axis { distance: 15.0, notches: 0.5 } );
}
#[ test ]
fn whole_detents_from_an_older_compositor()
{
let scroll = AxisScroll { absolute: -30.0, discrete: -2, ..AxisScroll::default() };
assert_eq!( axis( scroll ), Axis { distance: -30.0, notches: -2.0 } );
}
#[ test ]
fn a_touchpad_scrolls_without_detents()
{
let scroll = AxisScroll { absolute: 3.5, ..AxisScroll::default() };
assert_eq!( axis( scroll ), Axis { distance: 3.5, notches: 0.0 } );
}
#[ test ]
fn axis_sources_are_named()
{
assert_eq!( axis_source( Some( wl_pointer::AxisSource::Wheel ) ), AxisSource::Wheel );
assert_eq!( axis_source( Some( wl_pointer::AxisSource::Finger ) ), AxisSource::Continuous );
assert_eq!( axis_source( Some( wl_pointer::AxisSource::Continuous ) ), AxisSource::Continuous );
assert_eq!( axis_source( Some( wl_pointer::AxisSource::WheelTilt ) ), AxisSource::Other );
assert_eq!( axis_source( None ), AxisSource::Other );
}
#[ test ]
fn a_key_event_keeps_its_code_and_text()
{
let event = KeyEvent { time: 7, raw_code: 30, keysym: Keysym::a, utf8: Some( "a".into() ) };
assert_eq!( key_input( event ), KeyInput { keysym: Keysym::a, keycode: 30, text: Some( "a".into() ) } );
}
}