Skip to content

fix(desktop-gpui): keep the camera bubble above the picker overlays - #3441

Merged
richiemcilroy merged 11 commits into
mainfrom
fix/gpui-camera-above-picker
Oct 27, 2026
Merged

richiemcilroy merged 11 commits into
mainfrom
fix/gpui-camera-above-picker

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Problem

When the target picker opens, the camera bubble can end up behind the picker overlays. The new picker probe reproduces it on every desktop.

  • macOS. The camera is meant to sit at level 8 (recording_controls_level) and the overlays at 7. apply_panel_behavior and place_overlay_panel set that level, then call apply_fullscreen_overlay_behavior, whose setFloatingPanel:YES resets an NSPanel to NSFloatingWindowLevel. So the camera, the overlays, the recording bar and the teleprompter all ran at level 3, and whichever was ordered front last won. The probe on main read the camera at layer 3 behind an overlay at layer 3 in all three modes.
  • Windows. The camera and the overlays are all plain HWND_TOPMOST windows, and each overlay is placed at the top of that band after the camera exists. The camera's re-raise was a posted HWND_TOP (SWP_ASYNCWINDOWPOS), and gpui's activate() runs on a later executor turn, so the overlay's activation landed last and won. Every later click on an overlay activated it again.
  • Linux (X11). The re-raise only ran for a camera that platform::window_is_visible reported visible. That helper always returns false off macOS and Windows, so the raise never ran. The probe on main caught the overlay above the camera in Display mode.

Change

  • macOS: apply the Spaces behaviour before the level in both places, so the level sticks: camera and bar at 8, overlays at 7, teleprompter at its intended 101. The main window passes NSFloatingWindowLevel explicitly and is unchanged.
  • One raise path: raise_camera_above_overlays replaces the visibility-filtered raise. Windows and X11 no longer require window_is_visible, because neither raise path shows a hidden window. macOS keeps the filter, because orderFrontRegardless would show a hidden bubble.
  • Overlay activation: the overlay observes its own activation and re-raises the camera each time it becomes active. That covers the focus hand-off when it opens and every click afterwards.
  • Windows: the camera raise is a synchronous SetWindowPos(HWND_TOPMOST, SWP_NOACTIVATE) (platform::raise_panel_native). On macOS the same call first restores the panel level if anything lowered it.
  • Outside the gpui borrow: the camera's frame is read inside cx.update, and the native raise runs after it returns. orderFrontRegardless calls straight back into gpui, which would drop those callbacks while the app is borrowed.

Test

CAP_PICKER_PROBE_OUTPUT (debug builds only) does the following, and the new Picker smoke (real app) workflow runs it on macOS, Windows, and Linux under Xvfb with openbox:

  1. Opens the camera.
  2. Arms Display, Window and Area.
  3. Hands focus to the main window, then activates each overlay the way a click does. Opening an overlay already raises the camera, so this checks that activation alone raises it again.
  4. Writes the native front-to-back order of Cap's windows (CGWindowListCopyWindowInfo with each window's layer, EnumWindows, or the X11 window tree, since the override-redirect camera and overlays are not in the window manager's client list).

The workflow fails unless the camera is above every overlay in every mode. The probe writes its verdict as the report's first key, and run.sh checks only that key: nested checks have passed keys of their own.

main (probe only) this branch
macOS camera layer 3 behind overlay layer 3, all modes camera layer 8 above overlays at 7, all modes
Linux X11 overlay above camera in Display mode camera on top in all modes
Windows no run: the first probe run failed to build on the windows-2025 image (ffmpeg-sys bindgen) camera on top in all modes

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no new actionable issue was found.

Summary

Keeps the camera bubble above target-picker overlays on macOS, Windows, and X11.

  • Picker overlays no longer cover the camera bubble.
  • Picker smoke checks run on all three desktop platforms.

Reviews (5) · Last reviewed commit: "fix(desktop-gpui): the picker smoke read..." · Reviewed by Greptile

@vercel

vercel Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cap-status Ready Ready Preview Oct 27, 2026 9:46pm UTC

@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

Comment thread apps/desktop-gpui/src/app_windows.rs Outdated
Comment thread apps/desktop-gpui/src/picker_probe.rs
Comment thread scripts/picker-smoke/run.sh Outdated
@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

Comment thread .github/workflows/picker-smoke.yml Outdated
@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

1 similar comment
@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

@superagent-security superagent-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Superagent found 1 security concern(s).

- "apps/desktop-gpui/src/platform.rs"
- "apps/desktop-gpui/src/platform/**"
- "scripts/picker-smoke/**"
- ".github/workflows/picker-smoke.yml"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Fork pull requests can queue three full-platform app builds by editing only the new smoke workflow

Self-referencing paths lets a fork queue 3 full app builds (60-min timeout) by editing only CI/harness files.

Gate workflow/harness-only triggers to same-repo PRs (as perf-budget.yml does) or drop those paths from the fork-triggerable filters.

AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.

<file name=".github/workflows/picker-smoke.yml">
<violation number="1" location=".github/workflows/picker-smoke.yml:14">
<priority>P2</priority>
<title>Fork pull requests can queue three full-platform app builds by editing only the new smoke workflow</title>
<evidence>The new workflow runs on pull_request (opened, synchronize, reopened, ready_for_review) and lists both its own file (`.github/workflows/picker-smoke.yml`, added line 14) and `scripts/picker-smoke/**` (line 13) in its paths filters. A fork contributor can therefore trigger the `smoke` matrix by editing only CI/harness files, without touching product code. That matrix builds the whole `cap-gpui` app on `blacksmith-6vcpu-macos-15`, `windows-2022`, and `blacksmith-8vcpu-ubuntu-2404` with `timeout-minutes: 60` (added lines 27-43). `concurrency.cancel-in-progress: true` only cancels overlapping runs, so successive `synchronize` pushes each get a fresh three-platform job. The repository already fixed this exact pattern in `perf-budget.yml` by gating self-file-triggered work on same-repository PRs, and an equivalent finding on `instant-reliability.yml` was accepted for fixing. This adds a new, cheap, repeatable route for untrusted forks to consume shared macOS/Windows/Linux runner capacity.</evidence>
<recommendation>Do not let a PR that changes only the smoke workflow or `scripts/picker-smoke/**` queue the full three-platform matrix for forks. Mirror the `perf-budget.yml` same-repo guard (e.g. `github.event.pull_request.head.repo.full_name == github.repository`) for workflow/harness-only changes, or remove the workflow's own path and the harness path from the fork-triggerable filters. Optionally lower the 60-minute timeout and keep full validation for internal PRs or `workflow_dispatch`.</recommendation>
</violation>
</file>

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Capy found no issues.

View 1 other finding in Capy.

Open in Capy

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Capy found no issues.

Open in Capy

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Capy found no issues.

View 2 other findings in Capy.

Open in Capy

@richiemcilroy
richiemcilroy merged commit 5672f59 into main Oct 27, 2026
71 of 72 checks passed

This branch was successfully deployed

2 active deployments
Preview – cap-web — b55f926d Deployed Oct 27, 2026 by vercel[bot]
Preview – cap-status — b55f926d Deployed Oct 27, 2026 by vercel[bot]
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