From fb06e629c2b0e9c33e28eef472c1f0f0e431c234 Mon Sep 17 00:00:00 2001 From: dzc <2388224167@qq.com> Date: Mon, 21 Sep 2026 13:20:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(mac):=20=E7=82=B9=E5=87=BB=E7=BA=A2?= =?UTF-8?q?=E7=82=B9=E7=9B=B4=E6=8E=A5=E9=80=80=E5=87=BA=E8=80=8C=E9=9D=9E?= =?UTF-8?q?=E6=9C=80=E5=B0=8F=E5=8C=96=E5=88=B0=E6=89=98=E7=9B=98=E2=80=94?= =?UTF-8?q?=E2=80=94=E5=8E=9F=E7=94=9F=E4=BE=A7=E9=87=8D=E5=86=99=20perfor?= =?UTF-8?q?mClose=20=E5=8F=8C=E4=BF=9D=E9=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:window_manager 的 setPreventClose 依赖把 WindowManager 挂为 NSWindowDelegate 来拦 windowShouldClose,在 xib 创建的窗口上该 delegate 挂载时机不可靠(会被 xib 原有 delegate/AppKit 流程绕过),preventClose 形同虚设,红点直接关窗。 修复:MainFlutterWindow 重写 performClose(_:)(红点与 Cmd+W 的 target-action 必经之路),直接 orderOut 隐藏窗口,进程/HTTP 服务/托盘保持运行;不依赖 window_manager 的 delegate 是否挂上。真正退出只走托盘菜单 → window_manager.destroy() → NSApp.terminate(不经过 performClose,无冲突); Cmd+Q 系统标准退出保留。window_manager 的 onWindowClose→hide 路径保留 (若 delegate 生效则幂等)。 --- macos/Runner/MainFlutterWindow.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift index cc3974e..2af11c4 100644 --- a/macos/Runner/MainFlutterWindow.swift +++ b/macos/Runner/MainFlutterWindow.swift @@ -13,4 +13,14 @@ class MainFlutterWindow: NSWindow { super.awakeFromNib() } + + /// 关窗不退出(双保险):红点按钮与 Cmd+W 的 target 都是 performClose:, + /// 这里直接 orderOut 隐藏窗口,进程/服务/托盘保持运行; + /// 真正退出只走托盘菜单 → window_manager.destroy() → NSApp.terminate(不经过此处)。 + /// window_manager 的 setPreventClose/delegate 拦截在 xib 窗口上挂载时机不可靠, + /// 不能作为关窗拦截的唯一依赖(实测会被绕过导致整窗关闭)。 + override func performClose(_ sender: Any?) { + print("MainFlutterWindow: performClose 拦截,窗口隐藏到托盘(服务继续运行)") + orderOut(sender) + } }