Files
gopeed/ui/flutter/macos/Runner/MainFlutterWindow.swift

60 lines
2.3 KiB
Swift

import Cocoa
import FlutterMacOS
import desktop_multi_window
import window_manager
class MainFlutterWindow: NSWindow {
private var childWindowCloseObservers: [ObjectIdentifier: NSObjectProtocol] = [:]
override func awakeFromNib() {
let flutterViewController = FlutterViewController()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
RegisterGeneratedPlugins(registry: flutterViewController)
FlutterMultiWindowPlugin.setOnWindowCreatedCallback { [weak self] controller in
RegisterGeneratedPlugins(registry: controller)
self?.releaseChildEngineOnClose(controller)
}
super.awakeFromNib()
}
// desktop_multi_window removes closed windows from its registry, but plugin
// channels can still retain the window/controller/engine cycle. NSWindow.close
// alone therefore leaves each child Dart isolate and its heap running.
private func releaseChildEngineOnClose(_ controller: FlutterViewController) {
guard let window = controller.view.window else { return }
let key = ObjectIdentifier(window)
childWindowCloseObservers[key] = NotificationCenter.default.addObserver(
forName: NSWindow.willCloseNotification, object: window, queue: .main
) { [weak self, weak controller, weak window] _ in
if let observer = self?.childWindowCloseObservers.removeValue(forKey: key) {
NotificationCenter.default.removeObserver(observer)
}
// Let close notifications and the plugin's registry removal finish before
// tearing down the engine that delivered the close request.
DispatchQueue.main.async { [weak controller, weak window] in
// window_manager's onEvent closure retains its plugin, which retains
// the manager and NSWindow even after the engine has stopped.
(window?.delegate as? WindowManager)?.onEvent = nil
window?.delegate = nil
controller?.engine.shutDownEngine()
window?.contentViewController = nil
}
}
}
deinit {
for observer in childWindowCloseObservers.values {
NotificationCenter.default.removeObserver(observer)
}
}
override public func order(_ place: NSWindow.OrderingMode, relativeTo otherWin: Int) {
super.order(place, relativeTo: otherWin)
hiddenWindowAtLaunch()
}
}