Skip to content

Commit ae2c82d

Browse files
committed
Changes
1 parent a43a877 commit ae2c82d

1 file changed

Lines changed: 46 additions & 31 deletions

File tree

editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)