fix(macos): release closed child window engines (#1639)

This commit is contained in:
Levi authored and GitHub committed 2026-11-02 23:52:11 +08:00
1 parent cd19772099
commit b0d45226d7
3 files changed
+120 -1

No files matched your search

@@ -52,6 +52,7 @@ class AppWindowCapabilityHost {
CapabilityRegistry? _registry;
AppWindowAppearance _appearance = const AppWindowAppearance.defaults();
final Map<String, WindowController> _subscribers = {};
StreamSubscription<void>? _windowsChanged;
bool get started => _registry != null;
@@ -59,14 +60,33 @@ class AppWindowCapabilityHost {
if (_registry != null) return;
_registry = registry;
await _hostChannel.setMethodCallHandler(_handleCall);
_windowsChanged = onWindowsChanged.listen((_) => unawaited(_removeClosedSubscribers()));
}
Future<void> stop() async {
_registry = null;
await _windowsChanged?.cancel();
_windowsChanged = null;
_subscribers.clear();
await _hostChannel.setMethodCallHandler(null);
}
Future<void> _removeClosedSubscribers() async {
// Engine shutdown does not run Widget.dispose, so a closed child cannot
// always send window.unsubscribe itself.
final registry = _registry;
final candidates = _subscribers.keys.toSet();
if (registry == null || candidates.isEmpty) return;
try {
final windows = await WindowController.getAll();
if (!identical(registry, _registry)) return;
final openIds = windows.map((window) => window.windowId).toSet();
_subscribers.removeWhere((id, _) => candidates.contains(id) && !openIds.contains(id));
} catch (_) {
// The native window registry can already be gone during app shutdown.
}
}
void updateAppearance(AppWindowAppearance appearance) {
if (_appearance == appearance) return;
_appearance = appearance;