Skip to content

Let typing follow Ctrl+N without a click - #555

Merged
erikdarlingdata merged 1 commit into
devfrom
fix/551-focus-after-new-tab
Sep 22, 2026
Merged

erikdarlingdata merged 1 commit into
devfrom
fix/551-focus-after-new-tab

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

Fixes #551. FocusEditor ran synchronously inside AttachedToVisualTree, where the tab strip and window are still arbitrating focus — the later claimant won, and the first keystrokes after Ctrl+N vanished until a click. Present on Avalonia 11 (reproduced on the installed 1.25 build) and 12 alike; headless tests can't see it because no focus arbitration runs there. The fix defers the focus one Loaded-priority hop. Gotcha review clean, including the detach race: Focus() without a visual root is a verified no-op in both Avalonia lines, so no guard is needed, and the suite's focus assertions all sit on untouched synchronous paths (full suite 713 passed / 1 known skip). Drive-verified: Ctrl+N then immediate typing lands colorized with zero clicks.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sr43FouJ6RizUyoWQeR5FX

The attach handler focused the editor synchronously, mid-event, while
the tab strip and window were still arbitrating focus - so whatever
ran after the handler won, and the first keystrokes into a fresh
query tab landed nowhere until something was clicked. The same in a
real window on Avalonia 11 and 12; invisible headlessly, because no
arbitration runs there.

Focusing one Loaded-priority hop later lands after the layout pass
and sticks. Focus() on a control whose tab was switched away before
the post fires is a benign no-op in both Avalonia lines (no visual
root means no focus manager means false, not a throw), so the
deferral needs no guard. The other FocusEditor call sites run from
input handlers after arbitration settles and stay synchronous.

Drive-verified both directions: fresh launch, Ctrl+N, immediate
typing - lost before the change, colorized in the editor after it.

Fixes #551

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sr43FouJ6RizUyoWQeR5FX
@claude

claude Bot commented Sep 22, 2026

Copy link
Copy Markdown

Reviewed. This is a minimal, well-scoped fix — deferring FocusEditor() to DispatcherPriority.Loaded matches an existing pattern already used elsewhere in this codebase (QueryStoreGridControl, PlanViewerControl.Minimap, ProgressBarBehaviors), so it's consistent with repo conventions rather than a one-off workaround.

Checked:

  • FocusEditor() (QuerySessionControl.EmptyState.cs:177) just calls QueryEditor.Focus() / TextArea.Focus() — no state that would be unsafe to invoke on a control that got detached before the posted callback runs.
  • The other three FocusEditor() call sites are untouched and still run synchronously from input handlers post-arbitration, so this doesn't broaden the fix beyond the one case that needed it.
  • No new warnings, no T-SQL/untrusted-input surface here, no version-file changes needed.
  • Confirmed no existing headless test exercises this path (grepped SessionKeyboardTests.cs and the rest of PlanViewer.Core.Tests for Focus/IsFocused — no hits), consistent with the PR body's explanation that focus arbitration doesn't run headlessly. Not something to block on given the constraint is real, but worth knowing this regression class stays uncovered by CI.

No blocking issues.

@erikdarlingdata
erikdarlingdata merged commit b2b0907 into dev Sep 22, 2026
3 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/551-focus-after-new-tab branch September 22, 2026 02:45
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