Conversation
CodexBar now takes the foreground only on a direct user action (tray click, tray menu item, global hotkey, a click in its own UI). - Route every focus request through shell::activation (UserAction, IfAllowed, Never). Only UserAction calls set_focus, whose tao implementation injects a synthetic Alt through SendInput. - Build main, flyout, Settings and the float bar unfocused so show() uses SW_SHOWNOACTIVATE; add SWP_NOACTIVATE to the DWM frame refresh. - Startup and single-instance handoff ask Windows once (IfAllowed); the second instance passes its foreground permission on with AllowSetForegroundWindow before handing off. - Proof mode (CODEXBAR_PROOF_MODE) shows surfaces without activating them. - Float bar recovery restores with SW_SHOWNOACTIVATE instead of SW_RESTORE. - Auto-resume flashes an already running session's taskbar button instead of restoring and activating it, and starts new resume consoles minimized and inactive (SW_SHOWMINNOACTIVE). Batch shims now run through the system cmd.exe with quoting cmd.exe parses; the old wrapper produced \" escapes that cmd.exe cannot read. - Hooks, the Bedrock AWS CLI call and Doubao's arkcli run with CREATE_NO_WINDOW, so background refreshes open no console windows.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
UI proof (browser-use)Result: PASS on build At the maintainer's direction, this proof drove the app's WebView2 over CDP with the browser-use CLI instead of CUA. It used only DOM reads: no Setup
Results
Validation at
|
| Command | Result |
|---|---|
cargo +1.98.0 fmt --all --check |
pass |
cargo +1.98.0 clippy --workspace --all-targets -- -D warnings |
pass |
cargo +1.98.0 test -p codexbar |
2165 passed, 0 failed, 1 ignored |
cargo +1.98.0 test -p codexbar-desktop-tauri |
464 passed, 1 failed: bootstrap_payload_exposes_every_provider_variant, the non-hermetic #684 test that #711 fixes |
ci/circleci: pr-check |
SUCCESS |
| CodeRabbit | SUCCESS |
Screenshots
All paths are under C:\Users\FSOS\AppData\Local\Win-CodexBar\port-audit\proof\713\shots\.
bu-trayPanel-traypanel.png: run 1, the tray panel with the seeded Codex card.bu-popOut-flyout.png: run 2, the flyout window.bu-settings-general-main.png: run 3, Settings → General in dark, with Theme "Auto (system)".bu-settings-handoff-flyout.png: the flyout that the second launch opened.
The three 328×434 tray panel captures are byte-identical. That's expected: the seed and window size are the same, and the panel shows no countdown.
Not blocking (found on main, not caused by this PR)
- The reset-refresh timer in
useProvidersoverflows for resets more than about 24.8 days away. WebView2 stores thesetTimeoutdelay as a 32-bit signed integer, so the timer fires at once and forces a refresh. The Port upstream 0.70.0: refresh 16 provider brand accents #719 proof comment has the details. It's tracked as a separate fix, and this kit's seed keeps every reset under that limit.
Summary
CodexBar should take the foreground only when the user acts on it directly: a tray click, a tray menu item, the global hotkey, or a click in one of its own windows. Startup, single-instance handoff, refreshes, auto-resume, hooks and proof automation now show things without activating them.
Why it happened:
WebviewWindow::set_focusisn't a polite request on Windows.src/platform_impl/windows/window.rs,Window::set_focus(lines 175-186), callsforce_window_active(lines 1500-1527).SetForegroundWindowis refused, that function injects a synthetic Alt down and up throughSendInput, then retries. The source comment calls it "a little hack which can "steal" the foreground window permission".SW_SHOW(taowindow_state.rs,WindowFlags::apply_diff, lines 325-337), which activates on its own.Changes
New
shell/activation.rs: one decision point with three levelsUserActioncallsset_focus(tray click, menu item, hotkey, a click in CodexBar's own UI).IfAllowedmakes one plainSetForegroundWindowand accepts a refusal (launch from Start or Explorer, single-instance handoff).Neverleaves the foreground alone (proof automation, hide-to-tray and failed-transition recovery).Showing without activating
main("focus": falseintauri.conf.json), the flyout, Settings and the float bar are built withfocused(false), so tao shows them withSW_SHOWNOACTIVATE.set_focusis only called fromactivation::apply.Proof mode
CODEXBAR_PROOF_MODEset,activation::suppress_all()turns every request intoNever.set_focusand no foreground change.Single-instance handoff
{id}-sic/{id}-siwwindow (tauri-plugin-single-instance 2.4.1src/platform_impl/windows.rs).AllowSetForegroundWindowfor that instance's pid, so the running instance'sIfAllowedrequest succeeds without the Alt hack.DWM caption refresh
SetWindowPos(SWP_FRAMECHANGED …)inshell/dwm.rsnow also passesSWP_NOACTIVATE. It runs on every surface transition.Float bar recovery
SW_RESTORE, which activates (taowindow_state.rslines 390-402).SW_SHOWNOACTIVATEon the main thread.unminimizethen only refreshes tao's cached flag (taowindow.rslines 584-598 re-readIsIconic).Auto-resume
FlashWindowEx(FLASHW_TRAY | FLASHW_TIMERNOFG)on the session's window, where it used to callShowWindow(SW_RESTORE)plusSetForegroundWindow. The user-initiatedfocus_sessionis unchanged.codexbar::host::console_launchcallsCreateProcessWwithSTARTF_USESHOWWINDOW+SW_SHOWMINNOACTIVE, the same requeststart /minmakes. This is needed becauseCommandExt::show_windowis unstable (Tracking issue for CommandExt::show_window rust-lang/rust#127544).claude.cmd) now run as"<System32>\cmd.exe" /d /v:off /s /c ""<script>" "<arg>" …", with",%and control characters rejected.\". cmd.exe can't parse that.Hooks, Bedrock (
aws configure export-credentials) and Doubao (arkcli usage plan)CREATE_NO_WINDOW, so background refreshes and events don't pop a console window.Checked and left unchanged, since they don't activate or only run on a user action: toasts,
rfddialogs, open URL/path, the updater,codex_desktop,login_runner,credentials_store.Upstream reference
None. This is a Windows-only shell fix (maintainer item "no focus stealing"), with no upstream CodexBar counterpart.
Ported / Deferred
Nothing is ported. Out of scope and unchanged here:
SW_SHOWMINNOACTIVE.focus_sessionbefore this change.CREATE_NEW_PROCESS_GROUPdisables Ctrl+C there. This predates this branch.try_waitloop: pipe-drain risk, predates this branch.Validation
All commands ran in the worktree with a dedicated
CARGO_TARGET_DIR.cargo +1.98.0 fmt --all --checkcargo +1.98.0 clippy --workspace --all-targets -- -D warningscargo test -p codexbarcargo test -p codexbar-desktop-tauricommands::tests::bootstrap_payload_exposes_every_provider_variant(see below)The one failure is #684 and doesn't come from this branch:
mainthe test reads the real%APPDATA%\CodexBar\settings.json, and a deprecated provider is enabled on this machine (79 vs 78).New tests:
shell::activation: user actions force focus; launches only ask; background never touches the foreground; proof mode never activates anything.state: the pending flyout reveal carries its activation.auto_resume_tests::batch_shims_keep_exact_resume_arguments.host::console_launch(Windows):cmd.exeline for.cmd/.bat, case-insensitive, with& ( )kept literal.",%and control characters.GetSystemDirectoryWlookup.agent_sessions:request_session_attentionreportsUnsupportedfor remote and file-only sessions.Affected areas
apps/desktop-tauri/src-tauri/src/:shell/(activation, window, transition, flyout, Settings, DWM),floatbar/window.rs,commands/surface.rs,tray_bridge.rs,main.rs,proof_harness.rs,state.rs,auto_resume.rs,tauri.conf.json.rust/src/:host/console_launch.rs(new),agent_sessions/focus.rs,core/hooks.rs,providers/bedrock,providers/doubao,managed_process.rs(build_command_lineis nowpub(crate)).UI proof
PASS with browser-use over WebView2 CDP on
d38bce7d: #713 (comment)document.hasFocus()false while visible. Dark under themeauto; no host email or account visible.UserAction),IfAllowedoutside proof mode, the auto-resume flash and minimized console, andCREATE_NO_WINDOWspawns. The unit tests above cover them.