Skip to content

Commit 354a689

Browse files
authored
Improve hotkeys with canonical flag, more industry-standard mappings, and fix GRS menu bar labels (#2827)
1 parent 8a0241f commit 354a689

File tree

15 files changed

+153
-152
lines changed

15 files changed

+153
-152
lines changed

editor/src/dispatcher.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,12 +319,11 @@ impl Dispatcher {
319319
}))
320320
}
321321

322-
/// Logs a message that is about to be executed,
323-
/// either as a tree with a discriminant or the entire payload (depending on settings)
322+
/// Logs a message that is about to be executed, either as a tree
323+
/// with a discriminant or the entire payload (depending on settings)
324324
fn log_message(&self, message: &Message, queues: &[VecDeque<Message>], message_logging_verbosity: MessageLoggingVerbosity) {
325325
let discriminant = MessageDiscriminant::from(message);
326-
let is_blocked = DEBUG_MESSAGE_BLOCK_LIST.iter().any(|&blocked_discriminant| discriminant == blocked_discriminant)
327-
|| DEBUG_MESSAGE_ENDING_BLOCK_LIST.iter().any(|blocked_name| discriminant.local_name().ends_with(blocked_name));
326+
let is_blocked = DEBUG_MESSAGE_BLOCK_LIST.contains(&discriminant) || DEBUG_MESSAGE_ENDING_BLOCK_LIST.iter().any(|blocked_name| discriminant.local_name().ends_with(blocked_name));
328327

329328
if !is_blocked {
330329
match message_logging_verbosity {

editor/src/messages/input_mapper/input_mapper_message_handler.rs

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::utility_types::input_keyboard::KeysGroup;
22
use super::utility_types::misc::Mapping;
33
use crate::messages::input_mapper::utility_types::input_keyboard::{self, Key};
4+
use crate::messages::input_mapper::utility_types::misc::MappingEntry;
45
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
56
use crate::messages::prelude::*;
67
use std::fmt::Write;
@@ -47,12 +48,12 @@ impl InputMapperMessageHandler {
4748
ma.map(|a| ((i as u8).try_into().unwrap(), a))
4849
})
4950
.for_each(|(k, a): (Key, _)| {
50-
let _ = write!(output, "{}: {}, ", k.to_discriminant().local_name(), a.local_name().split('.').last().unwrap());
51+
let _ = write!(output, "{}: {}, ", k.to_discriminant().local_name(), a.local_name().split('.').next_back().unwrap());
5152
});
5253
output.replace("Key", "")
5354
}
5455

55-
pub fn action_input_mapping(&self, action_to_find: &MessageDiscriminant) -> Vec<KeysGroup> {
56+
pub fn action_input_mapping(&self, action_to_find: &MessageDiscriminant) -> Option<KeysGroup> {
5657
let all_key_mapping_entries = std::iter::empty()
5758
.chain(self.mapping.key_up.iter())
5859
.chain(self.mapping.key_down.iter())
@@ -66,55 +67,65 @@ impl InputMapperMessageHandler {
6667
// Filter for the desired message
6768
let found_actions = all_mapping_entries.filter(|entry| entry.action.to_discriminant() == *action_to_find);
6869

70+
// Get the `Key` for this platform's accelerator key
6971
let keyboard_layout = || GLOBAL_PLATFORM.get().copied().unwrap_or_default().as_keyboard_platform_layout();
7072
let platform_accel_key = match keyboard_layout() {
7173
KeyboardPlatformLayout::Standard => Key::Control,
7274
KeyboardPlatformLayout::Mac => Key::Command,
7375
};
7476

77+
let entry_to_key = |entry: &MappingEntry| {
78+
// Get the modifier keys for the entry (and convert them to Key)
79+
let mut keys = entry
80+
.modifiers
81+
.iter()
82+
.map(|i| {
83+
// TODO: Use a safe solution eventually
84+
assert!(
85+
i < input_keyboard::NUMBER_OF_KEYS,
86+
"Attempting to convert a Key with enum index {i}, which is larger than the number of Key enums",
87+
);
88+
(i as u8).try_into().unwrap()
89+
})
90+
.collect::<Vec<_>>();
91+
92+
// Append the key button for the entry
93+
use InputMapperMessage as IMM;
94+
match entry.input {
95+
IMM::KeyDown(key) | IMM::KeyUp(key) | IMM::KeyDownNoRepeat(key) | IMM::KeyUpNoRepeat(key) => keys.push(key),
96+
_ => (),
97+
}
98+
99+
keys.sort_by(|&a, &b| {
100+
// Order according to platform guidelines mentioned at https://ux.stackexchange.com/questions/58185/normative-ordering-for-modifier-key-combinations
101+
const ORDER: [Key; 4] = [Key::Control, Key::Alt, Key::Shift, Key::Command];
102+
103+
// Treat the `Accel` virtual key as the platform's accel key for sorting comparison purposes
104+
let a = if a == Key::Accel { platform_accel_key } else { a };
105+
let b = if b == Key::Accel { platform_accel_key } else { b };
106+
107+
// Find where the keys are in the order, or put them at the end if they're not found
108+
let a = ORDER.iter().position(|&key| key == a).unwrap_or(ORDER.len());
109+
let b = ORDER.iter().position(|&key| key == b).unwrap_or(ORDER.len());
110+
111+
// Compare the positions of both keys
112+
a.cmp(&b)
113+
});
114+
115+
KeysGroup(keys)
116+
};
117+
118+
// If a canonical key combination is found, return it
119+
if let Some(canonical) = found_actions.clone().find(|entry| entry.canonical).map(entry_to_key) {
120+
return Some(canonical);
121+
}
122+
75123
// Find the key combinations for all keymaps matching the desired action
76124
assert!(std::mem::size_of::<usize>() >= std::mem::size_of::<Key>());
77-
found_actions
78-
.map(|entry| {
79-
// Get the modifier keys for the entry (and convert them to Key)
80-
let mut keys = entry
81-
.modifiers
82-
.iter()
83-
.map(|i| {
84-
// TODO: Use a safe solution eventually
85-
assert!(
86-
i < input_keyboard::NUMBER_OF_KEYS,
87-
"Attempting to convert a Key with enum index {i}, which is larger than the number of Key enums",
88-
);
89-
(i as u8).try_into().unwrap()
90-
})
91-
.collect::<Vec<_>>();
92-
93-
// Append the key button for the entry
94-
use InputMapperMessage as IMM;
95-
match entry.input {
96-
IMM::KeyDown(key) | IMM::KeyUp(key) | IMM::KeyDownNoRepeat(key) | IMM::KeyUpNoRepeat(key) => keys.push(key),
97-
_ => (),
98-
}
99-
100-
keys.sort_by(|&a, &b| {
101-
// Order according to platform guidelines mentioned at https://ux.stackexchange.com/questions/58185/normative-ordering-for-modifier-key-combinations
102-
const ORDER: [Key; 4] = [Key::Control, Key::Alt, Key::Shift, Key::Command];
103-
104-
// Treat the `Accel` virtual key as the platform's accel key for sorting comparison purposes
105-
let a = if a == Key::Accel { platform_accel_key } else { a };
106-
let b = if b == Key::Accel { platform_accel_key } else { b };
107-
108-
// Find where the keys are in the order, or put them at the end if they're not found
109-
let a = ORDER.iter().position(|&key| key == a).unwrap_or(ORDER.len());
110-
let b = ORDER.iter().position(|&key| key == b).unwrap_or(ORDER.len());
111-
112-
// Compare the positions of both keys
113-
a.cmp(&b)
114-
});
115-
116-
KeysGroup(keys)
117-
})
118-
.collect::<Vec<_>>()
125+
let mut key_sequences = found_actions.map(entry_to_key).collect::<Vec<_>>();
126+
127+
// Return the shortest key sequence, if any
128+
key_sequences.sort_by_key(|keys| keys.0.len());
129+
key_sequences.first().cloned()
119130
}
120131
}

editor/src/messages/input_mapper/input_mappings.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::messages::input_mapper::utility_types::misc::{KeyMappingEntries, Mapp
88
use crate::messages::portfolio::document::node_graph::utility_types::Direction;
99
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
1010
use crate::messages::portfolio::document::utility_types::misc::GroupFolderType;
11-
use crate::messages::portfolio::document::utility_types::transformation::TransformType;
1211
use crate::messages::prelude::*;
1312
use crate::messages::tool::tool_messages::brush_tool::BrushToolMessageOptionsUpdate;
1413
use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys;
@@ -221,7 +220,8 @@ pub fn input_mappings() -> Mapping {
221220
entry!(PointerMove; refresh_keys=[KeyC, Space, Control, Shift, Alt], action_dispatch=PathToolMessage::PointerMove { toggle_colinear: KeyC, equidistant: Alt, move_anchor_with_handles: Space, snap_angle: Shift, lock_angle: Control, delete_segment: Alt, break_colinear_molding: Alt }),
222221
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
223222
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=PathToolMessage::SelectAllAnchors),
224-
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=PathToolMessage::DeselectAllPoints),
223+
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], canonical, action_dispatch=PathToolMessage::DeselectAllPoints),
224+
entry!(KeyDown(KeyA); modifiers=[Alt], action_dispatch=PathToolMessage::DeselectAllPoints),
225225
entry!(KeyDown(Backspace); action_dispatch=PathToolMessage::Delete),
226226
entry!(KeyUp(MouseLeft); action_dispatch=PathToolMessage::DragStop { extend_selection: Shift, shrink_selection: Alt }),
227227
entry!(KeyDown(Enter); action_dispatch=PathToolMessage::Enter { extend_selection: Shift, shrink_selection: Alt }),
@@ -313,9 +313,10 @@ pub fn input_mappings() -> Mapping {
313313
entry!(KeyDown(KeyE); action_dispatch=ToolMessage::ActivateToolShapeEllipse),
314314
entry!(KeyDown(KeyY); action_dispatch=ToolMessage::ActivateToolShape),
315315
entry!(KeyDown(KeyB); action_dispatch=ToolMessage::ActivateToolBrush),
316-
entry!(KeyDown(KeyX); modifiers=[Accel, Shift], action_dispatch=ToolMessage::ResetColors),
316+
entry!(KeyDown(KeyD); action_dispatch=ToolMessage::ResetColors),
317317
entry!(KeyDown(KeyX); modifiers=[Shift], action_dispatch=ToolMessage::SwapColors),
318-
entry!(KeyDown(KeyC); modifiers=[Alt], action_dispatch=ToolMessage::SelectRandomPrimaryColor),
318+
entry!(KeyDown(KeyC); modifiers=[Alt], action_dispatch=ToolMessage::SelectRandomWorkingColor { primary: true }),
319+
entry!(KeyDown(KeyC); modifiers=[Alt, Shift], action_dispatch=ToolMessage::SelectRandomWorkingColor { primary: false }),
319320
//
320321
// DocumentMessage
321322
entry!(KeyDown(Space); modifiers=[Control], action_dispatch=DocumentMessage::GraphViewOverlayToggle),
@@ -327,20 +328,21 @@ pub fn input_mappings() -> Mapping {
327328
entry!(KeyDown(KeyH); modifiers=[Accel], action_dispatch=DocumentMessage::ToggleSelectedVisibility),
328329
entry!(KeyDown(KeyL); modifiers=[Accel], action_dispatch=DocumentMessage::ToggleSelectedLocked),
329330
entry!(KeyDown(KeyG); modifiers=[Alt], action_dispatch=DocumentMessage::ToggleGridVisibility),
330-
entry!(KeyDown(KeyZ); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::Redo),
331+
entry!(KeyDown(KeyZ); modifiers=[Accel, Shift], canonical, action_dispatch=DocumentMessage::Redo),
331332
entry!(KeyDown(KeyY); modifiers=[Accel], action_dispatch=DocumentMessage::Redo),
332333
entry!(KeyDown(KeyZ); modifiers=[Accel], action_dispatch=DocumentMessage::Undo),
333334
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=DocumentMessage::SelectAllLayers),
334-
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::DeselectAllLayers),
335+
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], canonical, action_dispatch=DocumentMessage::DeselectAllLayers),
336+
entry!(KeyDown(KeyA); modifiers=[Alt], action_dispatch=DocumentMessage::DeselectAllLayers),
335337
entry!(KeyDown(KeyS); modifiers=[Accel], action_dispatch=DocumentMessage::SaveDocument),
336-
entry!(KeyDown(KeyD); modifiers=[Accel], action_dispatch=DocumentMessage::DuplicateSelectedLayers),
338+
entry!(KeyDown(KeyD); modifiers=[Accel], canonical, action_dispatch=DocumentMessage::DuplicateSelectedLayers),
337339
entry!(KeyDown(KeyJ); modifiers=[Accel], action_dispatch=DocumentMessage::DuplicateSelectedLayers),
338340
entry!(KeyDown(KeyG); modifiers=[Accel], action_dispatch=DocumentMessage::GroupSelectedLayers { group_folder_type: GroupFolderType::Layer }),
339341
entry!(KeyDown(KeyG); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::UngroupSelectedLayers),
340342
entry!(KeyDown(KeyN); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::CreateEmptyFolder),
341-
entry!(KeyDown(Backslash); modifiers=[Alt], action_dispatch=DocumentMessage::SelectParentLayer),
342-
entry!(KeyDown(BracketLeft); modifiers=[Alt], action_dispatch=DocumentMessage::SelectionStepBack),
343-
entry!(KeyDown(BracketRight); modifiers=[Alt], action_dispatch=DocumentMessage::SelectionStepForward),
343+
entry!(KeyDown(Escape); modifiers=[Shift], action_dispatch=DocumentMessage::SelectParentLayer),
344+
entry!(KeyDown(BracketLeft); modifiers=[Alt], canonical, action_dispatch=DocumentMessage::SelectionStepBack),
345+
entry!(KeyDown(BracketRight); modifiers=[Alt], canonical, action_dispatch=DocumentMessage::SelectionStepForward),
344346
entry!(KeyDown(MouseBack); action_dispatch=DocumentMessage::SelectionStepBack),
345347
entry!(KeyDown(MouseForward); action_dispatch=DocumentMessage::SelectionStepForward),
346348
entry!(KeyDown(Digit0); modifiers=[Accel], action_dispatch=DocumentMessage::ZoomCanvasToFitAll),
@@ -376,9 +378,9 @@ pub fn input_mappings() -> Mapping {
376378
entry!(KeyDown(ArrowRight); action_dispatch=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: 0., resize: Alt, resize_opposite_corner: Control }),
377379
//
378380
// TransformLayerMessage
379-
entry!(KeyDown(KeyG); action_dispatch=TransformLayerMessage::BeginGRS { transform_type: TransformType::Grab }),
380-
entry!(KeyDown(KeyR); action_dispatch=TransformLayerMessage::BeginGRS { transform_type: TransformType::Rotate }),
381-
entry!(KeyDown(KeyS); action_dispatch=TransformLayerMessage::BeginGRS { transform_type: TransformType::Scale }),
381+
entry!(KeyDown(KeyG); action_dispatch=TransformLayerMessage::BeginGrab),
382+
entry!(KeyDown(KeyR); action_dispatch=TransformLayerMessage::BeginRotate),
383+
entry!(KeyDown(KeyS); action_dispatch=TransformLayerMessage::BeginScale),
382384
entry!(KeyDown(Digit0); action_dispatch=TransformLayerMessage::TypeDigit { digit: 0 }),
383385
entry!(KeyDown(Digit1); action_dispatch=TransformLayerMessage::TypeDigit { digit: 1 }),
384386
entry!(KeyDown(Digit2); action_dispatch=TransformLayerMessage::TypeDigit { digit: 2 }),

editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl MessageHandler<KeyMappingMessage, KeyMappingMessageData<'_>> for KeyMapping
2525
}
2626

2727
impl KeyMappingMessageHandler {
28-
pub fn action_input_mapping(&self, action_to_find: &MessageDiscriminant) -> Vec<KeysGroup> {
28+
pub fn action_input_mapping(&self, action_to_find: &MessageDiscriminant) -> Option<KeysGroup> {
2929
self.mapping_handler.action_input_mapping(action_to_find)
3030
}
3131
}

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

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,44 +24,54 @@ macro_rules! modifiers {
2424
/// Each handler adds or removes actions in the form of message discriminants. Here, we tie an input condition (such as a hotkey) to an action's full message.
2525
/// When an action is currently available, and the user enters that input, the action's message is dispatched on the message bus.
2626
macro_rules! entry {
27+
// Pattern with canonical parameter
28+
($input:expr_2021; $(modifiers=[$($modifier:ident),*],)? $(refresh_keys=[$($refresh:ident),* $(,)?],)? canonical, action_dispatch=$action_dispatch:expr_2021$(,)?) => {
29+
entry!($input; $($($modifier),*)?; $($($refresh),*)?; $action_dispatch; true)
30+
};
31+
32+
// Pattern without canonical parameter
2733
($input:expr_2021; $(modifiers=[$($modifier:ident),*],)? $(refresh_keys=[$($refresh:ident),* $(,)?],)? action_dispatch=$action_dispatch:expr_2021$(,)?) => {
34+
entry!($input; $($($modifier),*)?; $($($refresh),*)?; $action_dispatch; false)
35+
};
36+
37+
// Implementation macro to avoid code duplication
38+
($input:expr; $($modifier:ident),*; $($refresh:ident),*; $action_dispatch:expr; $canonical:expr) => {
2839
&[&[
2940
// Cause the `action_dispatch` message to be sent when the specified input occurs.
3041
MappingEntry {
3142
action: $action_dispatch.into(),
3243
input: $input,
33-
modifiers: modifiers!($($($modifier),*)?),
44+
modifiers: modifiers!($($modifier),*),
45+
canonical: $canonical,
3446
},
3547

3648
// Also cause the `action_dispatch` message to be sent when any of the specified refresh keys change.
37-
//
38-
// For example, a snapping state bound to the Shift key may change if the user presses or releases that key.
39-
// In that case, we want to dispatch the action's message even though the pointer didn't necessarily move so
40-
// the input handler can update the snapping state without making the user move the mouse to see the change.
41-
$(
4249
$(
4350
MappingEntry {
4451
action: $action_dispatch.into(),
4552
input: InputMapperMessage::KeyDown(Key::$refresh),
4653
modifiers: modifiers!(),
54+
canonical: $canonical,
4755
},
4856
MappingEntry {
4957
action: $action_dispatch.into(),
5058
input: InputMapperMessage::KeyUp(Key::$refresh),
5159
modifiers: modifiers!(),
60+
canonical: $canonical,
5261
},
5362
MappingEntry {
5463
action: $action_dispatch.into(),
5564
input: InputMapperMessage::KeyDownNoRepeat(Key::$refresh),
5665
modifiers: modifiers!(),
66+
canonical: $canonical,
5767
},
5868
MappingEntry {
5969
action: $action_dispatch.into(),
6070
input: InputMapperMessage::KeyUpNoRepeat(Key::$refresh),
6171
modifiers: modifiers!(),
72+
canonical: $canonical,
6273
},
6374
)*
64-
)*
6575
]]
6676
};
6777
}

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

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::input_keyboard::{Key, KeysGroup, LayoutKeysGroup, all_required_modifiers_pressed};
1+
use super::input_keyboard::{KeysGroup, LayoutKeysGroup, all_required_modifiers_pressed};
22
use crate::messages::input_mapper::key_mapping::MappingVariant;
33
use crate::messages::input_mapper::utility_types::input_keyboard::{KeyStates, NUMBER_OF_KEYS};
44
use crate::messages::input_mapper::utility_types::input_mouse::NUMBER_OF_MOUSE_BUTTONS;
@@ -120,6 +120,8 @@ pub struct MappingEntry {
120120
pub input: InputMapperMessage,
121121
/// Any additional keys that must be also pressed for this input mapping to match
122122
pub modifiers: KeyStates,
123+
/// True indicates that this takes priority as the labeled hotkey shown in UI menus and tooltips instead of an alternate binding for the same action
124+
pub canonical: bool,
123125
}
124126

125127
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
@@ -130,36 +132,12 @@ pub enum ActionKeys {
130132
}
131133

132134
impl ActionKeys {
133-
pub fn to_keys(&mut self, action_input_mapping: &impl Fn(&MessageDiscriminant) -> Vec<KeysGroup>) -> String {
135+
pub fn to_keys(&mut self, action_input_mapping: &impl Fn(&MessageDiscriminant) -> Option<KeysGroup>) -> String {
134136
match self {
135137
Self::Action(action) => {
136-
// Take the shortest sequence of keys
137-
let mut key_sequences = action_input_mapping(action);
138-
key_sequences.sort_by_key(|keys| keys.0.len());
139-
let mut secondary_key_sequence = key_sequences.get(1).cloned();
140-
let mut key_sequence = key_sequences.get_mut(0);
141-
142-
// TODO: Replace this exception with a per-action choice of canonical hotkey
143-
if let Some(key_sequence) = &mut key_sequence {
144-
if key_sequence.0.as_slice() == [Key::MouseBack] {
145-
if let Some(replacement) = &mut secondary_key_sequence {
146-
std::mem::swap(*key_sequence, replacement);
147-
}
148-
}
149-
}
150-
if let Some(key_sequence) = &mut key_sequence {
151-
if key_sequence.0.as_slice() == [Key::MouseForward] {
152-
if let Some(replacement) = &mut secondary_key_sequence {
153-
std::mem::swap(*key_sequence, replacement);
154-
}
155-
}
156-
}
157-
158-
if let Some(keys) = key_sequence {
159-
let mut taken_keys = KeysGroup::default();
160-
std::mem::swap(keys, &mut taken_keys);
161-
let description = taken_keys.to_string();
162-
*self = Self::Keys(taken_keys.into());
138+
if let Some(keys) = action_input_mapping(action) {
139+
let description = keys.to_string();
140+
*self = Self::Keys(keys.into());
163141
description
164142
} else {
165143
*self = Self::Keys(KeysGroup::default().into());

editor/src/messages/layout/layout_message_handler.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ impl LayoutMessageHandler {
342342
}
343343
}
344344

345-
impl<F: Fn(&MessageDiscriminant) -> Vec<KeysGroup>> MessageHandler<LayoutMessage, F> for LayoutMessageHandler {
345+
impl<F: Fn(&MessageDiscriminant) -> Option<KeysGroup>> MessageHandler<LayoutMessage, F> for LayoutMessageHandler {
346346
fn process_message(&mut self, message: LayoutMessage, responses: &mut std::collections::VecDeque<Message>, action_input_mapping: F) {
347347
match message {
348348
LayoutMessage::ResendActiveWidget { layout_target, widget_id } => {
@@ -385,7 +385,7 @@ impl LayoutMessageHandler {
385385
layout_target: LayoutTarget,
386386
new_layout: Layout,
387387
responses: &mut VecDeque<Message>,
388-
action_input_mapping: &impl Fn(&MessageDiscriminant) -> Vec<KeysGroup>,
388+
action_input_mapping: &impl Fn(&MessageDiscriminant) -> Option<KeysGroup>,
389389
) {
390390
match new_layout {
391391
Layout::WidgetLayout(_) => {
@@ -419,7 +419,7 @@ impl LayoutMessageHandler {
419419
}
420420

421421
/// Send a diff to the frontend based on the layout target.
422-
fn send_diff(&self, mut diff: Vec<WidgetDiff>, layout_target: LayoutTarget, responses: &mut VecDeque<Message>, action_input_mapping: &impl Fn(&MessageDiscriminant) -> Vec<KeysGroup>) {
422+
fn send_diff(&self, mut diff: Vec<WidgetDiff>, layout_target: LayoutTarget, responses: &mut VecDeque<Message>, action_input_mapping: &impl Fn(&MessageDiscriminant) -> Option<KeysGroup>) {
423423
diff.iter_mut().for_each(|diff| diff.new_value.apply_keyboard_shortcut(action_input_mapping));
424424

425425
let message = match layout_target {

0 commit comments

Comments
 (0)