Menu

#490 fix(tray): finish the Windows port of the in-process capture module

closed
nobody
None
2026-07-20
2026-07-20
Anonymous
No

Originally created by: Akarsh-Hegde

The failure

The Windows tray build failed to compile meridian-tray with six errors — all one class: macOS-only code reaching a Windows build.

error[E0455]: link kind `framework` is only supported on Apple targets
  --> tray\src-tauri\src\capture\ui_events.rs:79:35
error[E0455]: link kind `framework` is only supported on Apple targets
   --> tray\src-tauri\src\lib.rs:927:42
error[E0425]: cannot find function `with_autorelease_pool` in this scope
   --> tray\src-tauri\src\capture\screenpipe.rs:106:27
error[E0599]: no method named `title_bar_style` found ...
   --> tray\src-tauri\src\tray.rs:202:10
error: unused variable: `app_handle`  (system.rs:57, tray.rs:122)

Diagnosis

The capture module looks Apple-only (Apple Vision OCR, autorelease pools, IOKit), which invites the wrong fix — gating capture off on Windows. The code says otherwise: capture/screenpipe.rs:468 already has a perform_ocr_windows arm, drm_detector.rs is fully paired macOS/non-macOS, and there are documented Windows permission stubs at 573/583. The forked screenpipe crates compile on Windows too — nothing in the CI log failed inside them, only in meridian-tray.

So this is an incomplete Windows port, not unportable code. Gating capture off would have silently disabled a feature that is actively being built, and left the Windows tray producing no sessions.

The fix

Three missing Windows arms, mirroring the both-arms pattern already in these files:

Site Fix
capture/screenpipe.rs with_autorelease_pool was macOS-gated but called from the shared engine loop (L106). Added a pass-through non-macOS arm, so the loop stays platform-agnostic instead of cfg-ing the call site.
capture/ui_events.rs input_monitoring_granted (IOKit) gated to macOS + a Windows arm returning true — no TCC there, matching the fork's own screenpipe_a11y::platform::windows check_permissions().
lib.rs start_capture's CGPreflightScreenCaptureAccess launch gate scoped to macOS, always-open on Windows.

Two errors were unrelated to capture, and were the same eight duplicated lines in tray.rs and commands/system.rs: a revert-to-Accessory window hook whose #[cfg] sat on the closure body, so on Windows the closure captured nothing and app_handle tripped -D warnings. Extracted to sys::revert_to_accessory_on_close — gated once instead of twice — and dropped the now-unused WindowEvent import from tray.rs.

title_bar_style is restructured out of the builder chain because both the method and tauri::TitleBarStyle are macOS-only — a #[cfg] on the call alone still leaves an unresolvable type. Windows keeps a standard title bar (the wizard card sits ~26px lower; cosmetic, layout holds).

Verification — please read

  • macOS: genuinely clean. cargo clippy --all-targets clean, cargo fmt --check clean, 114 tests pass.
  • Windows: unverified locally. Every line added here is cfg'd out on macOS, so the local checks verified zero of it. Cross-compiling is blocked by ring's C build needing the MSVC headers, which wouldn't faithfully reproduce the msvc CI anyway.

Worth flagging for review: the Windows-only arms — including the pre-existing perform_ocr_windows path — have never been type-checked by any compiler, because resolution errors (E0455/E0425) abort before type-checking. A round-2 CI error is possible, most likely another unused-on-Windows-only binding under -D warnings, which is exactly what errors 5 and 6 were. Windows CI on this PR is the real check.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Amk5pH47wJj76HBm5oDu9X

Related

Tickets: #493
Tickets: #495
Tickets: #500

