From 6290bf123a26dac914d9e33a0c79819b76f06122 Mon Sep 17 00:00:00 2001 From: vangel76 Date: Sun, 11 Oct 2026 21:32:57 +0200 Subject: [PATCH] Keyboard: Shift+Space and Ctrl+Space select without starting an edit (#338) Co-Authored-By: Claude Sonnet 5.5 --- ROADMAP.md | 1 + crates/ui-egui/src/grid.rs | 8 +++-- crates/ui-egui/src/keymap.rs | 5 +++ crates/ui-egui/tests/keyboard_shortcuts.rs | 36 ++++++++++++++++++++++ docs/ui-parity.md | 1 + 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 03830fb..4e55ad3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -132,6 +132,7 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in | Date | What landed | |---|---| +| 2026-10-11 | Shift+Space and Ctrl+Space select the row / column without starting an edit; Control+Space on Mac (#338) | | 2026-10-11 | Legacy Excel 97-2003 `.xls` (BIFF8) import with formulas, number formats, merges, sizes and names (#121) | | 2026-10-11 | XLSX pass-through: custom XML, external links, connections, query tables, printer settings, form/ActiveX controls and OLE objects are kept on save (#330, #324) | | 2026-10-11 | Data › Forecast › Forecast Sheet: a new sheet with the history, FORECAST.ETS forecast, confidence bounds, statistics and a chart (#322) | diff --git a/crates/ui-egui/src/grid.rs b/crates/ui-egui/src/grid.rs index 820acf7..9965a5c 100644 --- a/crates/ui-egui/src/grid.rs +++ b/crates/ui-egui/src/grid.rs @@ -2192,6 +2192,11 @@ fn keyboard(app: &mut SheetApp, ctx: &egui::Context, resp: &egui::Response, geo: m.set_focus_lock_filter(resp.id, egui::EventFilter { tab: true, horizontal_arrows: true, vertical_arrows: true, escape: true }) }); let events = ctx.input(|i| i.events.clone()); + // A shortcut key that also types a character (Shift+Space sends Text(" ")) must not start an edit. + let shortcut_pressed = events.iter().any(|e| { + matches!(e, egui::Event::Key { pressed: true, modifiers: m, key, .. } + if !m.alt && (m.ctrl || m.command || (m.shift && *key == egui::Key::Space))) + }); let page = ((geo.cells.height() / geo.z) / sh.default_row_height).floor().max(1.0) as i64; for ev in events { match ev { @@ -2202,6 +2207,7 @@ fn keyboard(app: &mut SheetApp, ctx: &egui::Context, resp: &egui::Response, geo: app.copy_to_clipboard(ctx, "edit.cut"); } egui::Event::Paste(text) => app.paste_external(text), + egui::Event::Text(_) if shortcut_pressed => {} egui::Event::Text(text) if text.chars().all(|c| !c.is_control()) && !text.is_empty() => { app.begin_edit(Some(text), false); if let Some(ed) = app.editor.as_mut() { @@ -2270,8 +2276,6 @@ fn keyboard(app: &mut SheetApp, ctx: &egui::Context, resp: &egui::Response, geo: app.session.format_painter = None; } Key::Space if !cmd && !shift && is_checkbox(sh, app) => app.run_or_alert("cell.toggleCheckbox", json!({})), - Key::Space if cmd && !shift => app.run_or_alert("selection.column", json!({})), - Key::Space if shift && !cmd => app.run_or_alert("selection.row", json!({})), Key::F9 => app.run_or_alert("formulas.calculateNow", json!({})), Key::F4 if !cmd => {} _ if cmd => crate::ribbon::shortcut(app, key, m), diff --git a/crates/ui-egui/src/keymap.rs b/crates/ui-egui/src/keymap.rs index 54ab319..65dbcca 100644 --- a/crates/ui-egui/src/keymap.rs +++ b/crates/ui-egui/src/keymap.rs @@ -108,6 +108,11 @@ pub fn lookup(key: Key, physical: Option, m: Modifiers, mac: bool) -> Optio Period if cmd && s => run("home.increaseFontSize"), Comma if cmd && s => run("home.decreaseFontSize"), Space if cmd && s => run("edit.selectAll"), + // Shift+Space selects the row; Ctrl+Space (Windows) / Control+Space (Excel for Mac) the + // column. Cmd+Space stays free: it is the macOS Spotlight shortcut. + Space if plain && s => run("selection.row"), + Space if !mac && cmd && !s => run("selection.column"), + Space if mac && ctrl && !m.command && !s => run("selection.column"), Home if cmd && s => Shortcut::ExtendToStart, End if cmd && s => Shortcut::ExtendToEnd, Home if plain && s => Shortcut::ExtendToRowStart, diff --git a/crates/ui-egui/tests/keyboard_shortcuts.rs b/crates/ui-egui/tests/keyboard_shortcuts.rs index a06f918..8a2b195 100644 --- a/crates/ui-egui/tests/keyboard_shortcuts.rs +++ b/crates/ui-egui/tests/keyboard_shortcuts.rs @@ -106,3 +106,39 @@ fn windows_and_mac_variants() { assert_eq!(lookup(Key::A, Some(Key::A), Modifiers::NONE, false), None); assert_eq!(lookup(Key::F2, Some(Key::F2), Modifiers::NONE, false), None); } + +#[test] +fn space_selection_shortcuts_do_not_start_an_edit() { + let mut h = harness(book("B2")); + // Shift+Space: the key press, then the space the OS types with it. + let shift = Modifiers::SHIFT; + h.input_mut().events.push(Event::Key { key: Key::Space, physical_key: Some(Key::Space), pressed: true, repeat: false, modifiers: shift }); + h.input_mut().events.push(Event::Text(" ".into())); + h.run_steps(2); + assert!(h.state().editor.is_none(), "Shift+Space started an edit"); + assert_eq!(h.state().session.active().unwrap().selection.ranges[0].a1(), "2:2"); + h.state_mut().session.run("selection.set", json!({"range": "B2"})).unwrap(); + // Ctrl+Space selects the column, also without starting an edit. + h.input_mut().events.push(Event::Key { key: Key::Space, physical_key: Some(Key::Space), pressed: true, repeat: false, modifiers: CTRL }); + h.input_mut().events.push(Event::Text(" ".into())); + h.run_steps(2); + assert!(h.state().editor.is_none()); + assert_eq!(h.state().session.active().unwrap().selection.ranges[0].a1(), "B:B"); + // Plain typing still edits. + h.input_mut().events.push(Event::Text("x".into())); + h.run_steps(2); + assert!(h.state().editor.is_some()); +} + +#[test] +fn space_shortcuts_per_platform() { + let run = |id: &'static str| Some(Shortcut::Run(id, json!({}))); + let mac_cmd = Modifiers { mac_cmd: true, command: true, ..Modifiers::NONE }; + let space = |m, mac| lookup(Key::Space, Some(Key::Space), m, mac); + assert_eq!(space(Modifiers::SHIFT, false), run("selection.row")); + assert_eq!(space(Modifiers::SHIFT, true), run("selection.row")); + assert_eq!(space(CTRL, false), run("selection.column")); + assert_eq!(space(Modifiers::CTRL, true), run("selection.column")); + // Cmd+Space is Spotlight on macOS. + assert_eq!(space(mac_cmd, true), None); +} diff --git a/docs/ui-parity.md b/docs/ui-parity.md index fcea332..b6e3b91 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -150,6 +150,7 @@ scrollbar bugs 2–4 · pixel/feel pass against observed Excel 7–12. | Date | Change | Summary | |---|---|---| +| 2026-10-11 | minor | Shift+Space / Ctrl+Space no longer start an edit; Control+Space selects the column on Mac (#338) | | 2026-10-11 | minor | Selected whole columns can be reordered by dragging their headers to an insertion point | | 2026-10-11 | minor | Page Layout view with rulers and in-place headers and footers (#329) | | 2026-10-11 | minor | Forecast Sheet dialog (#322) |