Skip to content

fix(tray): 托盘恢复主窗口按系统版本选择激活选择器,修复 macOS 13 及更早系统崩溃 - #238

Merged
feigeCode merged 1 commit into
mainfrom
fix/tray-restore-macos-selector
Sep 19, 2026
Merged

feigeCode merged 1 commit into
mainfrom
fix/tray-restore-macos-selector

Conversation

@feigeCode

Copy link
Copy Markdown
Owner

Description

Fixes a reproducible crash when restoring the main window from the system tray on macOS 13 and earlier.

Root cause. main/src/window_visibility.rs called NSApplication.activate() unconditionally. Per Apple's AppKit Release Notes for macOS 14, activate(ignoringOtherApps:) is deprecated in macOS 14 and a new activate method was added in that release. Info.plist declares LSMinimumSystemVersion = 12.0, so on macOS 12/13 the selector does not exist and the message goes through doesNotRecognizeSelector:std::terminateSIGABRT.

User report. X86-64 / macOS 12.7.6 (MacBookPro11,4) / navop 0.18.3, uncaught Objective-C exception EXC_CRASH (SIGABRT) with frames __exceptionPreprocessobjc_exception_throw___forwarding____CF_forwarding_prep_0. Reproducible: open an SSH terminal window → minimize to tray → restore. The regression was introduced with the tray feature in 0.18.3, and this call site is the only place in the repository using that selector.

Fix. Dispatch on runtime selector availability instead of hard-coding the new API:

if app.respondsToSelector(sel!(activate)) {
    app.activate();          // macOS 14+
} else {
    activate_legacy(app);    // macOS 13 and earlier
}

The legacy path calls activateIgnoringOtherApps: and is isolated in its own #[allow(deprecated)] function so the deprecated API is confined to one call site. Both branches run on systems that natively support them.

No UI change, so no screenshots are attached.

How to Test

  • cargo check -p main — passes.
  • cargo test -p main --bin navop window_activation1 passed; 0 failed. The new source-level guard test asserts that availability is checked, that the legacy fallback still exists, that the new selector is only reached after the check, and that callers do not bypass the helper.
  • Not verified on a real macOS 12/13 machine — the author is on macOS 27. A macOS 12/13 machine should verify the reported path: open an SSH terminal window → minimize to tray → restore the main window. Previously this crashed every time.

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate.
  • Passed cargo run for story tests related to the changes.
  • Tested macOS, Windows and Linux platforms performance (if the change is platform-specific)

`NSApplication::activate()` 是 macOS 14 才引入的选择器(Apple《AppKit Release Notes
for macOS 14》:`activate(ignoringOtherApps:)` 在 14 废弃,同时新增 `activate`),而
`Info.plist` 声明的最低支持版本是 macOS 12.0。旧系统上该选择器不存在,消息转发失败
(`doesNotRecognizeSelector:`)→ `std::terminate` → SIGABRT。

- 崩溃报告:x86_64 / macOS 12.7.6(MacBookPro11,4)/ navop 0.18.3;未捕获 ObjC 异常
  `EXC_CRASH (SIGABRT)`,帧序 `__exceptionPreprocess` → `objc_exception_throw` →
  `___forwarding___` → `_CF_forwarding_prep_0`
- 必现路径:SSH 终端窗口最小化到托盘后恢复主窗口
- 修复:`activate_app` 用 `respondsToSelector(sel!(activate))` 运行时按系统版本分派,
  命中走 `activate()`,否则回退 `activateIgnoringOtherApps:`;回退收进 `activate_legacy`
  并 `#[allow(deprecated)]`,两条路径各自都在原生支持的系统上
- 新增源码级守卫测试:禁止调用方绕过 helper 直接调新选择器,也禁止删掉旧系统回退
- 影响面仅 `main/src/window_visibility.rs`;gpui 的 `activate_window()` 只做
  `makeKeyAndOrderFront:`,无同类越线
@feigeCode
feigeCode merged commit f47b59c into main Sep 19, 2026
7 checks passed
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