1
1
//! Keyboard-related types for smithay's input abstraction
2
2
3
- use crate :: backend:: input:: KeyState ;
3
+ use crate :: backend:: input:: { Event , InputBackend , KeyEvent , KeyState , KeyboardKeyEvent } ;
4
+ use crate :: reexports:: calloop:: LoopHandle ;
4
5
use crate :: utils:: { IsAlive , Serial , SERIAL_COUNTER } ;
6
+ use calloop:: RegistrationToken ;
5
7
use downcast_rs:: { impl_downcast, Downcast } ;
6
8
use std:: collections:: HashSet ;
9
+ use std:: time:: Duration ;
7
10
#[ cfg( feature = "wayland_frontend" ) ]
8
11
use std:: sync:: RwLock ;
9
12
use std:: {
@@ -12,7 +15,7 @@ use std::{
12
15
sync:: { Arc , Mutex } ,
13
16
} ;
14
17
use thiserror:: Error ;
15
- use tracing:: { debug, error, info, info_span, instrument, trace} ;
18
+ use tracing:: { debug, error, info, info_span, instrument, trace, warn } ;
16
19
17
20
use xkbcommon:: xkb:: ffi:: XKB_STATE_LAYOUT_EFFECTIVE ;
18
21
pub use xkbcommon:: xkb:: { self , keysyms, Keycode , Keysym } ;
47
50
seat : & Seat < D > ,
48
51
data : & mut D ,
49
52
key : KeysymHandle < ' _ > ,
50
- state : KeyState ,
53
+ state : KeyEvent ,
51
54
serial : Serial ,
52
55
time : u32 ,
53
56
) ;
@@ -215,6 +218,17 @@ pub(crate) struct KbdInternal<D: SeatHandler> {
215
218
led_mapping : LedMapping ,
216
219
pub ( crate ) led_state : LedState ,
217
220
grab : GrabStatus < dyn KeyboardGrab < D > > ,
221
+ /// Warning: the token cannot unregister itself when the object is dropped, because it can't hold a reference to the event loop. This object is Send, but the event loop is not.
222
+ pub ( crate ) key_repeat_timer : Option < RegistrationToken > ,
223
+ }
224
+
225
+ #[ cfg( feature = "wayland_frontend" ) ]
226
+ impl < D : SeatHandler > Drop for KbdInternal < D > {
227
+ fn drop ( & mut self ) {
228
+ if self . key_repeat_timer . is_some ( ) {
229
+ error ! ( "A keyboard was dropped without unregistering a repeat handler. This is a bug in smithay or in the compositor." ) ;
230
+ }
231
+ }
218
232
}
219
233
220
234
// focus_hook does not implement debug, so we have to impl Debug manually
@@ -229,6 +243,7 @@ impl<D: SeatHandler> fmt::Debug for KbdInternal<D> {
229
243
. field ( "xkb" , & self . xkb )
230
244
. field ( "repeat_rate" , & self . repeat_rate )
231
245
. field ( "repeat_delay" , & self . repeat_delay )
246
+ . field ( "key_repeat_timer" , & self . key_repeat_timer )
232
247
. finish ( )
233
248
}
234
249
}
@@ -266,21 +281,25 @@ impl<D: SeatHandler + 'static> KbdInternal<D> {
266
281
led_mapping,
267
282
led_state,
268
283
grab : GrabStatus :: None ,
284
+ key_repeat_timer : None ,
269
285
} )
270
286
}
271
287
272
288
// returns whether the modifiers or led state has changed
273
- fn key_input ( & mut self , keycode : Keycode , state : KeyState ) -> ( bool , bool ) {
289
+ fn key_input ( & mut self , keycode : Keycode , state : KeyEvent ) -> ( bool , bool ) {
274
290
// track pressed keys as xkbcommon does not seem to expose it :(
275
291
let direction = match state {
276
- KeyState :: Pressed => {
292
+ KeyEvent :: Pressed => {
277
293
self . pressed_keys . insert ( keycode) ;
278
294
xkb:: KeyDirection :: Down
279
295
}
280
- KeyState :: Released => {
296
+ KeyEvent :: Released => {
281
297
self . pressed_keys . remove ( & keycode) ;
282
298
xkb:: KeyDirection :: Up
283
299
}
300
+ KeyEvent :: Repeated | _ => {
301
+ return ( false , false ) ;
302
+ }
284
303
} ;
285
304
286
305
// update state
@@ -602,10 +621,10 @@ pub trait KeyboardGrab<D: SeatHandler>: Downcast {
602
621
data : & mut D ,
603
622
handle : & mut KeyboardInnerHandle < ' _ , D > ,
604
623
keycode : Keycode ,
605
- state : KeyState ,
624
+ event : KeyEvent ,
606
625
modifiers : Option < ModifiersState > ,
607
626
serial : Serial ,
608
- time : u32 ,
627
+ time_ms : u32 ,
609
628
) ;
610
629
611
630
/// A focus change was requested.
@@ -931,6 +950,91 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
931
950
}
932
951
}
933
952
953
+ /// Processes the keyboard event, starting or stopping key repeat.
954
+ /// If this method is used, it must receive all keyboard events.
955
+ /// The `on_event` argument will be called with all events: the ones received directly and the generated repeats.
956
+ pub fn key_register_repeat < B : InputBackend > (
957
+ & self ,
958
+ data : & mut D ,
959
+ get_handle : impl Fn ( & D ) -> & LoopHandle < ' static , D > + ' static ,
960
+ event : B :: KeyboardKeyEvent ,
961
+ // event, timeout, code.
962
+ // This is Clone because there are two closures in here...
963
+ on_event : impl Fn ( & mut D , KeyEvent , u32 , Keycode ) + Clone + ' static ,
964
+ ) {
965
+ let time_ms = event. time_msec ( ) ;
966
+ let keycode = event. key_code ( ) ;
967
+ let state = event. state ( ) ;
968
+
969
+ // Forward initial hardware event as logical event
970
+ on_event ( data, state. into ( ) , time_ms, keycode) ;
971
+
972
+ // Unregister preexisting repeating
973
+ // Releasing a key press obviously stops the repeat.
974
+ // But also, pressing another key stops the repeat of the previous key and starts it for the newly pressed key.
975
+ // TODO: this may had odd consequences when a modifier is pressed as the second key. But is that worth worrying about?
976
+ self . key_stop_repeat ( data, & get_handle) ;
977
+
978
+ // Register repeating
979
+ match event. state ( ) {
980
+ KeyState :: Pressed => {
981
+ let mut guard = self . arc . internal . lock ( ) . unwrap ( ) ;
982
+ let delay = guard. repeat_delay ;
983
+ let rate = guard. repeat_rate ;
984
+ let mut time_ms = time_ms;
985
+
986
+ // This closure-in-closure business is somewhat ugly.
987
+ // The reason is that there are two timers needed: first, the delay timer, and after the delay, the repeat timer. Both of them receive different tokens for cancelling, so we have to swap the token after the delay.
988
+ // The only comparable alternative I can think of is to wrap the key_repeat_timer in an Mutex<Arc<>> and change the token when delay turns into repeat. But locks are worse than nesting.
989
+ let kbd = self . arc . clone ( ) ;
990
+ let duration = Duration :: from_millis ( delay as _ ) ;
991
+ let handle = get_handle ( data) ;
992
+ guard. key_repeat_timer = Some ( handle. insert_source (
993
+ calloop:: timer:: Timer :: from_duration ( duration) ,
994
+ move |_, _, data| {
995
+ time_ms += delay as u32 ;
996
+ on_event ( data, KeyEvent :: Repeated , time_ms, keycode) ;
997
+ let mut guard = kbd. internal . lock ( ) . unwrap ( ) ;
998
+
999
+ match guard. key_repeat_timer {
1000
+ Some ( token) => data. clear_timeout ( token) ,
1001
+ None => debug ! ( "Key starts repeating but there is no delay timer. Was repeat already cancelled?" ) ,
1002
+ } ;
1003
+
1004
+ // This implementation doesn't take into account changes to the repeat rate after repeating begins.
1005
+ let handle = get_handle ( data) ;
1006
+ let on_event = on_event. clone ( ) ;
1007
+ let duration = Duration :: from_millis ( rate as _ ) ;
1008
+ guard. key_repeat_timer = Some ( handle. insert_source (
1009
+ calloop:: timer:: Timer :: from_duration ( duration) ,
1010
+ move |_, _, data| {
1011
+ time_ms += rate as u32 ;
1012
+ on_event ( data, KeyEvent :: Repeated , time_ms, keycode) ;
1013
+ calloop:: timer:: TimeoutAction :: ToDuration ( duration)
1014
+ } ,
1015
+ ) . unwrap ( ) ) ;
1016
+ calloop:: timer:: TimeoutAction :: Drop
1017
+ }
1018
+ ) . unwrap ( ) ) ;
1019
+ } ,
1020
+ KeyState :: Released => {
1021
+ // Nothing to do; timer is released for both in the common path.
1022
+ }
1023
+ }
1024
+ }
1025
+
1026
+ /// Cancels any ongoing key repeat
1027
+ pub fn key_stop_repeat ( & self ,
1028
+ data : & mut D ,
1029
+ get_handle : impl Fn ( & D ) -> & LoopHandle < ' static , D > ,
1030
+ ) {
1031
+ let mut guard = self . arc . internal . lock ( ) . unwrap ( ) ;
1032
+ if let Some ( token) = guard. key_repeat_timer . take ( ) {
1033
+ let handle = get_handle ( data) ;
1034
+ handle. remove ( token) ;
1035
+ } ;
1036
+ }
1037
+
934
1038
/// Handle a keystroke
935
1039
///
936
1040
/// All keystrokes from the input backend should be fed _in order_ to this method of the
@@ -949,7 +1053,7 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
949
1053
& self ,
950
1054
data : & mut D ,
951
1055
keycode : Keycode ,
952
- state : KeyState ,
1056
+ state : KeyEvent ,
953
1057
serial : Serial ,
954
1058
time : u32 ,
955
1059
filter : F ,
@@ -979,13 +1083,13 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
979
1083
& self ,
980
1084
data : & mut D ,
981
1085
keycode : Keycode ,
982
- state : KeyState ,
1086
+ state : KeyEvent ,
983
1087
filter : F ,
984
1088
) -> ( T , bool )
985
1089
where
986
1090
F : FnOnce ( & mut D , & ModifiersState , KeysymHandle < ' _ > ) -> T ,
987
1091
{
988
- trace ! ( "Handling keystroke " ) ;
1092
+ trace ! ( "Handling key event " ) ;
989
1093
990
1094
let mut guard = self . arc . internal . lock ( ) . unwrap ( ) ;
991
1095
let ( mods_changed, leds_changed) = guard. key_input ( keycode, state) ;
@@ -1014,26 +1118,20 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
1014
1118
& self ,
1015
1119
data : & mut D ,
1016
1120
keycode : Keycode ,
1017
- state : KeyState ,
1121
+ state : KeyEvent ,
1018
1122
serial : Serial ,
1019
- time : u32 ,
1123
+ time_ms : u32 ,
1020
1124
mods_changed : bool ,
1021
1125
) {
1022
1126
let mut guard = self . arc . internal . lock ( ) . unwrap ( ) ;
1023
- match state {
1024
- KeyState :: Pressed => {
1025
- guard. forwarded_pressed_keys . insert ( keycode) ;
1026
- }
1027
- KeyState :: Released => {
1028
- guard. forwarded_pressed_keys . remove ( & keycode) ;
1029
- }
1030
- } ;
1127
+
1128
+ let event = state. into ( ) ;
1031
1129
1032
1130
// forward to client if no keybinding is triggered
1033
1131
let seat = self . get_seat ( data) ;
1034
1132
let modifiers = mods_changed. then_some ( guard. mods_state ) ;
1035
1133
guard. with_grab ( data, & seat, |data, handle, grab| {
1036
- grab. input ( data, handle, keycode, state , modifiers, serial, time ) ;
1134
+ grab. input ( data, handle, keycode, event , modifiers, serial, time_ms ) ;
1037
1135
} ) ;
1038
1136
if guard. focus . is_some ( ) {
1039
1137
trace ! ( "Input forwarded to client" ) ;
@@ -1151,6 +1249,11 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
1151
1249
continue ;
1152
1250
} ;
1153
1251
if kbd. version ( ) >= 4 {
1252
+ let rate = if kbd. version ( ) >= 10 {
1253
+ 0 // Enables compositor-side key repeat. See wl_keyboard key event
1254
+ } else {
1255
+ rate
1256
+ } ;
1154
1257
kbd. repeat_info ( rate, delay) ;
1155
1258
}
1156
1259
}
@@ -1266,7 +1369,7 @@ impl<D: SeatHandler + 'static> KeyboardInnerHandle<'_, D> {
1266
1369
& mut self ,
1267
1370
data : & mut D ,
1268
1371
keycode : Keycode ,
1269
- key_state : KeyState ,
1372
+ key_state : KeyEvent ,
1270
1373
modifiers : Option < ModifiersState > ,
1271
1374
serial : Serial ,
1272
1375
time : u32 ,
@@ -1377,7 +1480,7 @@ impl<D: SeatHandler + 'static> KeyboardGrab<D> for DefaultGrab {
1377
1480
data : & mut D ,
1378
1481
handle : & mut KeyboardInnerHandle < ' _ , D > ,
1379
1482
keycode : Keycode ,
1380
- state : KeyState ,
1483
+ state : KeyEvent ,
1381
1484
modifiers : Option < ModifiersState > ,
1382
1485
serial : Serial ,
1383
1486
time : u32 ,
0 commit comments