@@ -24,17 +24,33 @@ pub(super) fn raw_console_reader_loop(
2424 let mut handoff = WindowsInputHandoff :: default ( ) ;
2525
2626 while !should_quit. load ( Ordering :: Acquire ) {
27- match windows_console_input_items ( handle, & mut mapper) {
27+ let mut trace = windows_input_trace_enabled ( ) . then ( WindowsInputTraceBatch :: default) ;
28+ match windows_console_input_items ( handle, & mut mapper, trace. as_mut ( ) ) {
2829 WindowsInputItems :: Items ( items) => {
29- process_platform_input_items ( items, & mut pump, & mut handoff) ;
30+ process_platform_input_items ( items, & mut pump, & mut handoff, trace . as_mut ( ) ) ;
3031 }
3132 WindowsInputItems :: Idle => {
32- process_platform_input_items ( mapper. idle ( ) , & mut pump, & mut handoff) ;
33- handoff. push ( pump. idle ( ) ) ;
33+ process_platform_input_items (
34+ mapper. idle ( ) ,
35+ & mut pump,
36+ & mut handoff,
37+ trace. as_mut ( ) ,
38+ ) ;
39+ push_platform_input_events ( pump. idle ( ) , & mut handoff, trace. as_mut ( ) ) ;
3440 }
3541 WindowsInputItems :: Closed => return ,
3642 }
37- if !handoff. try_flush ( & event_tx) {
43+ let handoff_open = handoff. try_flush ( & event_tx) ;
44+ if let Some ( trace) = trace
45+ . filter ( |trace| !trace. raw_keys . is_empty ( ) || !trace. mapped_event_groups . is_empty ( ) )
46+ {
47+ tracing:: info!(
48+ raw_keys = ?trace. raw_keys,
49+ mapped_event_groups = ?trace. mapped_event_groups,
50+ "windows input trace: input batch"
51+ ) ;
52+ }
53+ if !handoff_open {
3854 return ;
3955 }
4056 }
@@ -45,10 +61,26 @@ fn process_platform_input_items(
4561 items : Vec < PlatformInputItem > ,
4662 pump : & mut WindowsInputPump ,
4763 handoff : & mut WindowsInputHandoff ,
64+ mut trace : Option < & mut WindowsInputTraceBatch > ,
4865) {
4966 for item in items {
50- handoff. push ( pump. process ( item) ) ;
67+ push_platform_input_events ( pump. process ( item) , handoff, trace. as_deref_mut ( ) ) ;
68+ }
69+ }
70+
71+ #[ cfg( windows) ]
72+ fn push_platform_input_events (
73+ events : Vec < crate :: protocol:: ClientInputEvent > ,
74+ handoff : & mut WindowsInputHandoff ,
75+ trace : Option < & mut WindowsInputTraceBatch > ,
76+ ) {
77+ if events. is_empty ( ) {
78+ return ;
5179 }
80+ if let Some ( trace) = trace {
81+ trace. mapped_event_groups . push ( events. clone ( ) ) ;
82+ }
83+ handoff. push ( events) ;
5284}
5385
5486#[ cfg( windows) ]
@@ -81,6 +113,13 @@ enum WindowsInputItems {
81113 Closed ,
82114}
83115
116+ #[ cfg( windows) ]
117+ #[ derive( Default ) ]
118+ struct WindowsInputTraceBatch {
119+ raw_keys : Vec < WindowsKeyRecord > ,
120+ mapped_event_groups : Vec < Vec < crate :: protocol:: ClientInputEvent > > ,
121+ }
122+
84123#[ cfg( windows) ]
85124#[ derive( Default ) ]
86125struct WindowsInputHandoff {
@@ -94,9 +133,6 @@ impl WindowsInputHandoff {
94133 if events. is_empty ( ) {
95134 return ;
96135 }
97- if windows_input_trace_enabled ( ) {
98- tracing:: info!( ?events, "windows input trace: client input events" ) ;
99- }
100136 if self . backpressured {
101137 self . push_backpressured ( events) ;
102138 } else {
@@ -185,6 +221,7 @@ fn windows_mouse_motion_can_replace(
185221fn windows_console_input_items (
186222 handle : windows_sys:: Win32 :: Foundation :: HANDLE ,
187223 mapper : & mut WindowsInputMapper ,
224+ mut trace : Option < & mut WindowsInputTraceBatch > ,
188225) -> WindowsInputItems {
189226 const WAIT_OBJECT_0 : u32 = 0 ;
190227 const WAIT_TIMEOUT : u32 = 258 ;
@@ -212,6 +249,9 @@ fn windows_console_input_items(
212249 let mut items = Vec :: new ( ) ;
213250 for record in records. iter ( ) . take ( read as usize ) {
214251 if let Some ( record) = windows_console_input_record_from_os ( * record) {
252+ if let ( Some ( trace) , WindowsInputRecord :: Key ( key) ) = ( trace. as_deref_mut ( ) , record) {
253+ trace. raw_keys . push ( key) ;
254+ }
215255 items. extend ( mapper. translate ( record) ) ;
216256 }
217257 }
@@ -662,18 +702,6 @@ impl WindowsInputMapper {
662702 }
663703
664704 fn translate_key ( & mut self , key : WindowsKeyRecord ) -> Vec < PlatformInputItem > {
665- if windows_input_trace_enabled ( ) {
666- tracing:: info!(
667- key_down = key. key_down,
668- repeat_count = key. repeat_count,
669- virtual_key_code = key. virtual_key_code,
670- virtual_scan_code = key. virtual_scan_code,
671- unicode = key. unicode,
672- control_key_state = key. control_key_state,
673- "windows input trace: console key record"
674- ) ;
675- }
676-
677705 if !self . key_record_can_emit_event ( key) {
678706 return Vec :: new ( ) ;
679707 }
@@ -1341,7 +1369,7 @@ fn resolve_ctrl_oem_char(key: WindowsKeyRecord) -> Option<char> {
13411369 None
13421370}
13431371
1344- #[ cfg( any ( windows, test ) ) ]
1372+ #[ cfg( windows) ]
13451373fn windows_input_trace_enabled ( ) -> bool {
13461374 std:: env:: var_os ( "HERDR_WINDOWS_INPUT_TRACE" ) . is_some ( )
13471375}
@@ -1558,6 +1586,28 @@ mod tests {
15581586 . collect ( )
15591587 }
15601588
1589+ #[ cfg( windows) ]
1590+ #[ test]
1591+ fn windows_input_trace_preserves_mapped_event_groups ( ) {
1592+ let groups = vec ! [
1593+ vec![ crate :: protocol:: ClientInputEvent :: FocusGained ] ,
1594+ vec![
1595+ crate :: protocol:: ClientInputEvent :: FocusLost ,
1596+ crate :: protocol:: ClientInputEvent :: FocusGained ,
1597+ ] ,
1598+ ] ;
1599+ let mut trace = WindowsInputTraceBatch :: default ( ) ;
1600+ let mut handoff = WindowsInputHandoff :: default ( ) ;
1601+
1602+ for events in & groups {
1603+ push_platform_input_events ( events. clone ( ) , & mut handoff, Some ( & mut trace) ) ;
1604+ }
1605+ push_platform_input_events ( Vec :: new ( ) , & mut handoff, Some ( & mut trace) ) ;
1606+
1607+ assert_eq ! ( trace. mapped_event_groups, groups) ;
1608+ assert_eq ! ( handoff. pending, VecDeque :: from( groups) ) ;
1609+ }
1610+
15611611 #[ cfg( windows) ]
15621612 #[ test]
15631613 fn windows_input_handoff_keeps_input_while_the_client_queue_is_full ( ) {
0 commit comments