@@ -23,6 +23,7 @@ use tokio::select;
2323use tokio:: time:: Duration ;
2424use tokio:: time:: { sleep, Instant } ;
2525use tokio_stream:: { StreamExt , StreamMap } ;
26+ use tokio_udev:: { AsyncMonitorSocket , EventType , MonitorBuilder } ;
2627
2728mod config;
2829mod perms;
@@ -142,23 +143,16 @@ async fn main() -> Result<(), Box<dyn Error>> {
142143 } ;
143144 }
144145
145- let keyboard_devices: Vec < Device > = {
146- if let Some ( arg_devices) = args. values_of ( "device" ) {
147- // for device in arg_devices {
148- // let device_path = Path::new(device);
149- // if let Ok(device_to_use) = Device::open(device_path) {
150- // log::info!("Using device: {}", device_to_use.name().unwrap_or(device));
151- // keyboard_devices.push(device_to_use);
152- // }
153- // }
154- let arg_devices = arg_devices. collect :: < Vec < & str > > ( ) ;
146+ let arg_devices: Vec < & str > = args. values_of ( "device" ) . unwrap_or_default ( ) . collect ( ) ;
147+
148+ let keyboard_devices: Vec < _ > = {
149+ if arg_devices. is_empty ( ) {
150+ log:: trace!( "Attempting to find all keyboard file descriptors." ) ;
151+ evdev:: enumerate ( ) . filter ( |( _, dev) | check_device_is_keyboard ( dev) ) . collect ( )
152+ } else {
155153 evdev:: enumerate ( )
156- . map ( |( _, device) | device)
157- . filter ( |device| arg_devices. contains ( & device. name ( ) . unwrap_or ( "" ) ) )
154+ . filter ( |( _, dev) | arg_devices. contains ( & dev. name ( ) . unwrap_or ( "" ) ) )
158155 . collect ( )
159- } else {
160- log:: trace!( "Attempting to find all keyboard file descriptors." ) ;
161- evdev:: enumerate ( ) . map ( |( _, device) | device) . filter ( check_device_is_keyboard) . collect ( )
162156 }
163157 } ;
164158
@@ -189,6 +183,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
189183 }
190184 } ;
191185
186+ let mut udev =
187+ AsyncMonitorSocket :: new ( MonitorBuilder :: new ( ) ?. match_subsystem ( "input" ) ?. listen ( ) ?) ?;
188+
192189 let modifiers_map: HashMap < Key , config:: Modifier > = HashMap :: from ( [
193190 ( Key :: KEY_LEFTMETA , config:: Modifier :: Super ) ,
194191 ( Key :: KEY_RIGHTMETA , config:: Modifier :: Super ) ,
@@ -206,21 +203,27 @@ async fn main() -> Result<(), Box<dyn Error>> {
206203 250
207204 } ;
208205
209- let mut signals = Signals :: new ( & [
206+ let mut signals = Signals :: new ( [
210207 SIGUSR1 , SIGUSR2 , SIGHUP , SIGABRT , SIGBUS , SIGCHLD , SIGCONT , SIGINT , SIGPIPE , SIGQUIT ,
211208 SIGSYS , SIGTERM , SIGTRAP , SIGTSTP , SIGVTALRM , SIGXCPU , SIGXFSZ ,
212209 ] ) ?;
213210
214211 let mut execution_is_paused = false ;
215212 let mut last_hotkey: Option < config:: Hotkey > = None ;
216213 let mut pending_release: bool = false ;
217- let mut keyboard_states: Vec < KeyboardState > = Vec :: new ( ) ;
214+ let mut keyboard_states = HashMap :: new ( ) ;
218215 let mut keyboard_stream_map = StreamMap :: new ( ) ;
219216
220- for ( i , mut device) in keyboard_devices. into_iter ( ) . enumerate ( ) {
217+ for ( path , mut device) in keyboard_devices. into_iter ( ) {
221218 let _ = device. grab ( ) ;
222- keyboard_stream_map. insert ( i, device. into_event_stream ( ) ?) ;
223- keyboard_states. push ( KeyboardState :: new ( ) ) ;
219+ let path = match path. to_str ( ) {
220+ Some ( p) => p,
221+ None => {
222+ continue ;
223+ }
224+ } ;
225+ keyboard_states. insert ( path. to_string ( ) , KeyboardState :: new ( ) ) ;
226+ keyboard_stream_map. insert ( path. to_string ( ) , device. into_event_stream ( ) ?) ;
224227 }
225228
226229 // The initial sleep duration is never read because last_hotkey is initialized to None
@@ -281,8 +284,54 @@ async fn main() -> Result<(), Box<dyn Error>> {
281284 }
282285 }
283286
284- Some ( ( i, Ok ( event) ) ) = keyboard_stream_map. next( ) => {
285- let keyboard_state = & mut keyboard_states[ i] ;
287+ Some ( Ok ( event) ) = udev. next( ) => {
288+ if !event. is_initialized( ) {
289+ log:: warn!( "Received udev event with uninitialized device." ) ;
290+ }
291+
292+ let node = match event. devnode( ) {
293+ None => { continue ; } ,
294+ Some ( node) => {
295+ match node. to_str( ) {
296+ None => { continue ; } ,
297+ Some ( node) => node,
298+ }
299+ } ,
300+ } ;
301+
302+ match event. event_type( ) {
303+ EventType :: Add => {
304+ let mut device = match Device :: open( node) {
305+ Err ( e) => {
306+ log:: error!( "Could not open evdev device at {}: {}" , node, e) ;
307+ continue ;
308+ } ,
309+ Ok ( device) => device
310+ } ;
311+ let name = device. name( ) . unwrap_or( "[unknown]" ) ;
312+ if arg_devices. contains( & name) || check_device_is_keyboard( & device) {
313+ log:: info!( "Device '{}' at '{}' added." , name, node) ;
314+ let _ = device. grab( ) ;
315+ keyboard_states. insert( node. to_string( ) , KeyboardState :: new( ) ) ;
316+ keyboard_stream_map. insert( node. to_string( ) , device. into_event_stream( ) ?) ;
317+ }
318+ }
319+ EventType :: Remove => {
320+ if keyboard_stream_map. contains_key( node) {
321+ keyboard_states. remove( node) ;
322+ let stream = keyboard_stream_map. remove( node) . expect( "device not in stream_map" ) ;
323+ let name = stream. device( ) . name( ) . unwrap_or( "[unknown]" ) ;
324+ log:: info!( "Device '{}' at '{}' removed" , name, node) ;
325+ }
326+ }
327+ _ => {
328+ log:: trace!( "Ignored udev event of type: {:?}" , event. event_type( ) ) ;
329+ }
330+ }
331+ }
332+
333+ Some ( ( node, Ok ( event) ) ) = keyboard_stream_map. next( ) => {
334+ let keyboard_state = & mut keyboard_states. get_mut( & node) . expect( "device not in states map" ) ;
286335
287336 let key = match event. kind( ) {
288337 InputEventKind :: Key ( keycode) => keycode,
0 commit comments