You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When clicking a session in the left sidebar, keyboard focus stays on the WPF sidebar item that was clicked — it does not "jump into" the selected CLI. The user has to click into the terminal area before they can start typing.
The root cause is in TerminalBridge.FocusTerminal(): it only posts a JS focus message to xterm.js inside the WebView2. That focuses the inner xterm textarea at the DOM level but does nothing at the WPF level, so the WebView2 host never actually gains keyboard focus when another WPF control (the clicked sidebar Border) currently holds it.
The same flow runs from Ctrl+Tab cycling and from the OnWindowActivated Alt+Tab refocus — the latter happens to work because focus was already on the WebView2 before the window deactivated, but a fresh sidebar click breaks the assumption.
Solution
Make TerminalBridge.FocusTerminal() call _webView.Focus() in addition to posting the JS focus message, so WPF keyboard focus actually moves onto the WebView2 host.
Add a new AppSettings.AutoFocusTerminalOnSelect setting (default true) that gates the focus call inside MainViewModel.FocusSession.
Surface the setting in the Settings window under "SESSION SETTINGS" as "Auto-focus terminal when selecting a session".
This means:
Default behaviour: clicking a sidebar session (or Ctrl+Tab cycling) immediately moves focus into that session's terminal — no extra click needed.
Users who prefer the old behaviour can disable the setting; selection still updates ActiveSession and the active-terminal highlight, but focus is left where it was.
Files affected
src/CodeShellManager/Models/AppState.cs — new AutoFocusTerminalOnSelect property on AppSettings.
src/CodeShellManager/Terminal/TerminalBridge.cs — FocusTerminal() now also calls _webView.Focus().
src/CodeShellManager/ViewModels/MainViewModel.cs — FocusSession gates the focus call on the setting.
src/CodeShellManager/Views/SettingsWindow.xaml + .xaml.cs — new checkbox with clone/populate/save wiring.
src/CodeShellManager/MainWindow.xaml.cs — copy edited value back into _vm.Settings.
the WPF-vs-WebView2 focus split is the obvious fix but there's a second trap waiting. _webView.Focus() moves logical focus onto the host but xterm.js inside CoreWebView2 has its own focus model, and on a cold WebView2 (first activation after process start) the JS focus message can race the WPF focus call and land before the iframe is actually ready to accept keystrokes. result: focus looks correct in spy++ but the first 1-2 chars get eaten. cheap mitigation is to await CoreWebView2InitializationCompleted before wiring FocusTerminal, and on Ctrl+Tab cycling debounce the focus call until WebMessageReceived confirms xterm acked. otherwise the setting works 95% of the time and you ship a heisenbug for the other 5.
Activity
mortenaslo commentedon May 9, 2026
Implementation in progress:
feat/auto-focus-terminal-on-selectfeat: auto-focus terminal when selecting a session (#13)Will auto-close on merge via the
Closes #13reference in the PR body.m13v commentedon May 9, 2026
the WPF-vs-WebView2 focus split is the obvious fix but there's a second trap waiting. _webView.Focus() moves logical focus onto the host but xterm.js inside CoreWebView2 has its own focus model, and on a cold WebView2 (first activation after process start) the JS focus message can race the WPF focus call and land before the iframe is actually ready to accept keystrokes. result: focus looks correct in spy++ but the first 1-2 chars get eaten. cheap mitigation is to await CoreWebView2InitializationCompleted before wiring FocusTerminal, and on Ctrl+Tab cycling debounce the focus call until WebMessageReceived confirms xterm acked. otherwise the setting works 95% of the time and you ship a heisenbug for the other 5.