Skip to content

Ctrl+Z/Y/S work from every dock panel, not only the focused 3D view - #850

Merged
haraldsteinlechner merged 4 commits into
developfrom
bugs/ctrl-shortcuts-focus
Oct 20, 2026
Merged

haraldsteinlechner merged 4 commits into
developfrom
bugs/ctrl-shortcuts-focus

Conversation

@haraldsteinlechner

@haraldsteinlechner haraldsteinlechner commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Ctrl+Z / Ctrl+Y / Ctrl+S were only handled by the main render control's onkeydown. Every dock panel (annotation properties, annotation tree, surfaces, config, …) is its own page (?page=…) with no key listener, so the shortcuts did nothing while the cursor was over a panel.

The shortcut also checked the model's ctrlFlag, which only key events reaching the render control maintain:

  • Ctrl pressed outside the 3D view, then Z inside it → nothing.
  • Ctrl pressed in the 3D view and released after the cursor left → ctrlFlag stuck; the next plain Z/S acted as Ctrl+Z/S and picking stayed armed.

Change

  • pro3dCtrlShortcut(event) (resources/utilities.js) decides client-side: Ctrl/Cmd, no Alt, not repeated, key Z/Y/S, target not a text-entry field (whitelist: contenteditable, textarea, text-like input types), preventDefault. Modifiers come from the event, not ctrlFlag.
  • Events.onCtrlShortcut (Utilities.fs): the page-body onkeydown that asks it and sends the key code. Bubbling delivers the key to the body; the target check is needed because a text field's own undo is the browser's default action, not a listener that could stop the event.
  • Attached to every page body in Gui.Pages.pageRouting (dock panels, render, instrument, map projection, image inspector, top-level page).
  • New ViewerAction.CtrlShortcut handles undo / redo / save. Z/Y/S removed from the KeyDown case — the render control's keydown bubbles to its page body, so keeping both would undo twice.
  • Text/number fields keep native Ctrl+Z/Y for their own text; Ctrl+S there does nothing (default prevented, no browser "save page").
  • Both render controls release ctrlFlag/shiftFlag on blur. Ctrl+S no longer resets ctrlFlag (Ctrl may still be held).
  • Docs: docs/KeyboardShortcuts.md.

Behaviour notes

  • Alt+Z no longer undoes (Keyboard.Modifier counted LeftAlt as Ctrl).
  • Other keys (F1–F4, Enter/Backspace/Escape, Delete from Delete with del key #848, …) still need the 3D view focused — unchanged.

Testing

  • Section 18 — Keyboard Shortcuts: 11/11 pass, five new: CtrlShortcut Z/Y undo/redo with ctrlFlag unset; KeyDown LeftCtrl+Z no longer touches the undo stack; Ctrl+S keeps a held Ctrl armed; KeyUp clears Ctrl+Shift; onCtrlShortcut calls pro3dCtrlShortcut(event) and decodes the key code (totally).
  • Agent review: nothing serious; low findings addressed in the second commit. Not addressed (by design / out of scope): Ctrl+Shift+Z still undoes rather than redoes; a focused element whose own keydown handler calls stopPropagation (e.g. a Semantic dropdown) swallows the shortcut; macOS Electron Edit-menu accelerators not checked.
  • Playwright tests-ui/tests/keyboard-undo.spec.ts (passes, ~1.2 min, Dimorphos), focus asserted before every press: two Sky lines; Ctrl+Z / Ctrl+Y in the properties panel undo and redo one; Ctrl+Z in the toolbar's number field undoes nothing, outside it on the top-level page Ctrl+Z / Ctrl+Y undo and redo; with the render control focused by hovering, Ctrl+Z undoes exactly one (no double undo through bubbling).
  • Final agent review: ready to merge; its low findings (focus assertion in the spec, docs say focused panel rather than cursor, Shift ignored, prefixed JS global) addressed in the last commit.
  • Manual (optional, in Aardium): Ctrl+Z in annotation properties (outside a text field), inside a text field (text undo only), over the 3D view (single undo); Ctrl+S from a panel.

🤖 Generated with Claude Code

…sed 3D view

Each page body now carries a client-filtered onkeydown (Ctrl/Cmd, no Alt, not
repeated, not in an editable field) that sends CtrlShortcut; modifiers come
from the event instead of the tracked ctrlFlag. The render controls clear
ctrlFlag/shiftFlag on blur so a modifier released elsewhere cannot stay stuck.
- Ctrl+S in a text field: preventDefault (no browser 'save page'), still no scene save
- Ctrl+S no longer clears ctrlFlag; Ctrl may still be held, blur releases it otherwise
- key code decoded with Int32.TryParse (total)
- docs: Alt+Z no longer undoes
- tests: Ctrl+S keeps Ctrl armed, KeyUp clears both flags, client filter and key decoding
…itelist; UI spec

- pro3dCtrlShortcut(event) in resources/utilities.js decides what is sent; the F#
  attribute only asks it. Text entry is a whitelist (contenteditable, textarea, text-like
  input types) instead of a blacklist of non-text inputs; a focused <select> no longer
  blocks the shortcut.
- tests-ui keyboard-undo spec: Ctrl+Z/Y over the properties panel undo/redo, Ctrl+Z in a
  number field undoes nothing, Ctrl+Z over the 3D view undoes exactly once.
…top-level page

- step 4 blurs the render control and re-enters it, so the no-double-undo check runs with
  onmouseenter focus, asserted, instead of focus left over from a pick
- Ctrl+Z/Y on the top-level page outside the number field
- field focus by DOM instead of locator click (ai/TESTING.md)
- docs: keys go to the focused panel, not where the cursor is; Shift is not looked at
- pro3dIsTextEntry: prefixed global
@haraldsteinlechner
haraldsteinlechner merged commit e931196 into develop Oct 20, 2026
3 checks passed
@haraldsteinlechner
haraldsteinlechner deleted the bugs/ctrl-shortcuts-focus branch October 20, 2026 13:15
haraldsteinlechner added a commit that referenced this pull request Oct 20, 2026
…dy shortcut handler

- Delete goes through the page-body onkeydown like Ctrl+Z (#850): pro3dDeleteKey in
  utilities.js, Events.onCtrlShortcutOrDelete, Gui.annotationShortcut. Only the 3D view,
  Annotations and Properties take it; Surfaces and the other panels do not, and text
  fields keep it. Removed from getDrawingActionForKey (would run twice through bubbling).
- DeleteSelectedAnnotations removes the batch in one tree walk (GroupsApp.removeLeavesById)
- tests: Section18 Delete wiring; Section19 List.head/List.take replaced by matches;
  keyboard-undo spec: Delete in Surfaces (none), Properties and the focused 3D view
- docs: AnnotationDeletion.md, KeyboardShortcuts.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant