mirror of
https://github.com/storytold/soundcraft.git
synced 2026-11-02 16:30:24 -06:00
Keep shortcuts working after Tab
With no widget focused, egui answers Tab by giving keyboard focus to the first widget in the window, and Shift+Tab to the last one. shortcuts::handle ignores every key while a widget has focus, so after Tab (to the next clip boundary) R/T zoom and every other shortcut did nothing until a click elsewhere or Escape. Space and Enter clicked the focused widget instead: on macOS that is the toolbar's Shuffle button, so Space switched the session to Shuffle; on Windows and Linux it opened the SoundCraft menu. While the shortcuts own the keyboard (nothing focused, no dialog open), handle() now cancels egui's focus move for the frame. Tab still moves between fields once one has focus, and inside dialogs.
This commit is contained in:
@@ -86,6 +86,8 @@ pub fn handle(app: &mut SoundApp, ctx: &egui::Context) {
|
||||
let _ = app.run(c.0, json!({}));
|
||||
}
|
||||
}
|
||||
// Tab moves the insertion point here, so egui must not also hand focus to the first widget: that would block every shortcut.
|
||||
ctx.memory_mut(|m| m.move_focus(egui::FocusDirection::None));
|
||||
}
|
||||
|
||||
fn command_for(key: Key, mods: Modifiers, mac: bool) -> Option<&'static str> {
|
||||
|
||||
@@ -25,6 +25,37 @@ fn ctrl_shift_arrows_nudge_the_selected_clip_gain() {
|
||||
}
|
||||
}
|
||||
|
||||
fn type_in_app(ctx: &egui::Context, app: &mut SoundApp, keys: &[(Key, Modifiers)]) {
|
||||
let events = keys
|
||||
.iter()
|
||||
.flat_map(|&(key, modifiers)| [true, false].map(|pressed| egui::Event::Key { key, physical_key: None, pressed, repeat: false, modifiers }))
|
||||
.collect();
|
||||
ctx.run_ui(egui::RawInput { events, ..Default::default() }, |ui| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
})
|
||||
.textures_delta
|
||||
.clear();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tab_leaves_the_keys_to_the_shortcuts() {
|
||||
let mut app = SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default());
|
||||
let ctx = egui::Context::default();
|
||||
for _ in 0..3 {
|
||||
type_in_app(&ctx, &mut app, &[]);
|
||||
}
|
||||
for tab in [Modifiers::NONE, Modifiers::SHIFT] {
|
||||
type_in_app(&ctx, &mut app, &[(Key::Tab, tab)]);
|
||||
assert_eq!(ctx.memory(|m| m.focused()), None, "{tab:?}");
|
||||
let zoom = app.engine.session().edit.zoom.samples_per_px;
|
||||
type_in_app(&ctx, &mut app, &[(Key::T, Modifiers::NONE)]);
|
||||
assert_eq!(app.engine.session().edit.zoom.samples_per_px, zoom / 2.0, "{tab:?}");
|
||||
type_in_app(&ctx, &mut app, &[(Key::R, Modifiers::NONE)]);
|
||||
assert_eq!(app.engine.session().edit.zoom.samples_per_px, zoom, "{tab:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmd_equals_toggles_mix_and_edit_without_zooming() {
|
||||
let mac_cmd = Modifiers { mac_cmd: true, command: true, ..Modifiers::NONE };
|
||||
|
||||
Reference in New Issue
Block a user