13 #include "flutter/common/constants.h"
15 #include "flutter/shell/platform/embedder/embedder.h"
70 FlPluginRegistryInterface* iface);
80 G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(),
91 gchar* l = g_strdup(locale);
94 gchar* match = strrchr(l,
'@');
95 if (match !=
nullptr) {
96 if (modifier !=
nullptr) {
97 *modifier = g_strdup(match + 1);
100 }
else if (modifier !=
nullptr) {
104 match = strrchr(l,
'.');
105 if (match !=
nullptr) {
106 if (codeset !=
nullptr) {
107 *codeset = g_strdup(match + 1);
110 }
else if (codeset !=
nullptr) {
114 match = strrchr(l,
'_');
115 if (match !=
nullptr) {
116 if (territory !=
nullptr) {
117 *territory = g_strdup(match + 1);
120 }
else if (territory !=
nullptr) {
121 *territory =
nullptr;
124 if (language !=
nullptr) {
130 g_autoptr(GTask) task = G_TASK(
result->user_data);
133 g_task_return_boolean(task,
TRUE);
141 g_autoptr(GTask) task = G_TASK(
result->user_data);
144 g_task_return_boolean(task,
TRUE);
152 free(
const_cast<gchar*
>(locale->language_code));
153 free(
const_cast<gchar*
>(locale->country_code));
159 const gchar*
const* languages = g_get_language_names();
160 g_autoptr(GPtrArray) locales_array = g_ptr_array_new_with_free_func(
162 for (
int i = 0; languages[
i] !=
nullptr;
i++) {
163 g_autofree gchar* locale_string = g_strstrip(g_strdup(languages[
i]));
166 if (strcmp(locale_string,
"") == 0) {
170 g_autofree gchar* language =
nullptr;
171 g_autofree gchar* territory =
nullptr;
172 parse_locale(locale_string, &language, &territory,
nullptr,
nullptr);
176 gboolean has_locale = FALSE;
177 for (guint j = 0; !has_locale && j < locales_array->len; j++) {
178 FlutterLocale* locale =
179 reinterpret_cast<FlutterLocale*
>(g_ptr_array_index(locales_array, j));
180 has_locale = g_strcmp0(locale->language_code, language) == 0 &&
181 g_strcmp0(locale->country_code, territory) == 0;
187 FlutterLocale* locale =
188 static_cast<FlutterLocale*
>(g_malloc0(
sizeof(FlutterLocale)));
189 g_ptr_array_add(locales_array, locale);
190 locale->struct_size =
sizeof(FlutterLocale);
191 locale->language_code =
192 reinterpret_cast<const gchar*
>(g_steal_pointer(&language));
193 locale->country_code =
194 reinterpret_cast<const gchar*
>(g_steal_pointer(&territory));
195 locale->script_code =
nullptr;
196 locale->variant_code =
nullptr;
198 FlutterLocale** locales =
199 reinterpret_cast<FlutterLocale**
>(locales_array->pdata);
200 FlutterEngineResult
result =
self->embedder_api.UpdateLocales(
201 self->engine,
const_cast<const FlutterLocale**
>(locales),
204 g_warning(
"Failed to set up Flutter locales");
210 const FlutterBackingStoreConfig* config,
211 FlutterBackingStore* backing_store_out,
213 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
220 const FlutterBackingStore* backing_store,
222 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
229 const FlutterPresentViewInfo* info) {
230 g_return_val_if_fail(FL_IS_RENDERER(info->user_data),
false);
232 info->layers, info->layers_count);
238 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
243 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
249 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
255 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
266 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
277 FlutterOpenGLTexture* opengl_texture) {
278 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
279 if (!self->texture_registrar) {
285 if (texture ==
nullptr) {
286 g_warning(
"Unable to find texture %" G_GINT64_FORMAT,
texture_id);
291 g_autoptr(GError)
error =
nullptr;
292 if (FL_IS_TEXTURE_GL(texture)) {
294 opengl_texture, &
error);
295 }
else if (FL_IS_PIXEL_BUFFER_TEXTURE(texture)) {
300 g_warning(
"Unsupported texture type %" G_GINT64_FORMAT,
texture_id);
305 g_warning(
"%s",
error->message);
314 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
315 return self->thread == g_thread_self();
320 uint64_t target_time_nanos,
322 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
332 gboolean handled = FALSE;
333 if (self->platform_message_handler !=
nullptr) {
334 g_autoptr(GBytes) data =
335 g_bytes_new(message->message, message->message_size);
336 handled =
self->platform_message_handler(
337 self, message->channel, data, message->response_handle,
338 self->platform_message_handler_data);
352 if (self->update_semantics_handler !=
nullptr) {
353 self->update_semantics_handler(
self, update,
354 self->update_semantics_handler_data);
374 g_autoptr(GTask) task = G_TASK(
user_data);
375 g_task_return_pointer(task, g_bytes_new(data, data_length),
376 reinterpret_cast<GDestroyNotify
>(g_bytes_unref));
381 FlPluginRegistry* registry,
383 FlEngine*
self = FL_ENGINE(registry);
386 self->texture_registrar);
390 FlPluginRegistryInterface* iface) {
398 FlEngine*
self = FL_ENGINE(
object);
400 case kPropBinaryMessenger:
401 g_set_object(&self->binary_messenger,
402 FL_BINARY_MESSENGER(g_value_get_object(
value)));
405 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object,
prop_id,
pspec);
411 FlEngine*
self = FL_ENGINE(
object);
413 if (self->engine !=
nullptr) {
414 self->embedder_api.Shutdown(self->engine);
415 self->engine =
nullptr;
418 if (self->aot_data !=
nullptr) {
419 self->embedder_api.CollectAOTData(self->aot_data);
420 self->aot_data =
nullptr;
426 g_clear_object(&self->project);
427 g_clear_object(&self->renderer);
428 g_clear_object(&self->texture_registrar);
429 g_clear_object(&self->binary_messenger);
430 g_clear_object(&self->settings_handler);
431 g_clear_object(&self->task_runner);
433 if (self->platform_message_handler_destroy_notify) {
434 self->platform_message_handler_destroy_notify(
435 self->platform_message_handler_data);
437 self->platform_message_handler_data =
nullptr;
438 self->platform_message_handler_destroy_notify =
nullptr;
440 if (self->update_semantics_handler_destroy_notify) {
441 self->update_semantics_handler_destroy_notify(
442 self->update_semantics_handler_data);
444 self->update_semantics_handler_data =
nullptr;
445 self->update_semantics_handler_destroy_notify =
nullptr;
447 G_OBJECT_CLASS(fl_engine_parent_class)->dispose(
object);
454 g_object_class_install_property(
455 G_OBJECT_CLASS(klass), kPropBinaryMessenger,
457 "binary-messenger",
"messenger",
"Binary messenger",
458 fl_binary_messenger_get_type(),
459 static_cast<GParamFlags
>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
460 G_PARAM_STATIC_STRINGS)));
463 "on-pre-engine-restart", fl_engine_get_type(), G_SIGNAL_RUN_LAST, 0,
464 nullptr,
nullptr,
nullptr, G_TYPE_NONE, 0);
468 self->thread = g_thread_self();
470 self->embedder_api.struct_size =
sizeof(FlutterEngineProcTable);
471 FlutterEngineGetProcAddresses(&self->embedder_api);
474 self->next_view_id = 1;
480 FlRenderer* renderer) {
481 g_return_val_if_fail(FL_IS_DART_PROJECT(project),
nullptr);
482 g_return_val_if_fail(FL_IS_RENDERER(renderer),
nullptr);
484 FlEngine*
self = FL_ENGINE(g_object_new(fl_engine_get_type(),
nullptr));
485 self->project = FL_DART_PROJECT(g_object_ref(project));
486 self->renderer = FL_RENDERER(g_object_ref(renderer));
505 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
506 return self->renderer;
510 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
514 FlutterRendererConfig config = {};
515 config.type = kOpenGL;
516 config.open_gl.struct_size =
sizeof(FlutterOpenGLRendererConfig);
523 config.open_gl.gl_external_texture_frame_callback =
526 FlutterTaskRunnerDescription platform_task_runner = {};
527 platform_task_runner.struct_size =
sizeof(FlutterTaskRunnerDescription);
528 platform_task_runner.user_data =
self;
529 platform_task_runner.runs_task_on_current_thread_callback =
534 FlutterCustomTaskRunners custom_task_runners = {};
535 custom_task_runners.struct_size =
sizeof(FlutterCustomTaskRunners);
536 custom_task_runners.platform_task_runner = &platform_task_runner;
537 custom_task_runners.render_task_runner = &platform_task_runner;
543 g_ptr_array_insert(command_line_args, 0, g_strdup(
"flutter"));
545 gchar** dart_entrypoint_args =
548 FlutterProjectArgs
args = {};
549 args.struct_size =
sizeof(FlutterProjectArgs);
552 args.command_line_argc = command_line_args->len;
553 args.command_line_argv =
554 reinterpret_cast<const char* const*
>(command_line_args->pdata);
557 args.custom_task_runners = &custom_task_runners;
558 args.shutdown_dart_vm_when_done =
true;
560 args.dart_entrypoint_argc =
561 dart_entrypoint_args !=
nullptr ? g_strv_length(dart_entrypoint_args) : 0;
562 args.dart_entrypoint_argv =
563 reinterpret_cast<const char* const*
>(dart_entrypoint_args);
565 FlutterCompositor compositor = {};
566 compositor.struct_size =
sizeof(FlutterCompositor);
567 compositor.user_data =
self->renderer;
568 compositor.create_backing_store_callback =
570 compositor.collect_backing_store_callback =
573 args.compositor = &compositor;
575 if (self->embedder_api.RunsAOTCompiledDartCode()) {
576 FlutterEngineAOTDataSource source = {};
577 source.type = kFlutterEngineAOTDataSourceTypeElfPath;
579 if (self->embedder_api.CreateAOTData(&source, &self->aot_data) !=
582 "Failed to create AOT data");
585 args.aot_data =
self->aot_data;
588 FlutterEngineResult
result =
self->embedder_api.Initialize(
589 FLUTTER_ENGINE_VERSION, &config, &
args,
self, &self->engine);
592 "Failed to initialize Flutter engine");
596 result =
self->embedder_api.RunInitialized(self->engine);
599 "Failed to run Flutter engine");
609 result =
self->embedder_api.UpdateSemanticsEnabled(self->engine,
TRUE);
611 g_warning(
"Failed to enable accessibility features on Flutter engine");
617 if (refresh_rate <= 0.0) {
620 FlutterEngineDisplay display = {};
621 display.struct_size =
sizeof(FlutterEngineDisplay);
622 display.display_id = 0;
623 display.single_display =
true;
624 display.refresh_rate = refresh_rate;
626 std::vector displays = {display};
627 result =
self->embedder_api.NotifyDisplayUpdate(
628 self->engine, kFlutterEngineDisplaysUpdateTypeStartup, displays.data(),
631 g_warning(
"Failed to notify display update to Flutter engine: %d",
result);
638 return &(
self->embedder_api);
645 GCancellable* cancellable,
648 g_return_val_if_fail(FL_IS_ENGINE(
self), -1);
652 FlutterViewId view_id =
self->next_view_id;
653 self->next_view_id++;
655 FlutterWindowMetricsEvent metrics;
656 metrics.struct_size =
sizeof(FlutterWindowMetricsEvent);
657 metrics.width =
width;
659 metrics.pixel_ratio = pixel_ratio;
660 metrics.view_id = view_id;
661 FlutterAddViewInfo info;
662 info.struct_size =
sizeof(FlutterAddViewInfo);
663 info.view_id = view_id;
664 info.view_metrics = &metrics;
665 info.user_data = g_object_ref(task);
667 FlutterEngineResult
result =
self->embedder_api.AddView(self->engine, &info);
673 g_object_unref(task);
682 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
683 return g_task_propagate_boolean(G_TASK(
result),
error);
687 FlutterViewId view_id,
688 GCancellable* cancellable,
691 g_return_if_fail(FL_IS_ENGINE(
self));
695 FlutterRemoveViewInfo info;
696 info.struct_size =
sizeof(FlutterRemoveViewInfo);
697 info.view_id = view_id;
698 info.user_data = g_object_ref(task);
700 FlutterEngineResult
result =
701 self->embedder_api.RemoveView(self->engine, &info);
707 g_object_unref(task);
714 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
715 return g_task_propagate_boolean(G_TASK(
result),
error);
722 GDestroyNotify destroy_notify) {
723 g_return_if_fail(FL_IS_ENGINE(
self));
724 g_return_if_fail(handler !=
nullptr);
726 if (self->platform_message_handler_destroy_notify) {
727 self->platform_message_handler_destroy_notify(
728 self->platform_message_handler_data);
731 self->platform_message_handler = handler;
732 self->platform_message_handler_data =
user_data;
733 self->platform_message_handler_destroy_notify = destroy_notify;
740 GDestroyNotify destroy_notify) {
741 g_return_if_fail(FL_IS_ENGINE(
self));
743 if (self->update_semantics_handler_destroy_notify) {
744 self->update_semantics_handler_destroy_notify(
745 self->update_semantics_handler_data);
748 self->update_semantics_handler = handler;
749 self->update_semantics_handler_data =
user_data;
750 self->update_semantics_handler_destroy_notify = destroy_notify;
756 const FlutterPlatformMessageResponseHandle* handle,
759 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
760 g_return_val_if_fail(handle !=
nullptr, FALSE);
762 if (self->engine ==
nullptr) {
764 "No engine to send response to");
768 gsize data_length = 0;
769 const uint8_t* data =
nullptr;
770 if (response !=
nullptr) {
772 static_cast<const uint8_t*
>(g_bytes_get_data(response, &data_length));
774 FlutterEngineResult
result =
self->embedder_api.SendPlatformMessageResponse(
775 self->engine, handle, data, data_length);
779 "Failed to send platform message response");
787 const gchar* channel,
789 GCancellable* cancellable,
792 g_return_if_fail(FL_IS_ENGINE(
self));
794 GTask* task =
nullptr;
795 FlutterPlatformMessageResponseHandle* response_handle =
nullptr;
799 if (self->engine ==
nullptr) {
805 FlutterEngineResult
result =
806 self->embedder_api.PlatformMessageCreateResponseHandle(
812 "Failed to create response handle");
813 g_object_unref(task);
816 }
else if (self->engine ==
nullptr) {
820 FlutterPlatformMessage fl_message = {};
821 fl_message.struct_size =
sizeof(fl_message);
822 fl_message.channel = channel;
825 ?
static_cast<const uint8_t*
>(g_bytes_get_data(message,
nullptr))
827 fl_message.message_size = message !=
nullptr ? g_bytes_get_size(message) : 0;
828 fl_message.response_handle = response_handle;
829 FlutterEngineResult
result =
830 self->embedder_api.SendPlatformMessage(self->engine, &fl_message);
832 if (
result != kSuccess && task !=
nullptr) {
835 "Failed to send platform messages");
836 g_object_unref(task);
839 if (response_handle !=
nullptr) {
840 self->embedder_api.PlatformMessageReleaseResponseHandle(self->engine,
848 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
849 g_return_val_if_fail(g_task_is_valid(
result,
self), FALSE);
851 return static_cast<GBytes*
>(g_task_propagate_pointer(G_TASK(
result),
error));
855 FlutterViewId view_id,
858 double pixel_ratio) {
859 g_return_if_fail(FL_IS_ENGINE(
self));
861 if (self->engine ==
nullptr) {
865 FlutterWindowMetricsEvent
event = {};
866 event.struct_size =
sizeof(FlutterWindowMetricsEvent);
869 event.pixel_ratio = pixel_ratio;
870 event.view_id = view_id;
871 self->embedder_api.SendWindowMetricsEvent(self->engine, &
event);
875 FlutterViewId view_id,
876 FlutterPointerPhase phase,
880 FlutterPointerDeviceKind device_kind,
881 double scroll_delta_x,
882 double scroll_delta_y,
884 g_return_if_fail(FL_IS_ENGINE(
self));
886 if (self->engine ==
nullptr) {
890 FlutterPointerEvent fl_event = {};
891 fl_event.struct_size =
sizeof(fl_event);
892 fl_event.phase = phase;
893 fl_event.timestamp = timestamp;
896 if (scroll_delta_x != 0 || scroll_delta_y != 0) {
897 fl_event.signal_kind = kFlutterPointerSignalKindScroll;
899 fl_event.scroll_delta_x = scroll_delta_x;
900 fl_event.scroll_delta_y = scroll_delta_y;
901 fl_event.device_kind = device_kind;
902 fl_event.buttons = buttons;
904 fl_event.view_id = view_id;
905 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
909 FlutterViewId view_id,
913 FlutterPointerPhase phase,
918 g_return_if_fail(FL_IS_ENGINE(
self));
920 if (self->engine ==
nullptr) {
924 FlutterPointerEvent fl_event = {};
925 fl_event.struct_size =
sizeof(fl_event);
926 fl_event.timestamp = timestamp;
929 fl_event.phase = phase;
930 fl_event.pan_x = pan_x;
931 fl_event.pan_y = pan_y;
932 fl_event.scale = scale;
933 fl_event.rotation = rotation;
935 fl_event.device_kind = kFlutterPointerDeviceKindTrackpad;
936 fl_event.view_id = view_id;
937 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
941 const FlutterKeyEvent*
event,
944 g_return_if_fail(FL_IS_ENGINE(
self));
946 if (self->engine ==
nullptr) {
955 FlutterSemanticsAction action,
957 g_return_if_fail(FL_IS_ENGINE(
self));
959 if (self->engine ==
nullptr) {
963 const uint8_t* action_data =
nullptr;
964 size_t action_data_length = 0;
965 if (data !=
nullptr) {
966 action_data =
static_cast<const uint8_t*
>(
967 g_bytes_get_data(data, &action_data_length));
970 self->embedder_api.DispatchSemanticsAction(self->engine,
id, action,
971 action_data, action_data_length);
976 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
977 return self->embedder_api.MarkExternalTextureFrameAvailable(
983 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
984 return self->embedder_api.RegisterExternalTexture(self->engine,
texture_id) ==
990 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
991 return self->embedder_api.UnregisterExternalTexture(self->engine,
997 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
998 return self->binary_messenger;
1002 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
1003 return self->task_runner;
1007 g_return_if_fail(FL_IS_ENGINE(
self));
1008 self->embedder_api.RunTask(self->engine, task);
1013 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
1014 return self->texture_registrar;
1018 g_return_if_fail(FL_IS_ENGINE(
self));
1020 if (self->engine ==
nullptr) {
1024 self->embedder_api.UpdateAccessibilityFeatures(
1025 self->engine,
static_cast<FlutterAccessibilityFeature
>(
flags));
1029 GPtrArray* switches = g_ptr_array_new_with_free_func(g_free);
1031 g_ptr_array_add(switches, g_strdup(env_switch.c_str()));