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 ;
7
9
#[ cfg( feature = "wayland_frontend" ) ]
8
10
use std:: sync:: RwLock ;
11
+ use std:: time:: Duration ;
9
12
use std:: {
10
13
default:: Default ,
11
14
fmt, io,
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,19 @@ 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
+ /// Holds the token to cancel key repeat.
222
+ /// The token gets cleared when the keyboard is dropped, to neutralize the repeat callback.
223
+ pub ( crate ) key_repeat_timer : Arc < Mutex < Option < RegistrationToken > > > ,
224
+ }
225
+
226
+ #[ cfg( feature = "wayland_frontend" ) ]
227
+ impl < D : SeatHandler > Drop for KbdInternal < D > {
228
+ fn drop ( & mut self ) {
229
+ let timer = self . key_repeat_timer . lock ( ) . unwrap ( ) . take ( ) ;
230
+ if timer. is_some ( ) {
231
+ error ! ( "A keyboard was dropped without unregistering a repeat handler. This is a bug in smithay or in the compositor." ) ;
232
+ }
233
+ }
218
234
}
219
235
220
236
// focus_hook does not implement debug, so we have to impl Debug manually
@@ -229,6 +245,7 @@ impl<D: SeatHandler> fmt::Debug for KbdInternal<D> {
229
245
. field ( "xkb" , & self . xkb )
230
246
. field ( "repeat_rate" , & self . repeat_rate )
231
247
. field ( "repeat_delay" , & self . repeat_delay )
248
+ . field ( "key_repeat_timer" , & self . key_repeat_timer )
232
249
. finish ( )
233
250
}
234
251
}
@@ -266,21 +283,25 @@ impl<D: SeatHandler + 'static> KbdInternal<D> {
266
283
led_mapping,
267
284
led_state,
268
285
grab : GrabStatus :: None ,
286
+ key_repeat_timer : Arc :: new ( Mutex :: new ( None ) ) ,
269
287
} )
270
288
}
271
289
272
290
// returns whether the modifiers or led state has changed
273
- fn key_input ( & mut self , keycode : Keycode , state : KeyState ) -> ( bool , bool ) {
291
+ fn key_input ( & mut self , keycode : Keycode , state : KeyEvent ) -> ( bool , bool ) {
274
292
// track pressed keys as xkbcommon does not seem to expose it :(
275
293
let direction = match state {
276
- KeyState :: Pressed => {
294
+ KeyEvent :: Pressed => {
277
295
self . pressed_keys . insert ( keycode) ;
278
296
xkb:: KeyDirection :: Down
279
297
}
280
- KeyState :: Released => {
298
+ KeyEvent :: Released => {
281
299
self . pressed_keys . remove ( & keycode) ;
282
300
xkb:: KeyDirection :: Up
283
301
}
302
+ KeyEvent :: Repeated => {
303
+ return ( false , false ) ;
304
+ }
284
305
} ;
285
306
286
307
// update state
@@ -602,10 +623,10 @@ pub trait KeyboardGrab<D: SeatHandler>: Downcast {
602
623
data : & mut D ,
603
624
handle : & mut KeyboardInnerHandle < ' _ , D > ,
604
625
keycode : Keycode ,
605
- state : KeyState ,
626
+ event : KeyEvent ,
606
627
modifiers : Option < ModifiersState > ,
607
628
serial : Serial ,
608
- time : u32 ,
629
+ time_ms : u32 ,
609
630
) ;
610
631
611
632
/// A focus change was requested.
@@ -931,6 +952,106 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
931
952
}
932
953
}
933
954
955
+ /// Processes the keyboard event, starting or stopping key repeat.
956
+ /// If this method is used, it must receive all keyboard events.
957
+ /// The `on_event` argument will be called with all events: the ones received directly and the generated repeats.
958
+ pub fn key_register_repeat < B : InputBackend > (
959
+ & self ,
960
+ data : & mut D ,
961
+ get_handle : impl Fn ( & D ) -> & LoopHandle < ' static , D > + ' static ,
962
+ event : B :: KeyboardKeyEvent ,
963
+ // event, timeout, code.
964
+ // This is Clone because there are two closures in here...
965
+ on_event : impl Fn ( & mut D , KeyEvent , u32 , Keycode ) + Clone + ' static ,
966
+ ) {
967
+ let time_ms = event. time_msec ( ) ;
968
+ let keycode = event. key_code ( ) ;
969
+ let state = event. state ( ) ;
970
+
971
+ // Forward initial hardware event as logical event
972
+ on_event ( data, state. into ( ) , time_ms, keycode) ;
973
+
974
+ // Unregister preexisting repeating
975
+ // Releasing a key press obviously stops the repeat.
976
+ // But also, pressing another key stops the repeat of the previous key and starts it for the newly pressed key.
977
+ // TODO: this may had odd consequences when a modifier is pressed as the second key. But is that worth worrying about?
978
+ self . key_stop_repeat ( data, & get_handle) ;
979
+
980
+ // Register repeating
981
+ match event. state ( ) {
982
+ KeyState :: Pressed => {
983
+ let mut guard = self . arc . internal . lock ( ) . unwrap ( ) ;
984
+ let delay = guard. repeat_delay ;
985
+ let rate = guard. repeat_rate ;
986
+ let mut time_ms = time_ms;
987
+
988
+ // This closure-in-closure business is somewhat ugly.
989
+ // 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.
990
+ // 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.
991
+ let kbd = self . arc . clone ( ) ;
992
+ let duration = Duration :: from_millis ( delay as _ ) ;
993
+ let handle = get_handle ( data) ;
994
+ let token = handle. insert_source (
995
+ calloop:: timer:: Timer :: from_duration ( duration) ,
996
+ move |_, _, data| {
997
+ time_ms += delay as u32 ;
998
+ on_event ( data, KeyEvent :: Repeated , time_ms, keycode) ;
999
+ let mut guard = kbd. internal . lock ( ) . unwrap ( ) ;
1000
+
1001
+ let handle = get_handle ( data) ;
1002
+ {
1003
+ let timer = guard. key_repeat_timer . lock ( ) . unwrap ( ) ;
1004
+ match * timer {
1005
+ Some ( token) => handle. remove ( token) ,
1006
+ None => debug ! ( "Key starts repeating but there is no delay timer. Was repeat already cancelled?" ) ,
1007
+ } ;
1008
+ }
1009
+
1010
+ // This implementation doesn't take into account changes to the repeat rate after repeating begins.
1011
+ let kbd = kbd. clone ( ) ;
1012
+ let on_event = on_event. clone ( ) ;
1013
+ let duration = Duration :: from_millis ( rate as _ ) ;
1014
+ let token = handle. insert_source (
1015
+ calloop:: timer:: Timer :: from_duration ( duration) ,
1016
+ move |_, _, data| {
1017
+ time_ms += rate as u32 ;
1018
+ let guard = kbd. internal . lock ( ) . unwrap ( ) ;
1019
+ let timer = guard. key_repeat_timer . lock ( ) . unwrap ( ) ;
1020
+
1021
+ // If the timer has been orphaned by dropping the keyboard, don't actually send the event, don't register a repeat.
1022
+ if timer. is_some ( ) {
1023
+ drop ( timer) ;
1024
+ drop ( guard) ;
1025
+ on_event ( data, KeyEvent :: Repeated , time_ms, keycode) ;
1026
+ calloop:: timer:: TimeoutAction :: ToDuration ( duration)
1027
+ } else {
1028
+ debug ! ( "Cancelling an orphaned keyboard repeat." ) ;
1029
+ calloop:: timer:: TimeoutAction :: Drop
1030
+ }
1031
+ } ,
1032
+ ) . unwrap ( ) ;
1033
+ guard. key_repeat_timer = Arc :: new ( Mutex :: new ( Some ( token) ) ) ;
1034
+ calloop:: timer:: TimeoutAction :: Drop
1035
+ }
1036
+ ) . unwrap ( ) ;
1037
+ guard. key_repeat_timer = Arc :: new ( Mutex :: new ( Some ( token) ) ) ;
1038
+ }
1039
+ KeyState :: Released => {
1040
+ // Nothing to do; timer is released for both in the common path.
1041
+ }
1042
+ }
1043
+ }
1044
+
1045
+ /// Cancels any ongoing key repeat
1046
+ pub fn key_stop_repeat ( & self , data : & mut D , get_handle : impl Fn ( & D ) -> & LoopHandle < ' static , D > ) {
1047
+ let guard = self . arc . internal . lock ( ) . unwrap ( ) ;
1048
+ let mut timer = guard. key_repeat_timer . lock ( ) . unwrap ( ) ;
1049
+ if let Some ( token) = timer. take ( ) {
1050
+ let handle = get_handle ( data) ;
1051
+ handle. remove ( token) ;
1052
+ } ;
1053
+ }
1054
+
934
1055
/// Handle a keystroke
935
1056
///
936
1057
/// All keystrokes from the input backend should be fed _in order_ to this method of the
@@ -949,7 +1070,7 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
949
1070
& self ,
950
1071
data : & mut D ,
951
1072
keycode : Keycode ,
952
- state : KeyState ,
1073
+ state : KeyEvent ,
953
1074
serial : Serial ,
954
1075
time : u32 ,
955
1076
filter : F ,
@@ -979,13 +1100,13 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
979
1100
& self ,
980
1101
data : & mut D ,
981
1102
keycode : Keycode ,
982
- state : KeyState ,
1103
+ state : KeyEvent ,
983
1104
filter : F ,
984
1105
) -> ( T , bool )
985
1106
where
986
1107
F : FnOnce ( & mut D , & ModifiersState , KeysymHandle < ' _ > ) -> T ,
987
1108
{
988
- trace ! ( "Handling keystroke " ) ;
1109
+ trace ! ( "Handling key event " ) ;
989
1110
990
1111
let mut guard = self . arc . internal . lock ( ) . unwrap ( ) ;
991
1112
let ( mods_changed, leds_changed) = guard. key_input ( keycode, state) ;
@@ -1014,26 +1135,18 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
1014
1135
& self ,
1015
1136
data : & mut D ,
1016
1137
keycode : Keycode ,
1017
- state : KeyState ,
1138
+ event : KeyEvent ,
1018
1139
serial : Serial ,
1019
- time : u32 ,
1140
+ time_ms : u32 ,
1020
1141
mods_changed : bool ,
1021
1142
) {
1022
1143
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
- } ;
1031
1144
1032
1145
// forward to client if no keybinding is triggered
1033
1146
let seat = self . get_seat ( data) ;
1034
1147
let modifiers = mods_changed. then_some ( guard. mods_state ) ;
1035
1148
guard. with_grab ( data, & seat, |data, handle, grab| {
1036
- grab. input ( data, handle, keycode, state , modifiers, serial, time ) ;
1149
+ grab. input ( data, handle, keycode, event , modifiers, serial, time_ms ) ;
1037
1150
} ) ;
1038
1151
if guard. focus . is_some ( ) {
1039
1152
trace ! ( "Input forwarded to client" ) ;
@@ -1151,6 +1264,11 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
1151
1264
continue ;
1152
1265
} ;
1153
1266
if kbd. version ( ) >= 4 {
1267
+ let rate = if kbd. version ( ) >= 10 {
1268
+ 0 // Enables compositor-side key repeat. See wl_keyboard key event
1269
+ } else {
1270
+ rate
1271
+ } ;
1154
1272
kbd. repeat_info ( rate, delay) ;
1155
1273
}
1156
1274
}
@@ -1266,7 +1384,7 @@ impl<D: SeatHandler + 'static> KeyboardInnerHandle<'_, D> {
1266
1384
& mut self ,
1267
1385
data : & mut D ,
1268
1386
keycode : Keycode ,
1269
- key_state : KeyState ,
1387
+ key_state : KeyEvent ,
1270
1388
modifiers : Option < ModifiersState > ,
1271
1389
serial : Serial ,
1272
1390
time : u32 ,
@@ -1377,7 +1495,7 @@ impl<D: SeatHandler + 'static> KeyboardGrab<D> for DefaultGrab {
1377
1495
data : & mut D ,
1378
1496
handle : & mut KeyboardInnerHandle < ' _ , D > ,
1379
1497
keycode : Keycode ,
1380
- state : KeyState ,
1498
+ state : KeyEvent ,
1381
1499
modifiers : Option < ModifiersState > ,
1382
1500
serial : Serial ,
1383
1501
time : u32 ,
0 commit comments