Skip to content

Commit 689682b

Browse files
committed
Double-Tap
1 parent a1c1039 commit 689682b

6 files changed

Lines changed: 78 additions & 4 deletions

File tree

editor/src/messages/input_mapper/input_mapper_message.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ pub enum InputMapperMessage {
1616
KeyUpNoRepeat(Key),
1717
#[child]
1818
DoubleClick(MouseButton),
19+
#[child]
20+
DoubleTap(Key),
1921

2022
// Messages
2123
PointerMove,

editor/src/messages/input_mapper/input_mapper_message_handler.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl InputMapperMessageHandler {
4040
.chain(self.mapping.key_up_no_repeat.iter())
4141
.chain(self.mapping.key_down_no_repeat.iter())
4242
.chain(self.mapping.double_click.iter())
43+
.chain(self.mapping.double_tap.iter())
4344
.chain(std::iter::once(&self.mapping.wheel_scroll))
4445
.chain(std::iter::once(&self.mapping.pointer_move));
4546
let all_mapping_entries = all_key_mapping_entries.flat_map(|entry| entry.0.iter());
@@ -68,7 +69,7 @@ impl InputMapperMessageHandler {
6869
// Append the key button for the entry
6970
use InputMapperMessage as IMM;
7071
match entry.input {
71-
IMM::KeyDown(key) | IMM::KeyUp(key) | IMM::KeyDownNoRepeat(key) | IMM::KeyUpNoRepeat(key) => keys.push(key),
72+
IMM::KeyDown(key) | IMM::KeyUp(key) | IMM::KeyDownNoRepeat(key) | IMM::KeyUpNoRepeat(key) | IMM::DoubleTap(key) => keys.push(key),
7273
_ => (),
7374
}
7475

editor/src/messages/input_mapper/input_mappings.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ pub fn input_mappings(zoom_with_scroll: bool) -> Mapping {
337337
entry!(KeyDown(Tab); action_dispatch=ToolMessage::ToggleSelectVsPath),
338338
//
339339
// DocumentMessage
340-
entry!(KeyDown(Space); modifiers=[Control], action_dispatch=DocumentMessage::GraphViewOverlayToggle),
340+
entry!(DoubleTap(Space); action_dispatch=DocumentMessage::GraphViewOverlayToggle),
341341
entry!(KeyDownNoRepeat(Escape); action_dispatch=DocumentMessage::Escape),
342342
entry!(KeyDown(Delete); action_dispatch=DocumentMessage::DeleteSelectedLayers),
343343
entry!(KeyDown(Backspace); action_dispatch=DocumentMessage::DeleteSelectedLayers),
@@ -463,7 +463,7 @@ pub fn input_mappings(zoom_with_scroll: bool) -> Mapping {
463463
entry!(KeyDown(Space); modifiers=[Shift], action_dispatch=AnimationMessage::ToggleLivePreview),
464464
entry!(KeyDown(Home); modifiers=[Shift], action_dispatch=AnimationMessage::RestartAnimation),
465465
];
466-
let (mut key_up, mut key_down, mut key_up_no_repeat, mut key_down_no_repeat, mut double_click, mut wheel_scroll, mut pointer_move, mut pointer_shake) = mappings;
466+
let (mut key_up, mut key_down, mut key_up_no_repeat, mut key_down_no_repeat, mut double_click, mut double_tap, mut wheel_scroll, mut pointer_move, mut pointer_shake) = mappings;
467467

468468
let sort = |list: &mut KeyMappingEntries| list.0.sort_by(|a, b| b.modifiers.count_ones().cmp(&a.modifiers.count_ones()));
469469
// Sort the sublists of `key_up`, `key_down`, `key_up_no_repeat`, and `key_down_no_repeat`
@@ -476,6 +476,10 @@ pub fn input_mappings(zoom_with_scroll: bool) -> Mapping {
476476
for sublist in &mut double_click {
477477
sort(sublist)
478478
}
479+
// Sort the sublists of `double_tap`
480+
for sublist in &mut double_tap {
481+
sort(sublist)
482+
}
479483
// Sort `wheel_scroll`
480484
sort(&mut wheel_scroll);
481485
// Sort `pointer_move`
@@ -489,6 +493,7 @@ pub fn input_mappings(zoom_with_scroll: bool) -> Mapping {
489493
key_up_no_repeat,
490494
key_down_no_repeat,
491495
double_click,
496+
double_tap,
492497
wheel_scroll,
493498
pointer_move,
494499
pointer_shake,

editor/src/messages/input_mapper/utility_types/macros.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ macro_rules! mapping {
119119
let mut key_up_no_repeat = KeyMappingEntries::key_array();
120120
let mut key_down_no_repeat = KeyMappingEntries::key_array();
121121
let mut double_click = KeyMappingEntries::mouse_buttons_arrays();
122+
let mut double_tap = KeyMappingEntries::key_array();
122123
let mut wheel_scroll = KeyMappingEntries::new();
123124
let mut pointer_move = KeyMappingEntries::new();
124125
let mut pointer_shake = KeyMappingEntries::new();
@@ -138,6 +139,7 @@ macro_rules! mapping {
138139
InputMapperMessage::KeyDownNoRepeat(key) => &mut key_down_no_repeat[key as usize],
139140
InputMapperMessage::KeyUpNoRepeat(key) => &mut key_up_no_repeat[key as usize],
140141
InputMapperMessage::DoubleClick(key) => &mut double_click[key as usize],
142+
InputMapperMessage::DoubleTap(key) => &mut double_tap[key as usize],
141143
InputMapperMessage::WheelScroll => &mut wheel_scroll,
142144
InputMapperMessage::PointerMove => &mut pointer_move,
143145
InputMapperMessage::PointerShake => &mut pointer_shake,
@@ -148,7 +150,7 @@ macro_rules! mapping {
148150
}
149151
)*
150152

151-
(key_up, key_down, key_up_no_repeat, key_down_no_repeat, double_click, wheel_scroll, pointer_move, pointer_shake)
153+
(key_up, key_down, key_up_no_repeat, key_down_no_repeat, double_click, double_tap, wheel_scroll, pointer_move, pointer_shake)
152154
}};
153155
}
154156

editor/src/messages/input_mapper/utility_types/misc.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct Mapping {
1212
pub key_up_no_repeat: [KeyMappingEntries; NUMBER_OF_KEYS],
1313
pub key_down_no_repeat: [KeyMappingEntries; NUMBER_OF_KEYS],
1414
pub double_click: [KeyMappingEntries; NUMBER_OF_MOUSE_BUTTONS],
15+
pub double_tap: [KeyMappingEntries; NUMBER_OF_KEYS],
1516
pub wheel_scroll: KeyMappingEntries,
1617
pub pointer_move: KeyMappingEntries,
1718
pub pointer_shake: KeyMappingEntries,
@@ -36,6 +37,7 @@ impl Mapping {
3637
InputMapperMessage::KeyDownNoRepeat(key) => &self.key_down_no_repeat[*key as usize],
3738
InputMapperMessage::KeyUpNoRepeat(key) => &self.key_up_no_repeat[*key as usize],
3839
InputMapperMessage::DoubleClick(key) => &self.double_click[*key as usize],
40+
InputMapperMessage::DoubleTap(key) => &self.double_tap[*key as usize],
3941
InputMapperMessage::WheelScroll => &self.wheel_scroll,
4042
InputMapperMessage::PointerMove => &self.pointer_move,
4143
InputMapperMessage::PointerShake => &self.pointer_shake,

editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::application::Editor;
2+
use crate::consts::DOUBLE_CLICK_MILLISECONDS;
23
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeyStates, ModifierKeys};
34
use crate::messages::input_mapper::utility_types::input_mouse::{MouseButton, MouseKeys, MouseState};
45
use crate::messages::input_mapper::utility_types::misc::FrameTimeInfo;
@@ -16,6 +17,7 @@ pub struct InputPreprocessorMessageHandler {
1617
pub time: u64,
1718
pub keyboard: KeyStates,
1819
pub mouse: MouseState,
20+
pub last_key_down: Option<(Key, u64)>, // (Key, timestamp)
1921
}
2022

2123
#[message_handler_data]
@@ -44,7 +46,18 @@ impl<'a> MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageContex
4446
InputPreprocessorMessage::KeyDown { key, key_repeat, modifier_keys } => {
4547
self.update_states_of_modifier_keys(modifier_keys, responses);
4648
self.keyboard.set(key as usize);
49+
4750
if !key_repeat {
51+
if let Some((last_key, last_time)) = self.last_key_down {
52+
if last_key == key && self.time.saturating_sub(last_time) < DOUBLE_CLICK_MILLISECONDS {
53+
responses.add(InputMapperMessage::DoubleTap(key));
54+
self.last_key_down = None;
55+
} else {
56+
self.last_key_down = Some((key, self.time));
57+
}
58+
} else {
59+
self.last_key_down = Some((key, self.time));
60+
}
4861
responses.add(InputMapperMessage::KeyDownNoRepeat(key));
4962
}
5063
responses.add(InputMapperMessage::KeyDown(key));
@@ -185,6 +198,7 @@ impl InputPreprocessorMessageHandler {
185198

186199
#[cfg(test)]
187200
mod test {
201+
use crate::consts::DOUBLE_CLICK_MILLISECONDS;
188202
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys};
189203
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta};
190204
use crate::messages::prelude::*;
@@ -292,4 +306,52 @@ mod test {
292306
assert!(responses.contains(&InputMapperMessage::KeyDown(Key::Control).into()));
293307
assert!(responses.contains(&InputMapperMessage::KeyDown(Key::Control).into()));
294308
}
309+
310+
fn key_down(input_preprocessor: &mut InputPreprocessorMessageHandler, key: Key, responses: &mut VecDeque<Message>) {
311+
input_preprocessor.process_message(
312+
InputPreprocessorMessage::KeyDown {
313+
key,
314+
key_repeat: false,
315+
modifier_keys: ModifierKeys::empty(),
316+
},
317+
responses,
318+
InputPreprocessorMessageContext {
319+
viewport: &ViewportMessageHandler::default(),
320+
},
321+
);
322+
}
323+
324+
#[test]
325+
fn process_double_tap_within_threshold() {
326+
let mut input_preprocessor = InputPreprocessorMessageHandler::default();
327+
let mut responses = VecDeque::new();
328+
329+
// First tap at time 0
330+
key_down(&mut input_preprocessor, Key::Space, &mut responses);
331+
responses.clear();
332+
333+
// Second tap within threshold
334+
input_preprocessor.time = 50;
335+
key_down(&mut input_preprocessor, Key::Space, &mut responses);
336+
337+
assert!(responses.contains(&InputMapperMessage::DoubleTap(Key::Space).into()));
338+
assert!(input_preprocessor.last_key_down.is_none());
339+
}
340+
341+
#[test]
342+
fn process_double_tap_outside_threshold() {
343+
let mut input_preprocessor = InputPreprocessorMessageHandler::default();
344+
let mut responses = VecDeque::new();
345+
346+
// First tap at time 0
347+
key_down(&mut input_preprocessor, Key::Space, &mut responses);
348+
responses.clear();
349+
350+
// Second tap outside threshold
351+
input_preprocessor.time = DOUBLE_CLICK_MILLISECONDS + 1;
352+
key_down(&mut input_preprocessor, Key::Space, &mut responses);
353+
354+
assert!(!responses.contains(&InputMapperMessage::DoubleTap(Key::Space).into()));
355+
assert_eq!(input_preprocessor.last_key_down, Some((Key::Space, DOUBLE_CLICK_MILLISECONDS + 1)));
356+
}
295357
}

0 commit comments

Comments
 (0)