From a89c2ae2a4cd604eab9e615f90cc622bea71ba2c Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 12 Sep 2024 09:25:52 +1200 Subject: [PATCH] Use a signal for the pre-engine restart event (flutter/engine#55063) With multiple FlViews a callback doesn't scale. --- .../flutter/shell/platform/linux/fl_engine.cc | 42 ++++--------------- .../shell/platform/linux/fl_engine_private.h | 26 ------------ .../shell/platform/linux/fl_engine_test.cc | 16 ++----- .../flutter/shell/platform/linux/fl_view.cc | 20 +++++---- 4 files changed, 25 insertions(+), 79 deletions(-) diff --git a/engine/src/flutter/shell/platform/linux/fl_engine.cc b/engine/src/flutter/shell/platform/linux/fl_engine.cc index 9d5022acc9..77112fd5e2 100644 --- a/engine/src/flutter/shell/platform/linux/fl_engine.cc +++ b/engine/src/flutter/shell/platform/linux/fl_engine.cc @@ -62,11 +62,6 @@ struct _FlEngine { FlEngineUpdateSemanticsHandler update_semantics_handler; gpointer update_semantics_handler_data; GDestroyNotify update_semantics_handler_destroy_notify; - - // Function to call right before the engine is restarted. - FlEngineOnPreEngineRestartHandler on_pre_engine_restart_handler; - gpointer on_pre_engine_restart_handler_data; - GDestroyNotify on_pre_engine_restart_handler_destroy_notify; }; G_DEFINE_QUARK(fl_engine_error_quark, fl_engine_error) @@ -74,6 +69,10 @@ G_DEFINE_QUARK(fl_engine_error_quark, fl_engine_error) static void fl_engine_plugin_registry_iface_init( FlPluginRegistryInterface* iface); +enum { kSignalOnPreEngineRestart, kSignalLastSignal }; + +static guint fl_engine_signals[kSignalLastSignal]; + G_DEFINE_TYPE_WITH_CODE( FlEngine, fl_engine, @@ -343,10 +342,7 @@ static void fl_engine_update_semantics_cb(const FlutterSemanticsUpdate2* update, static void fl_engine_on_pre_engine_restart_cb(void* user_data) { FlEngine* self = FL_ENGINE(user_data); - if (self->on_pre_engine_restart_handler != nullptr) { - self->on_pre_engine_restart_handler( - self, self->on_pre_engine_restart_handler_data); - } + g_signal_emit(self, fl_engine_signals[kSignalOnPreEngineRestart], 0); } // Called when a response to a sent platform message is received from the @@ -427,13 +423,6 @@ static void fl_engine_dispose(GObject* object) { self->update_semantics_handler_data = nullptr; self->update_semantics_handler_destroy_notify = nullptr; - if (self->on_pre_engine_restart_handler_destroy_notify) { - self->on_pre_engine_restart_handler_destroy_notify( - self->on_pre_engine_restart_handler_data); - } - self->on_pre_engine_restart_handler_data = nullptr; - self->on_pre_engine_restart_handler_destroy_notify = nullptr; - G_OBJECT_CLASS(fl_engine_parent_class)->dispose(object); } @@ -448,6 +437,10 @@ static void fl_engine_class_init(FlEngineClass* klass) { fl_binary_messenger_get_type(), static_cast(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS))); + + fl_engine_signals[kSignalOnPreEngineRestart] = g_signal_new( + "on-pre-engine-restart", fl_engine_get_type(), G_SIGNAL_RUN_LAST, 0, + nullptr, nullptr, nullptr, G_TYPE_NONE, 0); } static void fl_engine_init(FlEngine* self) { @@ -735,23 +728,6 @@ void fl_engine_set_update_semantics_handler( self->update_semantics_handler_destroy_notify = destroy_notify; } -void fl_engine_set_on_pre_engine_restart_handler( - FlEngine* self, - FlEngineOnPreEngineRestartHandler handler, - gpointer user_data, - GDestroyNotify destroy_notify) { - g_return_if_fail(FL_IS_ENGINE(self)); - - if (self->on_pre_engine_restart_handler_destroy_notify) { - self->on_pre_engine_restart_handler_destroy_notify( - self->on_pre_engine_restart_handler_data); - } - - self->on_pre_engine_restart_handler = handler; - self->on_pre_engine_restart_handler_data = user_data; - self->on_pre_engine_restart_handler_destroy_notify = destroy_notify; -} - // Note: This function can be called from any thread. gboolean fl_engine_send_platform_message_response( FlEngine* self, diff --git a/engine/src/flutter/shell/platform/linux/fl_engine_private.h b/engine/src/flutter/shell/platform/linux/fl_engine_private.h index 9c3ef70c26..b507de96e2 100644 --- a/engine/src/flutter/shell/platform/linux/fl_engine_private.h +++ b/engine/src/flutter/shell/platform/linux/fl_engine_private.h @@ -60,16 +60,6 @@ typedef void (*FlEngineUpdateSemanticsHandler)( const FlutterSemanticsUpdate2* update, gpointer user_data); -/** - * FlEngineOnPreEngineRestartHandler: - * @engine: an #FlEngine. - * @user_data: (closure): data provided when registering this handler. - * - * Function called right before the engine is restarted. - */ -typedef void (*FlEngineOnPreEngineRestartHandler)(FlEngine* engine, - gpointer user_data); - /** * fl_engine_new_with_renderer: * @project: an #FlDartProject. @@ -218,22 +208,6 @@ void fl_engine_set_update_semantics_handler( gpointer user_data, GDestroyNotify destroy_notify); -/** - * fl_engine_set_on_pre_engine_restart_handler: - * @engine: an #FlEngine. - * @handler: function to call when the engine is restarted. - * @user_data: (closure): user data to pass to @handler. - * @destroy_notify: (allow-none): a function which gets called to free - * @user_data, or %NULL. - * - * Registers the function called right before the engine is restarted. - */ -void fl_engine_set_on_pre_engine_restart_handler( - FlEngine* engine, - FlEngineOnPreEngineRestartHandler handler, - gpointer user_data, - GDestroyNotify destroy_notify); - /** * fl_engine_send_window_metrics_event: * @engine: an #FlEngine. diff --git a/engine/src/flutter/shell/platform/linux/fl_engine_test.cc b/engine/src/flutter/shell/platform/linux/fl_engine_test.cc index 4f3fa079e0..6fec47c2a5 100644 --- a/engine/src/flutter/shell/platform/linux/fl_engine_test.cc +++ b/engine/src/flutter/shell/platform/linux/fl_engine_test.cc @@ -275,14 +275,9 @@ void on_pre_engine_restart_cb(FlEngine* engine, gpointer user_data) { *count += 1; } -void on_pre_engine_restart_destroy_notify(gpointer user_data) { - int* count = reinterpret_cast(user_data); - *count += 10; -} - // Checks restarting the engine invokes the correct callback. TEST(FlEngineTest, OnPreEngineRestart) { - FlEngine* engine = make_mock_engine(); + g_autoptr(FlEngine) engine = make_mock_engine(); FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine); OnPreEngineRestartCallback callback; @@ -317,16 +312,11 @@ TEST(FlEngineTest, OnPreEngineRestart) { // // * When the engine restarts, count += 1; // * When the engine is freed, count += 10. - fl_engine_set_on_pre_engine_restart_handler( - engine, on_pre_engine_restart_cb, &count, - on_pre_engine_restart_destroy_notify); + g_signal_connect(engine, "on-pre-engine-restart", + G_CALLBACK(on_pre_engine_restart_cb), &count); callback(callback_user_data); EXPECT_EQ(count, 1); - - // Disposal should call the destroy notify. - g_object_unref(engine); - EXPECT_EQ(count, 11); } TEST(FlEngineTest, DartEntrypointArgs) { diff --git a/engine/src/flutter/shell/platform/linux/fl_view.cc b/engine/src/flutter/shell/platform/linux/fl_view.cc index 542f3f97c1..3dacc776f0 100644 --- a/engine/src/flutter/shell/platform/linux/fl_view.cc +++ b/engine/src/flutter/shell/platform/linux/fl_view.cc @@ -40,6 +40,9 @@ struct _FlView { // Engine this view is showing. FlEngine* engine; + // Handler for engine restart signal. + guint on_pre_engine_restart_handler; + // ID for this view. FlutterViewId view_id; @@ -274,9 +277,7 @@ static void update_semantics_cb(FlEngine* engine, // This method should reset states to be as if the engine had just been started, // which usually indicates the user has requested a hot restart (Shift-R in the // Flutter CLI.) -static void on_pre_engine_restart_cb(FlEngine* engine, gpointer user_data) { - FlView* self = FL_VIEW(user_data); - +static void on_pre_engine_restart_cb(FlView* self) { init_keyboard(self); init_scrolling(self); } @@ -652,8 +653,12 @@ static void fl_view_dispose(GObject* object) { if (self->engine != nullptr) { fl_engine_set_update_semantics_handler(self->engine, nullptr, nullptr, nullptr); - fl_engine_set_on_pre_engine_restart_handler(self->engine, nullptr, nullptr, - nullptr); + } + + if (self->on_pre_engine_restart_handler != 0) { + g_signal_handler_disconnect(self->engine, + self->on_pre_engine_restart_handler); + self->on_pre_engine_restart_handler = 0; } g_clear_object(&self->engine); @@ -784,8 +789,9 @@ G_MODULE_EXPORT FlView* fl_view_new_for_engine(FlEngine* engine) { fl_engine_set_update_semantics_handler(self->engine, update_semantics_cb, self, nullptr); - fl_engine_set_on_pre_engine_restart_handler( - self->engine, on_pre_engine_restart_cb, self, nullptr); + self->on_pre_engine_restart_handler = + g_signal_connect_swapped(engine, "on-pre-engine-restart", + G_CALLBACK(on_pre_engine_restart_cb), self); return self; }