@@ -17,7 +17,9 @@ pub struct InputPreprocessorMessageHandler {
1717 pub time : u64 ,
1818 pub keyboard : KeyStates ,
1919 pub mouse : MouseState ,
20- pub last_key_down : Option < ( Key , u64 ) > , // (Key, timestamp)
20+ /// The most recent non-repeated key press and the timestamp of when it occurred, used as the first tap in double-tap detection.
21+ pub last_key_down : Option < ( Key , u64 ) > ,
22+ /// Set when a second tap of the same key occurs within the double-tap threshold. Cleared by any interrupting input (mouse button, scroll, or different key). The `DoubleTap` event is emitted on `KeyUp` if this is still set.
2123 pub double_tap_key : Option < ( Key , u64 ) > ,
2224}
2325
@@ -50,11 +52,12 @@ impl<'a> MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageContex
5052 self . keyboard . set ( key as usize ) ;
5153
5254 if !key_repeat {
53- let is_double_tap = self
55+ let no_mouse_buttons_held = self . mouse . mouse_keys . is_empty ( ) ;
56+ let same_key_within_threshold = self
5457 . last_key_down
5558 . is_some_and ( |( last_key, last_time) | last_key == key && self . time . saturating_sub ( last_time) < DOUBLE_CLICK_MILLISECONDS ) ;
5659
57- if is_double_tap {
60+ if no_mouse_buttons_held && same_key_within_threshold {
5861 self . double_tap_key = Some ( ( key, self . time ) ) ;
5962 self . last_key_down = None ;
6063 } else {
@@ -72,11 +75,10 @@ impl<'a> MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageContex
7275 if !key_repeat {
7376 responses. add ( InputMapperMessage :: KeyUpNoRepeat ( key) ) ;
7477 }
75- if let Some ( ( dt_key, dt_time) ) = self . double_tap_key {
76- if dt_key == key && self . time . saturating_sub ( dt_time) < DOUBLE_CLICK_MILLISECONDS {
78+ if let Some ( ( dt_key, dt_time) ) = self . double_tap_key . take ( ) {
79+ if dt_key == key && self . mouse . mouse_keys . is_empty ( ) && self . time . saturating_sub ( dt_time) < DOUBLE_CLICK_MILLISECONDS {
7780 responses. add ( InputMapperMessage :: DoubleTap ( key) ) ;
7881 }
79- self . double_tap_key = None ;
8082 }
8183 responses. add ( InputMapperMessage :: KeyUp ( key) ) ;
8284 }
@@ -90,7 +92,6 @@ impl<'a> MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageContex
9092 self . translate_mouse_event ( mouse_state, true , responses) ;
9193 }
9294 InputPreprocessorMessage :: PointerMove { editor_mouse_state, modifier_keys } => {
93- self . clear_double_tap_state ( ) ;
9495 self . update_states_of_modifier_keys ( modifier_keys, responses) ;
9596
9697 let mouse_state = editor_mouse_state. to_mouse_state ( viewport) ;
@@ -354,31 +355,35 @@ mod test {
354355 ) ;
355356 }
356357
358+ fn process_input ( input_preprocessor : & mut InputPreprocessorMessageHandler , message : InputPreprocessorMessage , responses : & mut VecDeque < Message > ) {
359+ input_preprocessor. process_message (
360+ message,
361+ responses,
362+ InputPreprocessorMessageContext {
363+ viewport : & ViewportMessageHandler :: default ( ) ,
364+ } ,
365+ ) ;
366+ }
367+
357368 #[ test]
358369 fn process_double_tap_within_threshold ( ) {
359370 let mut input_preprocessor = InputPreprocessorMessageHandler :: default ( ) ;
360371 let mut responses = VecDeque :: new ( ) ;
361372
362- // First tap at time 0
363373 key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
364374 key_up ( & mut input_preprocessor, Key :: Space , & mut responses) ;
365375 responses. clear ( ) ;
366376
367- // Second tap within threshold
368377 input_preprocessor. time = 50 ;
369378 key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
370379
371380 assert ! ( !responses. contains( & InputMapperMessage :: DoubleTap ( Key :: Space ) . into( ) ) ) ;
372- assert ! ( responses. contains( & InputMapperMessage :: KeyDown ( Key :: Space ) . into( ) ) ) ;
373- assert ! ( responses. contains( & InputMapperMessage :: KeyDownNoRepeat ( Key :: Space ) . into( ) ) ) ;
374- assert ! ( input_preprocessor. last_key_down. is_none( ) ) ;
375381 assert_eq ! ( input_preprocessor. double_tap_key, Some ( ( Key :: Space , 50 ) ) ) ;
376382
377383 responses. clear ( ) ;
378384 key_up ( & mut input_preprocessor, Key :: Space , & mut responses) ;
379385
380386 assert ! ( responses. contains( & InputMapperMessage :: DoubleTap ( Key :: Space ) . into( ) ) ) ;
381- assert ! ( input_preprocessor. last_key_down. is_none( ) ) ;
382387 assert ! ( input_preprocessor. double_tap_key. is_none( ) ) ;
383388 }
384389
@@ -387,19 +392,14 @@ mod test {
387392 let mut input_preprocessor = InputPreprocessorMessageHandler :: default ( ) ;
388393 let mut responses = VecDeque :: new ( ) ;
389394
390- // First tap at time 0
391395 key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
392396 key_up ( & mut input_preprocessor, Key :: Space , & mut responses) ;
393397 responses. clear ( ) ;
394398
395- // Second tap outside threshold
396399 input_preprocessor. time = DOUBLE_CLICK_MILLISECONDS + 1 ;
397400 key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
398401
399402 assert ! ( !responses. contains( & InputMapperMessage :: DoubleTap ( Key :: Space ) . into( ) ) ) ;
400- assert ! ( responses. contains( & InputMapperMessage :: KeyDown ( Key :: Space ) . into( ) ) ) ;
401- assert ! ( responses. contains( & InputMapperMessage :: KeyDownNoRepeat ( Key :: Space ) . into( ) ) ) ;
402- assert_eq ! ( input_preprocessor. last_key_down, Some ( ( Key :: Space , DOUBLE_CLICK_MILLISECONDS + 1 ) ) ) ;
403403 assert ! ( input_preprocessor. double_tap_key. is_none( ) ) ;
404404
405405 responses. clear ( ) ;
@@ -421,15 +421,14 @@ mod test {
421421 key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
422422 responses. clear ( ) ;
423423
424- // Release after the threshold
425424 input_preprocessor. time = 50 + DOUBLE_CLICK_MILLISECONDS + 1 ;
426425 key_up ( & mut input_preprocessor, Key :: Space , & mut responses) ;
427426
428427 assert ! ( !responses. contains( & InputMapperMessage :: DoubleTap ( Key :: Space ) . into( ) ) ) ;
429428 }
430429
431430 #[ test]
432- fn process_double_tap_interrupted_by_pointer ( ) {
431+ fn process_double_tap_interrupted_by_pointer_down ( ) {
433432 let mut input_preprocessor = InputPreprocessorMessageHandler :: default ( ) ;
434433 let mut responses = VecDeque :: new ( ) ;
435434
@@ -441,16 +440,13 @@ mod test {
441440 key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
442441 responses. clear ( ) ;
443442
444- // PointerDown happens!
445- input_preprocessor. process_message (
443+ process_input (
444+ & mut input_preprocessor,
446445 InputPreprocessorMessage :: PointerDown {
447446 editor_mouse_state : EditorMouseState :: default ( ) ,
448447 modifier_keys : ModifierKeys :: empty ( ) ,
449448 } ,
450449 & mut responses,
451- InputPreprocessorMessageContext {
452- viewport : & ViewportMessageHandler :: default ( ) ,
453- } ,
454450 ) ;
455451 responses. clear ( ) ;
456452
@@ -460,7 +456,7 @@ mod test {
460456 }
461457
462458 #[ test]
463- fn process_double_tap_interrupted_by_mouse_movement ( ) {
459+ fn process_double_tap_not_interrupted_by_mouse_movement ( ) {
464460 let mut input_preprocessor = InputPreprocessorMessageHandler :: default ( ) ;
465461 let mut responses = VecDeque :: new ( ) ;
466462
@@ -472,21 +468,40 @@ mod test {
472468 key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
473469 responses. clear ( ) ;
474470
475- // PointerMove happens!
476- input_preprocessor. process_message (
471+ process_input (
472+ & mut input_preprocessor,
477473 InputPreprocessorMessage :: PointerMove {
478474 editor_mouse_state : EditorMouseState :: default ( ) ,
479475 modifier_keys : ModifierKeys :: empty ( ) ,
480476 } ,
481477 & mut responses,
482- InputPreprocessorMessageContext {
483- viewport : & ViewportMessageHandler :: default ( ) ,
484- } ,
485478 ) ;
486479 responses. clear ( ) ;
487480
488481 key_up ( & mut input_preprocessor, Key :: Space , & mut responses) ;
489482
483+ assert ! ( responses. contains( & InputMapperMessage :: DoubleTap ( Key :: Space ) . into( ) ) ) ;
484+ }
485+
486+ #[ test]
487+ fn process_double_tap_blocked_by_mouse_button_held ( ) {
488+ let mut input_preprocessor = InputPreprocessorMessageHandler :: default ( ) ;
489+ let mut responses = VecDeque :: new ( ) ;
490+
491+ input_preprocessor. mouse . mouse_keys = MouseKeys :: LEFT ;
492+
493+ key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
494+ key_up ( & mut input_preprocessor, Key :: Space , & mut responses) ;
495+ responses. clear ( ) ;
496+
497+ input_preprocessor. time = 50 ;
498+ key_down ( & mut input_preprocessor, Key :: Space , & mut responses) ;
499+
500+ assert ! ( input_preprocessor. double_tap_key. is_none( ) ) ;
501+
502+ responses. clear ( ) ;
503+ key_up ( & mut input_preprocessor, Key :: Space , & mut responses) ;
504+
490505 assert ! ( !responses. contains( & InputMapperMessage :: DoubleTap ( Key :: Space ) . into( ) ) ) ;
491506 }
492507}
0 commit comments