Files
desktop-plugin/macos/Runner/MainFlutterWindow.swift
dzc a7cc69bb92 fix(mac): 点红点直接退出——真凶是模板 AppDelegate 的关窗即退开关
三层排查实锤(lldb 运行时取证):
1. 红点按钮真实 action 是 AppKit 私有 selector `_close:`(并非文档所称
   performClose:),内部直接关窗,绕过 performClose/close 重写与 delegate 拦截
2. flutter create 模板的 AppDelegate 自带
   applicationShouldTerminateAfterLastWindowClosed 返回 true——最后一个窗口
   关闭即 NSApp.terminate,这是"点红点进程退出、托盘随进程消失"的根因
3. 修复:改为返回 false。窗口即便被真关闭,进程/HTTP 服务/托盘也保持运行,
   托盘点击 makeKeyAndOrderFront 恢复窗口(releasedWhenClosed=NO,窗口对象在)

验证(红点 action 原样重放 `_close:`):窗口关闭后进程存活、服务在线、
托盘状态栏窗口存在、makeKeyAndOrderFront 可恢复窗口。
保留 MainFlutterWindow 的 performClose/close 重写(Cmd+W 等正常路径只隐藏
不关闭,体验更好)。
2026-09-21 13:34:46 +08:00

32 lines
1.2 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
self.minSize = NSSize(width: 860, height: 560)
RegisterGeneratedPlugins(registry: flutterViewController)
super.awakeFromNib()
}
/// 关窗不退出(最终拦截点)。实测(macOS 15)红点按钮的真实 action 是 AppKit
/// 私有 selector `_close:`(并非文档所称的 performClose:),其内部直接调 close(),
/// 会绕过 performClose/windowShouldClose/delegate 拦截——因此必须在 close() 上拦。
/// 此处 orderOut 隐藏窗口,进程/HTTP 服务/托盘保持运行;NSApp.terminate 流程中
/// 的窗口关闭不受影响(进程照常结束),真正退出只走托盘菜单。
override func close() {
print("MainFlutterWindow: close() 拦截,窗口隐藏到托盘(服务继续运行)")
orderOut(nil)
}
/// Cmd+W / 菜单"关闭窗口"走 performClose:,同样只隐藏不关闭。
override func performClose(_ sender: Any?) {
orderOut(sender)
}
}