diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index 56419b18a661c..f354a23675952 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -847,15 +847,9 @@ - (FlutterCompositor*)createFlutterCompositor { void* user_data // ) { return true; }; - _compositor.present_layers_callback = [](const FlutterLayer** layers, // - size_t layers_count, // - void* user_data // - ) { - // TODO(dkwingsmt): This callback only supports single-view, therefore it - // only operates on the implicit view. To support multi-view, we need a new - // callback that also receives a view ID. - return reinterpret_cast(user_data)->Present(kFlutterImplicitViewId, - layers, layers_count); + _compositor.present_view_callback = [](const FlutterPresentViewInfo* info) { + return reinterpret_cast(info->user_data) + ->Present(info->view_id, info->layers, info->layers_count); }; _compositor.avoid_backing_store_cache = true; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm index 209903d8fa549..e181199dfe839 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm @@ -535,7 +535,56 @@ @implementation MockableFlutterEngine // TODO(gw280): add support for screenshot tests in this test harness [engine shutDownEngine]; -} // namespace flutter::testing +} + +TEST_F(FlutterEngineTest, CompositorIgnoresUnknownView) { + FlutterEngine* engine = GetFlutterEngine(); + auto original_init = engine.embedderAPI.Initialize; + ::FlutterCompositor compositor; + engine.embedderAPI.Initialize = MOCK_ENGINE_PROC( + Initialize, ([&compositor, &original_init]( + size_t version, const FlutterRendererConfig* config, + const FlutterProjectArgs* args, void* user_data, auto engine_out) { + compositor = *args->compositor; + return original_init(version, config, args, user_data, engine_out); + })); + + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + [viewController loadView]; + + EXPECT_TRUE([engine runWithEntrypoint:@"empty"]); + + FlutterBackingStoreConfig config = { + .struct_size = sizeof(FlutterBackingStoreConfig), + .size = FlutterSize{10, 10}, + }; + FlutterBackingStore backing_store = {}; + EXPECT_NE(compositor.create_backing_store_callback, nullptr); + EXPECT_TRUE( + compositor.create_backing_store_callback(&config, &backing_store, compositor.user_data)); + + FlutterLayer layer{ + .type = kFlutterLayerContentTypeBackingStore, + .backing_store = &backing_store, + }; + std::vector layers = {&layer}; + + FlutterPresentViewInfo info = { + .struct_size = sizeof(FlutterPresentViewInfo), + .view_id = 123, + .layers = const_cast(layers.data()), + .layers_count = 1, + .user_data = compositor.user_data, + }; + EXPECT_NE(compositor.present_view_callback, nullptr); + EXPECT_FALSE(compositor.present_view_callback(&info)); + EXPECT_TRUE(compositor.collect_backing_store_callback(&backing_store, compositor.user_data)); + + (void)viewController; + [engine shutDownEngine]; +} TEST_F(FlutterEngineTest, DartEntrypointArguments) { NSString* fixtures = @(flutter::testing::GetFixturesPath()); diff --git a/shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart b/shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart index 835588ff354ac..7a9a69db73de7 100644 --- a/shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart +++ b/shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart @@ -12,6 +12,10 @@ external void signalNativeTest(); void main() { } +@pragma('vm:entry-point') +void empty() { +} + /// Notifies the test of a string value. /// /// This is used to notify the native side of the test of a string value from