Skip to content

fix(browser): focus the owning split when the page guest is focused - #24364

Open
innocarpe wants to merge 3 commits into
stablyai:mainfrom
innocarpe:fix-22144-browser-guest-focus
Open

innocarpe wants to merge 3 commits into
stablyai:mainfrom
innocarpe:fix-22144-browser-guest-focus

Conversation

@innocarpe

Copy link
Copy Markdown
Contributor

Description

Clicking inside a browser page did not focus the split that owns that page. The overlay focuses its group on its own pointer and focus events, but a guest webview does not bubble those events. Ctrl+Tab then cycled the previously focused group.

Focused fix

In:

  • On the webview focus event, resolve the browser page's unified tab and focus that tab's group.
  • A page that is not in a group yet (mid-move) does not change the focused split.

Out:

  • Address-bar focus, find-in-page, and guest shortcut routing.
  • Synthetic mouse forwarding.

Preserves

The existing address-bar suggestion dismiss still runs on guest focus. Focusing the address bar does not emit webview focus, so it does not move the split. focusGroup only updates split state; it does not pull keyboard focus out of the page.

Evidence

node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts --cache false src/renderer/src/components/browser-pane/host-guest/browser-guest-owning-group.test.ts

The test covers the owning split, a non-browser tab with the same id, and the same page id on another worktree.

User-regression-tradeoffs

A click in the page now makes that split the Ctrl+Tab target, which is the reported expectation. An orphaned page that has not landed in a group yet leaves the previous split focused.

Fixes #22144

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 45 seconds.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: f76477b7-c260-4de9-8882-7f4c04eba7d4

📥 Commits

Reviewing files that changed from the base of the PR and between f32ada7a4015dc4c04bcbd366d3086cff9d7434e and 56180cc.

📒 Files selected for processing (4)
  • src/renderer/src/components/browser-pane/host-guest/bind-browser-page-webview-listeners.test.ts
  • src/renderer/src/components/browser-pane/host-guest/bind-browser-page-webview-listeners.ts
  • src/renderer/src/components/browser-pane/host-guest/browser-guest-owning-group.test.ts
  • src/renderer/src/components/browser-pane/host-guest/browser-guest-owning-group.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 6dc562b7-67ba-4631-8c4e-1e11e78e574a

📥 Commits

Reviewing files that changed from the base of the PR and between 0ad77ea and f32ada7a4015dc4c04bcbd366d3086cff9d7434e.

📒 Files selected for processing (4)
  • src/renderer/src/components/browser-pane/host-guest/bind-browser-page-webview-listeners.test.ts
  • src/renderer/src/components/browser-pane/host-guest/bind-browser-page-webview-listeners.ts
  • src/renderer/src/components/browser-pane/host-guest/browser-guest-owning-group.test.ts
  • src/renderer/src/components/browser-pane/host-guest/browser-guest-owning-group.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

When a browser webview receives focus, its handler dismisses address-bar suggestions and looks up the browser guest’s owning group using the current app-store state. If a matching group exists, the handler focuses it. The handler is removed during cleanup. Tests cover group lookup, focus behavior, and listener cleanup.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to f32ad

