fix(editor): prevent focus loss when typing in header/footer editors (SD-1993)#2238
fix(editor): prevent focus loss when typing in header/footer editors (SD-1993)#2238
Conversation
…(SD-1993) Replace unconditional appendChild calls in DomPainter.updateVirtualWindow() with cursor-based DOM reconciliation that skips moves for elements already in the correct position. Add focus save/restore safety net in PresentationEditor.#flushRerenderQueue for edge cases.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 41a9dec4be
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (hadHfFocus && activeHfEditor?.view) { | ||
| const doc = this.#visibleHost.ownerDocument; | ||
| const editorDom = activeHfEditor.view.dom; | ||
| if (doc && !editorDom.contains(doc.activeElement)) { |
There was a problem hiding this comment.
Gate focus recovery on current H/F session
The new focus recovery in #flushRerenderQueue always refocuses the previously-captured header/footer editor when it lost focus during rerender, but it does not verify that this editor is still the active session. If the user intentionally exits header/footer mode (or switches to another header/footer editor) while #rerender() is awaiting, exitMode() can correctly focus the body editor and then this block will immediately steal focus back to the stale editor, causing unexpected focus jumps and mode-switch glitches.
Useful? React with 👍 / 👎.
Summary
Fixes SD-1993: headers and footers lose focus after the first keystroke, making them effectively uneditable.
Root cause
Every keystroke in a header/footer PM editor triggers a full body rerender cycle:
DomPainter.updateVirtualWindow()has an ordering loop that re-appends all mounted page elements viaappendChild. CallingappendChildon an element already in the DOM is a move-to-end operation. The browser fires ablurevent on any focused element inside the moved subtree. This kills focus on the header/footer PM editor after every keystroke.All three reported symptoms stem from this single focus loss:
Fix
1. Cursor-based DOM reconciliation in
updateVirtualWindow(renderer.ts)Replace the unconditional
appendChildordering loop with cursor-based reconciliation. Tracks acursorpointer walking through the existing children. For each mounted page, if it's already at the cursor position, skip the DOM mutation and advance. Only callinsertBeforewhen elements are actually out of order.In the common case (H/F typing with no scroll or window change), pages are already in the correct order after
clearGapSpacers()removes old gaps. Zero moves = zero blur = focus preserved.2. Focus save/restore safety net (
PresentationEditor.ts)Captures the active H/F editor's focus state before
#rerender(). In thefinallyblock, if focus was lost (e.g. from edge cases like scroll during editing, viewport resize, page count changes), restores it viaactiveHfEditor.view.focus().Test plan