diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index 8ba35a05761..322c4f496e2 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -152,14 +152,6 @@ constexpr char kTextPlainFormat[] = "text/plain"; */ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message; -/** - * Invoked right before the engine is restarted. - * - * This should reset states to as if the application has just started. It - * usually indicates a hot restart (Shift-R in Flutter CLI.) - */ -- (void)engineCallbackOnPreEngineRestart; - /** * Requests that the task be posted back the to the Flutter engine at the target time. The target * time is in the clock used by the Flutter engine. @@ -1289,6 +1281,7 @@ static void SetThreadPriority(FlutterThreadPriority priority) { while ((nextViewController = [viewControllerEnumerator nextObject])) { [nextViewController onPreEngineRestart]; } + [_windowController closeAllWindows]; [_platformViewController reset]; _keyboardManager = [[FlutterKeyboardManager alloc] initWithDelegate:self]; } diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h index 7e562522f61..cca50663008 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h @@ -268,6 +268,13 @@ typedef NS_ENUM(NSInteger, FlutterAppExitResponse) { */ + (nullable FlutterEngine*)engineForIdentifier:(int64_t)identifier; +/** + * Invoked right before the engine is restarted. + * + * This should reset states to as if the application has just started. It + * usually indicates a hot restart (Shift-R in Flutter CLI.) + */ +- (void)engineCallbackOnPreEngineRestart; @end NS_ASSUME_NONNULL_END diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowController.h b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowController.h index 4fe8998aeb1..d52553c645f 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowController.h +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowController.h @@ -16,10 +16,6 @@ @property(nonatomic, weak) FlutterEngine* engine; -@end - -@interface FlutterWindowController (Testing) - - (void)closeAllWindows; @end diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowControllerTest.mm b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowControllerTest.mm index f991ea158b1..4889bf2508e 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowControllerTest.mm +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowControllerTest.mm @@ -202,4 +202,43 @@ TEST_F(FlutterWindowControllerTest, WindowStates) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false); EXPECT_EQ(window.miniaturized, YES); } + +TEST_F(FlutterWindowControllerTest, ClosesAllWindowsOnEngineRestart) { + FlutterWindowCreationRequest request{ + .has_size = true, + .size = {.width = 800, .height = 600}, + .on_should_close = [] {}, + .on_will_close = [] {}, + .notify_listeners = [] {}, + }; + + FlutterEngine* engine = GetFlutterEngine(); + int64_t engine_id = reinterpret_cast(engine); + + IsolateScope isolate_scope(isolate()); + + // Create multiple windows + int64_t handle1 = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request); + int64_t handle2 = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request); + int64_t handle3 = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request); + + // Verify windows are created + FlutterViewController* viewController1 = [engine viewControllerForIdentifier:handle1]; + FlutterViewController* viewController2 = [engine viewControllerForIdentifier:handle2]; + FlutterViewController* viewController3 = [engine viewControllerForIdentifier:handle3]; + EXPECT_NE(viewController1, nil); + EXPECT_NE(viewController2, nil); + EXPECT_NE(viewController3, nil); + + // Close all windows on engine restart + [engine engineCallbackOnPreEngineRestart]; + + // Verify all windows are closed and view controllers are disposed + viewController1 = [engine viewControllerForIdentifier:handle1]; + viewController2 = [engine viewControllerForIdentifier:handle2]; + viewController3 = [engine viewControllerForIdentifier:handle3]; + EXPECT_EQ(viewController1, nil); + EXPECT_EQ(viewController2, nil); + EXPECT_EQ(viewController3, nil); +} } // namespace flutter::testing