Guest focus now selects its owning split while preserving suggestion dismissal and listener cleanup. No actionable merge-blocking risk is identified.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the problem, fix, scope, preserved behavior, regression trade-off, linked issue, and one automated test. However, it does not follow the repository template and omits the requ… Rewrite the description using the repository template. Add the ELI5, What Changed, Why, Linked Issue, Visual Proof, Testing, AI Disclosure, Review, Agent skill upstream boundary, Notes, and Checklist sections. Provide before/after visual ev…
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: focusing the split that owns a browser page guest.
Linked Issues check ✅ Passed The changes satisfy the coding requirements in [#22144]. The webview focus handler reads the current store, matches the guest workspaceId to the owning browser tab in the current worktree, and cal…
Out of Scope Changes check ✅ Passed The changes stay within [#22144]. The new lookup helper, webview focus integration, cleanup logic, and automated tests directly support browser guest focus synchronization. No unrelated product behavi…
Full details: Description check

Explanation

The description explains the problem, fix, scope, preserved behavior, regression trade-off, linked issue, and one automated test. However, it does not follow the repository template and omits the required ELI5, What Changed, Why, Visual Proof, Testing checklist, AI Disclosure, Review, boundary, Notes, and Checklist sections. The behavior change also lacks the required visual proof or an explicit N/A explanation.

Resolution

Rewrite the description using the repository template. Add the ELI5, What Changed, Why, Linked Issue, Visual Proof, Testing, AI Disclosure, Review, Agent skill upstream boundary, Notes, and Checklist sections. Provide before/after visual evidence for the UI behavior change, or write exactly N/A with a reason if visual proof is not applicable. Record manual testing, platforms tested, automated test status, cross-platform and SSH considerations, and relevant lint, typecheck, test, and build results or state that CI will cover them.

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Adds focus handling for browser guest pages.

The PR appears safe to merge; no actionable new issue or outstanding previous finding remains.

Summary

The PR focuses a browser page’s owning split when its guest webview receives focus. The latest changes extract the focus-listener registration into a helper and update its test; suggestion dismissal and removal of the same listener on cleanup remain intact.

Reviews (3) · Last reviewed commit: "fix(browser): drop the casts from the gu..."

Comment thread src/renderer/src/components/browser-pane/host-guest/browser-guest-owning-group.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

One real defect: the new guest-focus listener is never removed because the cleanup still references the old named handler. Details on the line.

Reviewed changes

Read the full diff end-to-end (3 files). Context checked: focusGroup (tabs-group-actions.ts), the overlay's existing onPointerDown/onFocusCapture focus re-sync (BrowserPaneOverlayLayer.tsx), the browser-tab entityId === browserTabId convention across the renderer, and the attach/rebind path (attach-browser-page-webview.ts, use-browser-page-webview-lifecycle.ts).

  • New helper browser-guest-owning-group.ts — resolves the owning groupId for a browser page and calls focusGroup; no-ops for a tab mid-move or on another worktree.
  • Guest focus listener — replaces the named dismiss handler with an anonymous arrow that also focuses the owning split, reached through useAppStore.getState().
  • New unit test — covers the owning split, a non-browser tab with the same id, and the same page id on another worktree; exercises only the pure helper, not the listener binding.

The behavior is otherwise correct: focusGroup only mutates split state (no DOM focus pull), so there is no re-entrancy loop, and entityId === browserTabId matches every other browser-tab lookup in the renderer.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@innocarpe

Copy link
Copy Markdown
Contributor Author

Sync update (f32ada7a40)

Guest focus now looks up the unified tab by the page workspace id, which is what that tab stores. A page id no longer misses the split, so Ctrl+Tab follows the clicked page. Cleanup removes the same focus callback that was registered, so reattaching the webview does not stack listeners.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new bind test file fails the casting scan that PR CI runs (pnpm run check:code-quality:changed), so the check stays red until its three assertions carry the required SAFETY: suppressions.

Reviewed changes

Re-reviewed the delta since the prior pullfrog review (f32ada7a40, on top of 5f358a1b91). Verified the key semantics against the actual producers: workspaceId is the browser BrowserWorkspace.id (browser-workspace-pane.tsx passes workspaceId={browserTab.id}), which is exactly the value buildBrowserUnifiedTab writes to the unified tab's entityId (runtime/web-session-tabs-sync/tab-builders.ts:51), so the new lookup matches where the previous live-page-id lookup did not.

  • Named the guest-focus handler — handleGuestFocus is now registered and removed by the same reference, so unbind detaches the listener (retires the prior review's leak finding).
  • Corrected the owning-tab key — the owning-tab match uses workspaceId (stored in unified entityId) instead of the live page id.
  • Updated and added tests — the helper test follows the rename; a new bind test asserts the handler focuses the owning group and is removed on cleanup.

focusGroup only mutates split state, so a guest focus cannot pull DOM focus or re-enter. No behavior regressions found in the delta.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

innocarpe and others added 3 commits October 1, 2026 20:52
Guest webview focus does not bubble to the overlay, so Ctrl+Tab kept
the previously focused split. Address-bar focus still stays put.

Fixes stablyai#22144
Co-authored-by: Cursor <cursoragent@cursor.com>
Guest focus is registered through one helper, and cleanup removes that
same function. The test uses a small listener target instead of casting
a partial webview.
@innocarpe
innocarpe force-pushed the fix-22144-browser-guest-focus branch from f32ada7 to 56180cc Compare October 1, 2026 11:56
@innocarpe

Copy link
Copy Markdown
Contributor Author

Sync update (56180cc263)

Guest focus is registered and removed through one helper, so a reused webview does not accumulate callbacks. The listener test no longer casts a partial webview, which was failing the changed-code assertion check.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Re-reviewed the delta since the prior pullfrog review (f32ada7a40). The only net change is 56180cc263, which addresses that review's finding and tidies the test. Both prior Pullfrog threads are resolved.

  • Extracted bindBrowserGuestFocus — the focus handler and its add/remove now live in one exported function returning its own cleanup, with the webview typed through a narrow BrowserGuestFocusTarget; bindBrowserPageWebviewListeners calls it and uses removeGuestFocus() in cleanup.
  • Simplified the bind test — it targets bindBrowserGuestFocus directly with a hand-typed fake webview, dropping all three as casts (and the heavy module mocks) that failed the casting scan.

Verified locally: pnpm run check:code-quality:changed reports 0 findings across the 4 changed files, pnpm tc:web passes, and both new tests pass.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

This branch has not been deployed

No deployments
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.

[Bug]: Clicking inside browser page content does not focus its owning split, so Ctrl+Tab targets the previously focused group

1 participant