@@ -280,6 +280,69 @@ pub async fn send_windows_key(client: &crate::jetkvm_rpc_client::JetKvmRpcClient
280280    Ok ( ( ) ) 
281281} 
282282
283+ /// Represents a key combination for a remote KVM device. 
284+ ///  
285+ /// This struct defines the information required to simulate a key press event: 
286+ /// - `modifier`: A bitmask representing modifier keys (e.g., Ctrl, Alt). 
287+ /// - `keys`: A list of key codes to be pressed. 
288+ /// - `hold`: The duration (in milliseconds) to hold the key press (defaults to 100 ms). 
289+ /// - `wait`: The delay (in milliseconds) after releasing the keys before proceeding to the next combination (defaults to 10 ms). 
290+ #[ derive( Debug ) ]  
291+ struct  KeyCombo  { 
292+     modifier :  u64 , 
293+     keys :  Vec < u8 > , 
294+     hold :  u64 ,  // how long to hold the key press (in ms), defaults to 100 ms 
295+     wait :  u64 ,  // delay after releasing keys before next combo (in ms), defaults to 10 ms 
296+ } 
297+ 
298+ /// Sends a series of key combinations to the remote KVM device via RPC. 
299+ /// 
300+ /// This asynchronous function processes each key combination in the provided list by: 
301+ /// 1. Sending a `keyboardReport` RPC that presses the specified keys along with any modifier keys. 
302+ /// 2. Waiting for the duration specified in `combo.hold` to simulate holding the keys down. 
303+ /// 3. Sending another `keyboardReport` RPC to release all keys. 
304+ /// 4. Waiting for the duration specified in `combo.wait` before moving to the next combination. 
305+ /// 
306+ /// # Parameters 
307+ /// - `client`: A reference to the `JetKvmRpcClient` that is used to send RPC commands. 
308+ /// - `combos`: A vector of `KeyCombo` structs, where each struct contains: 
309+ ///   - `modifier`: The modifier key(s) (like Ctrl, Alt, etc.) to apply. 
310+ ///   - `keys`: The list of keys to be pressed. 
311+ ///   - `hold`: The duration (in milliseconds) to hold the keys down. 
312+ ///   - `wait`: The duration (in milliseconds) to wait after releasing the keys. 
313+ /// 
314+ /// # Returns 
315+ /// Returns `Ok(())` if all key combinations are successfully processed, or an error if any RPC call fails. 
316+ async  fn  send_key_combinations ( client :  & JetKvmRpcClient ,  combos :  Vec < KeyCombo > )  -> AnyResult < ( ) >  { 
317+     for  combo in  combos { 
318+         // Press the keys with the specified modifier. 
319+         client
320+             . send_rpc ( 
321+                 "keyboardReport" , 
322+                 json ! ( { 
323+                     "modifier" :  combo. modifier, 
324+                     "keys" :  combo. keys, 
325+                 } ) , 
326+             ) 
327+             . await ?; 
328+         // Hold the key for the specified duration. 
329+         sleep ( Duration :: from_millis ( combo. hold ) ) . await ; 
330+         // Release all keys. 
331+         client
332+             . send_rpc ( 
333+                 "keyboardReport" , 
334+                 json ! ( { 
335+                     "modifier" :  0 , 
336+                     "keys" :  [ ] , 
337+                 } ) , 
338+             ) 
339+             . await ?; 
340+         // Wait after releasing keys before proceeding. 
341+         sleep ( Duration :: from_millis ( combo. wait ) ) . await ; 
342+     } 
343+     Ok ( ( ) ) 
344+ } 
345+ 
283346/// Registers keyboard functions to the provided Lua context. 
284347#[ cfg( feature = "lua" ) ]  
285348use  mlua:: prelude:: * ; 
@@ -376,5 +439,37 @@ pub fn register_lua(lua: &Lua, client: Arc<Mutex<JetKvmRpcClient>>) -> LuaResult
376439    } ; 
377440    lua. globals ( ) . set ( "send_text" ,  send_text_fn) ?; 
378441
442+     let  send_key_combinations_fn = { 
443+         let  value = client. clone ( ) ; 
444+         // The async function returns a Result; we unwrap it here. 
445+         lua. create_async_function ( move  |_,  combos :  mlua:: Table | { 
446+             let  client = value. clone ( ) ; 
447+             async  move  { 
448+                 let  mut  key_combos = Vec :: new ( ) ; 
449+                 // Expecting combos to be an array of tables. 
450+                 for  pair in  combos. sequence_values :: < mlua:: Table > ( )  { 
451+                     let  combo_table = pair?; 
452+                     let  modifier:  u64  = combo_table. get ( "modifier" ) ?; 
453+                     let  keys:  Vec < u8 >  = combo_table. get ( "keys" ) ?; 
454+                     // Optional fields: default to hold = 100 ms and wait = 10 ms. 
455+                     let  hold:  u64  = combo_table. get ( "hold" ) . unwrap_or ( 100 ) ; 
456+                     let  wait:  u64  = combo_table. get ( "wait" ) . unwrap_or ( 10 ) ; 
457+                     key_combos. push ( KeyCombo  { 
458+                         modifier, 
459+                         keys, 
460+                         hold, 
461+                         wait, 
462+                     } ) ; 
463+                 } 
464+                 send_key_combinations ( & * client. lock ( ) . await ,  key_combos) 
465+                     . await 
466+                     . map_err ( mlua:: Error :: external) 
467+             } 
468+         } ) 
469+     } ?; 
470+ 
471+     lua. globals ( ) 
472+         . set ( "send_key_combinations" ,  send_key_combinations_fn) ?; 
473+ 
379474    Ok ( ( ) ) 
380475} 
0 commit comments