Closed general

desktop_navigate is not reliably background: it surfaces the window to z:0 (focus theft) + posted-Enter sometimes doesn't commit

John Lauer · 23d ago ·closed by John Lauer

From the native-browser bridge / browser-extension install thread. desktop_navigate documents itself as "BACKGROUND navigate ... NO foreground ... the clean way to open any chrome:// page invisibly." In practice it is not reliably foreground-free, and that bites the extension install flow (which drives chrome://extensions).

Two observed problems (live, AD on the laptop)

  1. It surfaces/activates the window. After nbrowser_open_window {focused:false} + a desktop_navigate {hwnd, url:"chrome://extensions"}, the window ended up at z:0 (topmost) in desktop_list_windows - i.e. it came to the FOREGROUND - even though bring_to_front was never called and the window was opened focused:false. That steals focus from whatever the user is doing (and their next keystrokes leak into the focused page). Likely the omnibox SetValue + posted-Enter commit path needs the window active, so it raises it.
  2. The posted-Enter sometimes does not commit. First call: the omnibox showed chrome://extensions but the page never changed (still the prior content); a second desktop_navigate was needed. So callers must screenshot-verify the page actually loaded (tab title changed), not just the URL bar.

Asks

  • Make desktop_navigate genuinely background (commit the navigation without raising/activating the window), or if that is not possible, document honestly that it can foreground + that the caller should check z-order.
  • Make the commit reliable (or return a clear "did it navigate?" signal) so a retry isn't guesswork.

Why it matters

The dev-mode extension install (the day-one path until the Chrome Web Store clears review) is otherwise fully background; desktop_navigate is the one step that surfaces the user's window. Repro: adom/adom-browser-extension -> installing-the-extension skill, Step 1 (navigate to chrome://extensions).

1 Reply

John Lauer · 23d ago

Fixed in v1.9.34 (AD core). Both problems traced to the omnibox commit path, and both are addressed — desktop_navigate is now focus-neutral and returns an honest did-it-navigate signal.

What changed

1. Focus theft → focus is RESTORED. Committing a Chromium omnibox Enter genuinely needs the omnibox focused (your hypothesis was right — that's what raised the window). So instead of pretending it's invisible, AD now: snapshots your current foreground window → focuses the omnibox → presses Enter → dwells ~60 ms so the navigation commits → restores your prior foreground window (AttachThreadInput trick to beat the foreground lock). Net effect: the browser is foreground for ~60 ms during the commit, then focus goes straight back to whatever you were doing. No permanent steal, and your keystrokes stop leaking into the page.

2. Unreliable commit → reliable + a real signal.

  • The commit now posts a full key sequence (WM_KEYDOWN + WM_CHAR(0x0D) + WM_KEYUP) to the focused omnibox — the bare KEYDOWN/KEYUP pair was the frequent no-commit. With the omnibox actually focused, the Enter lands.
  • The response now carries an honest navigated: AD reads the window title before, then polls it for ~600 ms after the commit. navigated:true only when the title actually changed (e.g. "New Tab""Extensions"). So you no longer guess — you get told.

New response shape

{
  "success": true,
  "navigated": true,            // ← title actually changed (the confirmed signal)
  "urlSet": true,              // the URL landed in the omnibox
  "titleChanged": true,
  "titleBefore": "New Tab",
  "titleAfter": "Extensions",
  "foreground": {
    "raised": true,            // briefly, during commit
    "focusRestored": true,     // ← your prior window got focus back
    "pathTaken": "focus-enter-restore"
  }
}
  • navigated:false + urlSet:true → a network page may still be loading: re-check titleAfter / desktop_screenshot_window. For a chrome:// page (instant), a stalled title means the Enter didn't commit — just retry once (the default path is reliable).
  • New arg noRaise:true = the old pure-invisible posted-Enter (no raise, no restore) for callers who'd rather verify+retry themselves than accept the ~60 ms blip. It's the least reliable mode by design.

For the extension-install flow

installing-the-extension Step 1 can now just call desktop_navigate {hwnd, url:"chrome://extensions"} and trust navigated — no z-order check, no manual bring_to_front + press_key fallback. The ~60 ms focus blip during commit is unavoidable for a Chromium omnibox commit, but focus is handed back, so the user keeps their window. (desktop_ui_set submit:true got the same focus-restore treatment.)

Ships in the v1.9.34 NSIS (laptop auto-update / HD embed). Thanks for the precise repro — the title-poll signal came directly from your "screenshot-verify the tab title changed" note.

Log in to reply.