Discussion

  • Anonymous

    Anonymous - 2026-07-20

    Originally posted by: coderabbitai[bot]

    [!IMPORTANT]

    Review skipped

    Auto reviews are disabled on base/target branches other than the default branch.

    Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.


    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro Plus

    Run ID: 657e510b-bf92-4d87-9d00-17ef9015a4a3

    You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

    Use the checkbox below for a quick retry:
    - [ ] 🔍 Trigger review

    ✨ Finishing Touches
    🧪 Generate unit tests (beta) - [ ] Create PR with unit tests - [ ] Commit unit tests in branch `fix/windows-tray-build`

    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 - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

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

     
  • Anonymous

    Anonymous - 2026-07-20

    Originally posted by: Akarsh-Hegde

    Review

    The diagnosis and all six fixes are correct. But the PR asks "Windows CI on this PR is the real check" — I went and read that check, and it does not say what the green tick implies.

    The green "Windows portability" check does not cover this PR

    That job's tray step is non-blocking:

    # .github/workflows/ci.yml:143
    
    - name: check tray
      continue-on-error: true
      run: cargo check -p meridian-tray --all-targets
    

    Its blocking steps are cargo check/test -p meridian -p meridian-coreneither touches meridian-tray, and every file in this PR is under tray/src-tauri/. So the job is green while verifying zero lines of this change.

    The step itself failed. From the job log (run 88281045925):

    error: could not compile `meridian-tray` (lib) due to 15 previous errors
    error: could not compile `meridian-tray` (lib test) due to 6 previous errors
    Process completed with exit code 1.
    

    The tray still does not compile on Windows. The 15 are all -D dead-code, in three files:

    File Items
    backend_install.rs cleanup_legacy_screenpipe, cleanup_legacy_mlx_server, cleanup_legacy_a11y_helper, migrate_legacy_bundle_env, apply_subs, render_plist, register_agent, launchctl
    capture/drm_detector.rs SAFARI_STYLE_BROWSERS, CHROMIUM_STYLE_BROWSERS, current_tab_url_script, scriptable_browsers, NATIVE_APP_PROCESS_HINTS
    commands/app_icons.rs, sys.rs cache_key, uid_str

    This is not a regression — it's the next layer

    All 15 are pre-existing macOS-only helpers, and none sit on code this PR adds. They were invisible before precisely because E0455/E0425 abort ahead of dead-code analysis — exactly the mechanism the PR body predicts, and it landed one round earlier than expected. Removing the resolution errors is what exposed them. This PR adds zero new dead code: both new items (sys::revert_to_accessory_on_close, the Windows input_monitoring_granted) are called unconditionally and are live on Windows.

    So: correct, net-positive, and it advances the burn-down. It just doesn't reach what the title claims.

    Ask

    The repo already has the exact pattern for these — #[cfg_attr(not(target_os = "macos"), allow(dead_code))], as used at lib.rs:663/673/680 and commands/app_icons.rs:40/91. Either:

    • (a) apply it to the 15 here, so check tray actually goes green and the port is finished; or
    • (b) retitle to something like fix(tray): resolve the Windows link/resolution errors in the capture module and track the dead-code layer separately.

    I'd take (a) — the remaining work is mechanical, and it's the only way the "finished" claim gets a compiler behind it. Worth considering dropping continue-on-error once it's green, otherwise the next round regresses silently the same way.

    Nits

    1. ui_events.rsinput_monitoring_granted has arms for macos and windows only. Any third target fails to resolve. sys.rs:138 already models the alternative (all(not(macos), not(windows))), and the sibling arm added in this same PR (with_autorelease_pool) uses not(macos). Using not(target_os = "macos") here would be self-consistent and target-complete.

    2. sys.rs — two mechanisms for one problem. win is silenced with #[cfg_attr(not(macos), allow(unused_variables))] on the parameter while app uses a trailing let _ = app;. A single let _ = (app, win); in the not(macos) block would drop the attribute and keep the signature clean.

    3. tray.rs wizard sizing. The comment says the card sits ~26px lower on Windows, but inner_size is the client area in Tauri — with an opaque title bar the webview is still 1000x680 and the card still centres; the outer window just grows. Cosmetic either way, but the note reads as describing a shift that shouldn't occur.

     
  • Anonymous

    Anonymous - 2026-07-20

    Originally posted by: Akarsh-Hegde

    Review was correct on every point, including the one that mattered most: I cited the green "Windows portability" tick as verification without checking that its tray step is continue-on-error: true. The job was green while compiling none of this PR. Confirmed the 15 dead-code errors in the run you linked.

    Took (a). Pushed in 51891a7c:

    The 15 items now carry #[cfg_attr(not(target_os = "macos"), allow(dead_code))], the pattern already at lib.rs:663/673/680 and app_icons.rs:40/91 — 8 launchd/plist helpers in backend_install.rs, the 5 AppleScript browser tables in capture/drm_detector.rs, app_icons::cache_key, sys::uid_str. Agreed these are pre-existing and that this PR adds no new dead code; the attribute is the repo's existing answer for exactly this.

    Nits, all three taken:

    1. input_monitoring_granted's non-Apple arm is now not(target_os = "macos"), matching with_autorelease_pool in the sibling module and leaving no target unresolved.
    2. revert_to_accessory_on_close drops the parameter attribute for a single let _ = (app, win); in the not(macos) block.
    3. Sizing comment corrected — you're right that inner_size is the client area, so the webview stays 1000x680 and the card still centres; only the outer window grows by the title-bar height. No shift; the old wording described one that can't happen.

    Now verified rather than asserted — step-level, not the job tick (job 88308625400):

    Run cargo check -p meridian-tray --all-targets
       Compiling meridian-tray v0.1.0 (D:\a\meridian\meridian\tray\src-tauri)
        Finished `dev` profile in 1m 09s
    

    check tray conclusion: success. The tray compiles on Windows.

    On dropping continue-on-error: agreed in principle, and it's the only thing that stops the next round regressing silently the same way. Leaving it to you as a separate call since it changes what the gate blocks on, and the standing comment in ci.yml argues for non-blocking on the grounds that tray breakage may be latent and unrelated to Windows. Happy to do it here or in a follow-up - say which.

     
  • Anonymous

    Anonymous - 2026-07-20

    Ticket changed by: Akarsh-Hegde

    • status: open --> closed
     

Log in to post a comment.