13 #include "flutter/common/constants.h"
16 #include "flutter/shell/platform/embedder/embedder.h"
75 FlPluginRegistryInterface* iface);
81 G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(),
92 gchar* l = g_strdup(locale);
95 gchar* match = strrchr(l,
'@');
96 if (match !=
nullptr) {
97 if (modifier !=
nullptr) {
98 *modifier = g_strdup(match + 1);
101 }
else if (modifier !=
nullptr) {
105 match = strrchr(l,
'.');
106 if (match !=
nullptr) {
107 if (codeset !=
nullptr) {
108 *codeset = g_strdup(match + 1);
111 }
else if (codeset !=
nullptr) {
115 match = strrchr(l,
'_');
116 if (match !=
nullptr) {
117 if (territory !=
nullptr) {
118 *territory = g_strdup(match + 1);
121 }
else if (territory !=
nullptr) {
122 *territory =
nullptr;
125 if (language !=
nullptr) {
137 g_autoptr(GBytes) message =
140 if (message ==
nullptr) {
146 nullptr,
nullptr,
nullptr);
151 const gchar*
const* languages = g_get_language_names();
152 g_autoptr(GPtrArray) locales_array = g_ptr_array_new_with_free_func(g_free);
154 g_autoptr(GPtrArray) locale_strings = g_ptr_array_new_with_free_func(g_free);
155 for (
int i = 0; languages[
i] !=
nullptr;
i++) {
156 gchar *language, *territory;
157 parse_locale(languages[
i], &language, &territory,
nullptr,
nullptr);
158 if (language !=
nullptr) {
159 g_ptr_array_add(locale_strings, language);
161 if (territory !=
nullptr) {
162 g_ptr_array_add(locale_strings, territory);
165 FlutterLocale* locale =
166 static_cast<FlutterLocale*
>(g_malloc0(
sizeof(FlutterLocale)));
167 g_ptr_array_add(locales_array, locale);
168 locale->struct_size =
sizeof(FlutterLocale);
169 locale->language_code = language;
170 locale->country_code = territory;
171 locale->script_code =
nullptr;
172 locale->variant_code =
nullptr;
174 FlutterLocale** locales =
175 reinterpret_cast<FlutterLocale**
>(locales_array->pdata);
176 FlutterEngineResult
result =
self->embedder_api.UpdateLocales(
177 self->engine,
const_cast<const FlutterLocale**
>(locales),
180 g_warning(
"Failed to set up Flutter locales");
186 const FlutterBackingStoreConfig* config,
187 FlutterBackingStore* backing_store_out,
189 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
196 const FlutterBackingStore* renderer,
198 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
206 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
214 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
219 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
225 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
231 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
242 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
253 FlutterOpenGLTexture* opengl_texture) {
254 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
255 if (!self->texture_registrar) {
261 if (texture ==
nullptr) {
262 g_warning(
"Unable to find texture %" G_GINT64_FORMAT,
texture_id);
267 g_autoptr(GError)
error =
nullptr;
268 if (FL_IS_TEXTURE_GL(texture)) {
270 opengl_texture, &
error);
271 }
else if (FL_IS_PIXEL_BUFFER_TEXTURE(texture)) {
276 g_warning(
"Unsupported texture type %" G_GINT64_FORMAT,
texture_id);
281 g_warning(
"%s",
error->message);
290 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
291 return self->thread == g_thread_self();
296 uint64_t target_time_nanos,
298 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
308 gboolean handled = FALSE;
309 if (self->platform_message_handler !=
nullptr) {
310 g_autoptr(GBytes) data =
311 g_bytes_new(message->message, message->message_size);
312 handled =
self->platform_message_handler(
313 self, message->channel, data, message->response_handle,
314 self->platform_message_handler_data);
328 if (self->update_semantics_handler !=
nullptr) {
329 self->update_semantics_handler(
self, update,
330 self->update_semantics_handler_data);
342 if (self->on_pre_engine_restart_handler !=
nullptr) {
343 self->on_pre_engine_restart_handler(
344 self, self->on_pre_engine_restart_handler_data);
353 g_autoptr(GTask) task = G_TASK(
user_data);
354 g_task_return_pointer(task, g_bytes_new(data, data_length),
355 reinterpret_cast<GDestroyNotify
>(g_bytes_unref));
360 FlPluginRegistry* registry,
362 FlEngine*
self = FL_ENGINE(registry);
365 self->texture_registrar);
369 FlPluginRegistryInterface* iface) {
377 FlEngine*
self = FL_ENGINE(
object);
379 case kPropBinaryMessenger:
380 g_set_object(&self->binary_messenger,
381 FL_BINARY_MESSENGER(g_value_get_object(
value)));
384 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object,
prop_id,
pspec);
390 FlEngine*
self = FL_ENGINE(
object);
392 if (self->engine !=
nullptr) {
393 self->embedder_api.Shutdown(self->engine);
394 self->engine =
nullptr;
397 if (self->aot_data !=
nullptr) {
398 self->embedder_api.CollectAOTData(self->aot_data);
399 self->aot_data =
nullptr;
405 g_clear_object(&self->project);
406 g_clear_object(&self->renderer);
407 g_clear_object(&self->texture_registrar);
408 g_clear_object(&self->binary_messenger);
409 g_clear_object(&self->settings_plugin);
410 g_clear_object(&self->task_runner);
412 if (self->platform_message_handler_destroy_notify) {
413 self->platform_message_handler_destroy_notify(
414 self->platform_message_handler_data);
416 self->platform_message_handler_data =
nullptr;
417 self->platform_message_handler_destroy_notify =
nullptr;
419 if (self->update_semantics_handler_destroy_notify) {
420 self->update_semantics_handler_destroy_notify(
421 self->update_semantics_handler_data);
423 self->update_semantics_handler_data =
nullptr;
424 self->update_semantics_handler_destroy_notify =
nullptr;
426 if (self->on_pre_engine_restart_handler_destroy_notify) {
427 self->on_pre_engine_restart_handler_destroy_notify(
428 self->on_pre_engine_restart_handler_data);
430 self->on_pre_engine_restart_handler_data =
nullptr;
431 self->on_pre_engine_restart_handler_destroy_notify =
nullptr;
433 G_OBJECT_CLASS(fl_engine_parent_class)->dispose(
object);
440 g_object_class_install_property(
441 G_OBJECT_CLASS(klass), kPropBinaryMessenger,
443 "binary-messenger",
"messenger",
"Binary messenger",
444 fl_binary_messenger_get_type(),
445 static_cast<GParamFlags
>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
446 G_PARAM_STATIC_STRINGS)));
450 self->thread = g_thread_self();
452 self->embedder_api.struct_size =
sizeof(FlutterEngineProcTable);
453 FlutterEngineGetProcAddresses(&self->embedder_api);
459 g_return_val_if_fail(FL_IS_DART_PROJECT(project),
nullptr);
460 g_return_val_if_fail(FL_IS_RENDERER(renderer),
nullptr);
462 FlEngine*
self = FL_ENGINE(g_object_new(fl_engine_get_type(),
nullptr));
463 self->project = FL_DART_PROJECT(g_object_ref(project));
464 self->renderer = FL_RENDERER(g_object_ref(renderer));
475 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
479 FlutterRendererConfig config = {};
480 config.type = kOpenGL;
481 config.open_gl.struct_size =
sizeof(FlutterOpenGLRendererConfig);
488 config.open_gl.gl_external_texture_frame_callback =
491 FlutterTaskRunnerDescription platform_task_runner = {};
492 platform_task_runner.struct_size =
sizeof(FlutterTaskRunnerDescription);
493 platform_task_runner.user_data =
self;
494 platform_task_runner.runs_task_on_current_thread_callback =
499 FlutterCustomTaskRunners custom_task_runners = {};
500 custom_task_runners.struct_size =
sizeof(FlutterCustomTaskRunners);
501 custom_task_runners.platform_task_runner = &platform_task_runner;
502 custom_task_runners.render_task_runner = &platform_task_runner;
508 g_ptr_array_insert(command_line_args, 0, g_strdup(
"flutter"));
510 gchar** dart_entrypoint_args =
513 FlutterProjectArgs
args = {};
514 args.struct_size =
sizeof(FlutterProjectArgs);
517 args.command_line_argc = command_line_args->len;
518 args.command_line_argv =
519 reinterpret_cast<const char* const*
>(command_line_args->pdata);
522 args.custom_task_runners = &custom_task_runners;
523 args.shutdown_dart_vm_when_done =
true;
525 args.dart_entrypoint_argc =
526 dart_entrypoint_args !=
nullptr ? g_strv_length(dart_entrypoint_args) : 0;
527 args.dart_entrypoint_argv =
528 reinterpret_cast<const char* const*
>(dart_entrypoint_args);
530 FlutterCompositor compositor = {};
531 compositor.struct_size =
sizeof(FlutterCompositor);
532 compositor.user_data =
self->renderer;
533 compositor.create_backing_store_callback =
535 compositor.collect_backing_store_callback =
538 args.compositor = &compositor;
540 if (self->embedder_api.RunsAOTCompiledDartCode()) {
541 FlutterEngineAOTDataSource source = {};
542 source.type = kFlutterEngineAOTDataSourceTypeElfPath;
544 if (self->embedder_api.CreateAOTData(&source, &self->aot_data) !=
547 "Failed to create AOT data");
550 args.aot_data =
self->aot_data;
553 FlutterEngineResult
result =
self->embedder_api.Initialize(
554 FLUTTER_ENGINE_VERSION, &config, &
args,
self, &self->engine);
557 "Failed to initialize Flutter engine");
561 result =
self->embedder_api.RunInitialized(self->engine);
564 "Failed to run Flutter engine");
574 result =
self->embedder_api.UpdateSemanticsEnabled(self->engine,
TRUE);
576 g_warning(
"Failed to enable accessibility features on Flutter engine");
582 if (refresh_rate <= 0.0) {
585 FlutterEngineDisplay display = {};
586 display.struct_size =
sizeof(FlutterEngineDisplay);
587 display.display_id = 0;
588 display.single_display =
true;
589 display.refresh_rate = refresh_rate;
591 std::vector displays = {display};
592 result =
self->embedder_api.NotifyDisplayUpdate(
593 self->engine, kFlutterEngineDisplaysUpdateTypeStartup, displays.data(),
596 g_warning(
"Failed to notify display update to Flutter engine: %d",
result);
603 return &(
self->embedder_api);
610 GDestroyNotify destroy_notify) {
611 g_return_if_fail(FL_IS_ENGINE(
self));
612 g_return_if_fail(handler !=
nullptr);
614 if (self->platform_message_handler_destroy_notify) {
615 self->platform_message_handler_destroy_notify(
616 self->platform_message_handler_data);
619 self->platform_message_handler = handler;
620 self->platform_message_handler_data =
user_data;
621 self->platform_message_handler_destroy_notify = destroy_notify;
628 GDestroyNotify destroy_notify) {
629 g_return_if_fail(FL_IS_ENGINE(
self));
631 if (self->update_semantics_handler_destroy_notify) {
632 self->update_semantics_handler_destroy_notify(
633 self->update_semantics_handler_data);
636 self->update_semantics_handler = handler;
637 self->update_semantics_handler_data =
user_data;
638 self->update_semantics_handler_destroy_notify = destroy_notify;
645 GDestroyNotify destroy_notify) {
646 g_return_if_fail(FL_IS_ENGINE(
self));
648 if (self->on_pre_engine_restart_handler_destroy_notify) {
649 self->on_pre_engine_restart_handler_destroy_notify(
650 self->on_pre_engine_restart_handler_data);
653 self->on_pre_engine_restart_handler = handler;
654 self->on_pre_engine_restart_handler_data =
user_data;
655 self->on_pre_engine_restart_handler_destroy_notify = destroy_notify;
661 const FlutterPlatformMessageResponseHandle* handle,
664 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
665 g_return_val_if_fail(handle !=
nullptr, FALSE);
667 if (self->engine ==
nullptr) {
669 "No engine to send response to");
673 gsize data_length = 0;
674 const uint8_t* data =
nullptr;
675 if (response !=
nullptr) {
677 static_cast<const uint8_t*
>(g_bytes_get_data(response, &data_length));
679 FlutterEngineResult
result =
self->embedder_api.SendPlatformMessageResponse(
680 self->engine, handle, data, data_length);
684 "Failed to send platform message response");
692 const gchar* channel,
694 GCancellable* cancellable,
697 g_return_if_fail(FL_IS_ENGINE(
self));
699 GTask* task =
nullptr;
700 FlutterPlatformMessageResponseHandle* response_handle =
nullptr;
704 if (self->engine ==
nullptr) {
710 FlutterEngineResult
result =
711 self->embedder_api.PlatformMessageCreateResponseHandle(
717 "Failed to create response handle");
718 g_object_unref(task);
721 }
else if (self->engine ==
nullptr) {
725 FlutterPlatformMessage fl_message = {};
726 fl_message.struct_size =
sizeof(fl_message);
727 fl_message.channel = channel;
730 ?
static_cast<const uint8_t*
>(g_bytes_get_data(message,
nullptr))
732 fl_message.message_size = message !=
nullptr ? g_bytes_get_size(message) : 0;
733 fl_message.response_handle = response_handle;
734 FlutterEngineResult
result =
735 self->embedder_api.SendPlatformMessage(self->engine, &fl_message);
737 if (
result != kSuccess && task !=
nullptr) {
740 "Failed to send platform messages");
741 g_object_unref(task);
744 if (response_handle !=
nullptr) {
745 self->embedder_api.PlatformMessageReleaseResponseHandle(self->engine,
753 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
754 g_return_val_if_fail(g_task_is_valid(
result,
self), FALSE);
756 return static_cast<GBytes*
>(g_task_propagate_pointer(G_TASK(
result),
error));
762 if (visible && focused) {
764 }
else if (visible) {
774 double pixel_ratio) {
775 g_return_if_fail(FL_IS_ENGINE(
self));
777 if (self->engine ==
nullptr) {
781 FlutterWindowMetricsEvent
event = {};
782 event.struct_size =
sizeof(FlutterWindowMetricsEvent);
785 event.pixel_ratio = pixel_ratio;
789 event.view_id = flutter::kFlutterImplicitViewId;
790 self->embedder_api.SendWindowMetricsEvent(self->engine, &
event);
794 FlutterPointerPhase phase,
798 FlutterPointerDeviceKind device_kind,
799 double scroll_delta_x,
800 double scroll_delta_y,
802 g_return_if_fail(FL_IS_ENGINE(
self));
804 if (self->engine ==
nullptr) {
808 FlutterPointerEvent fl_event = {};
809 fl_event.struct_size =
sizeof(fl_event);
810 fl_event.phase = phase;
811 fl_event.timestamp = timestamp;
814 if (scroll_delta_x != 0 || scroll_delta_y != 0) {
815 fl_event.signal_kind = kFlutterPointerSignalKindScroll;
817 fl_event.scroll_delta_x = scroll_delta_x;
818 fl_event.scroll_delta_y = scroll_delta_y;
819 fl_event.device_kind = device_kind;
820 fl_event.buttons = buttons;
825 fl_event.view_id = flutter::kFlutterImplicitViewId;
826 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
833 FlutterPointerPhase phase,
838 g_return_if_fail(FL_IS_ENGINE(
self));
840 if (self->engine ==
nullptr) {
844 FlutterPointerEvent fl_event = {};
845 fl_event.struct_size =
sizeof(fl_event);
846 fl_event.timestamp = timestamp;
849 fl_event.phase = phase;
850 fl_event.pan_x = pan_x;
851 fl_event.pan_y = pan_y;
852 fl_event.scale = scale;
853 fl_event.rotation = rotation;
855 fl_event.device_kind = kFlutterPointerDeviceKindTrackpad;
859 fl_event.view_id = flutter::kFlutterImplicitViewId;
860 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
864 const FlutterKeyEvent*
event,
867 g_return_if_fail(FL_IS_ENGINE(
self));
869 if (self->engine ==
nullptr) {
878 FlutterSemanticsAction action,
880 g_return_if_fail(FL_IS_ENGINE(
self));
882 if (self->engine ==
nullptr) {
886 const uint8_t* action_data =
nullptr;
887 size_t action_data_length = 0;
888 if (data !=
nullptr) {
889 action_data =
static_cast<const uint8_t*
>(
890 g_bytes_get_data(data, &action_data_length));
893 self->embedder_api.DispatchSemanticsAction(self->engine,
id, action,
894 action_data, action_data_length);
899 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
900 return self->embedder_api.MarkExternalTextureFrameAvailable(
906 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
907 return self->embedder_api.RegisterExternalTexture(self->engine,
texture_id) ==
913 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
914 return self->embedder_api.UnregisterExternalTexture(self->engine,
920 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
921 return self->binary_messenger;
925 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
926 return self->task_runner;
930 g_return_if_fail(FL_IS_ENGINE(
self));
931 self->embedder_api.RunTask(self->engine, task);
936 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
937 return self->texture_registrar;
941 g_return_if_fail(FL_IS_ENGINE(
self));
943 if (self->engine ==
nullptr) {
947 self->embedder_api.UpdateAccessibilityFeatures(
948 self->engine,
static_cast<FlutterAccessibilityFeature
>(
flags));
952 GPtrArray* switches = g_ptr_array_new_with_free_func(g_free);
954 g_ptr_array_add(switches, g_strdup(env_switch.c_str()));