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;
402 g_clear_object(&self->project);
403 g_clear_object(&self->renderer);
404 g_clear_object(&self->texture_registrar);
405 g_clear_object(&self->binary_messenger);
406 g_clear_object(&self->settings_plugin);
407 g_clear_object(&self->task_runner);
409 if (self->platform_message_handler_destroy_notify) {
410 self->platform_message_handler_destroy_notify(
411 self->platform_message_handler_data);
413 self->platform_message_handler_data =
nullptr;
414 self->platform_message_handler_destroy_notify =
nullptr;
416 if (self->update_semantics_handler_destroy_notify) {
417 self->update_semantics_handler_destroy_notify(
418 self->update_semantics_handler_data);
420 self->update_semantics_handler_data =
nullptr;
421 self->update_semantics_handler_destroy_notify =
nullptr;
423 if (self->on_pre_engine_restart_handler_destroy_notify) {
424 self->on_pre_engine_restart_handler_destroy_notify(
425 self->on_pre_engine_restart_handler_data);
427 self->on_pre_engine_restart_handler_data =
nullptr;
428 self->on_pre_engine_restart_handler_destroy_notify =
nullptr;
430 G_OBJECT_CLASS(fl_engine_parent_class)->dispose(
object);
437 g_object_class_install_property(
438 G_OBJECT_CLASS(klass), kPropBinaryMessenger,
440 "binary-messenger",
"messenger",
"Binary messenger",
441 fl_binary_messenger_get_type(),
442 static_cast<GParamFlags
>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
443 G_PARAM_STATIC_STRINGS)));
447 self->thread = g_thread_self();
449 self->embedder_api.struct_size =
sizeof(FlutterEngineProcTable);
450 FlutterEngineGetProcAddresses(&self->embedder_api);
456 g_return_val_if_fail(FL_IS_DART_PROJECT(project),
nullptr);
457 g_return_val_if_fail(FL_IS_RENDERER(renderer),
nullptr);
459 FlEngine*
self = FL_ENGINE(g_object_new(fl_engine_get_type(),
nullptr));
460 self->project = FL_DART_PROJECT(g_object_ref(project));
461 self->renderer = FL_RENDERER(g_object_ref(renderer));
472 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
476 FlutterRendererConfig config = {};
477 config.type = kOpenGL;
478 config.open_gl.struct_size =
sizeof(FlutterOpenGLRendererConfig);
485 config.open_gl.gl_external_texture_frame_callback =
488 FlutterTaskRunnerDescription platform_task_runner = {};
489 platform_task_runner.struct_size =
sizeof(FlutterTaskRunnerDescription);
490 platform_task_runner.user_data =
self;
491 platform_task_runner.runs_task_on_current_thread_callback =
496 FlutterCustomTaskRunners custom_task_runners = {};
497 custom_task_runners.struct_size =
sizeof(FlutterCustomTaskRunners);
498 custom_task_runners.platform_task_runner = &platform_task_runner;
499 custom_task_runners.render_task_runner = &platform_task_runner;
505 g_ptr_array_insert(command_line_args, 0, g_strdup(
"flutter"));
507 gchar** dart_entrypoint_args =
510 FlutterProjectArgs
args = {};
511 args.struct_size =
sizeof(FlutterProjectArgs);
514 args.command_line_argc = command_line_args->len;
515 args.command_line_argv =
516 reinterpret_cast<const char* const*
>(command_line_args->pdata);
519 args.custom_task_runners = &custom_task_runners;
520 args.shutdown_dart_vm_when_done =
true;
522 args.dart_entrypoint_argc =
523 dart_entrypoint_args !=
nullptr ? g_strv_length(dart_entrypoint_args) : 0;
524 args.dart_entrypoint_argv =
525 reinterpret_cast<const char* const*
>(dart_entrypoint_args);
527 FlutterCompositor compositor = {};
528 compositor.struct_size =
sizeof(FlutterCompositor);
529 compositor.user_data =
self->renderer;
530 compositor.create_backing_store_callback =
532 compositor.collect_backing_store_callback =
535 args.compositor = &compositor;
537 if (self->embedder_api.RunsAOTCompiledDartCode()) {
538 FlutterEngineAOTDataSource source = {};
539 source.type = kFlutterEngineAOTDataSourceTypeElfPath;
541 if (self->embedder_api.CreateAOTData(&source, &self->aot_data) !=
544 "Failed to create AOT data");
547 args.aot_data =
self->aot_data;
550 FlutterEngineResult
result =
self->embedder_api.Initialize(
551 FLUTTER_ENGINE_VERSION, &config, &
args,
self, &self->engine);
554 "Failed to initialize Flutter engine");
558 result =
self->embedder_api.RunInitialized(self->engine);
561 "Failed to run Flutter engine");
571 result =
self->embedder_api.UpdateSemanticsEnabled(self->engine,
TRUE);
573 g_warning(
"Failed to enable accessibility features on Flutter engine");
579 if (refresh_rate <= 0.0) {
582 FlutterEngineDisplay display = {};
583 display.struct_size =
sizeof(FlutterEngineDisplay);
584 display.display_id = 0;
585 display.single_display =
true;
586 display.refresh_rate = refresh_rate;
588 std::vector displays = {display};
589 result =
self->embedder_api.NotifyDisplayUpdate(
590 self->engine, kFlutterEngineDisplaysUpdateTypeStartup, displays.data(),
593 g_warning(
"Failed to notify display update to Flutter engine: %d",
result);
600 return &(
self->embedder_api);
607 GDestroyNotify destroy_notify) {
608 g_return_if_fail(FL_IS_ENGINE(
self));
609 g_return_if_fail(handler !=
nullptr);
611 if (self->platform_message_handler_destroy_notify) {
612 self->platform_message_handler_destroy_notify(
613 self->platform_message_handler_data);
616 self->platform_message_handler = handler;
617 self->platform_message_handler_data =
user_data;
618 self->platform_message_handler_destroy_notify = destroy_notify;
625 GDestroyNotify destroy_notify) {
626 g_return_if_fail(FL_IS_ENGINE(
self));
628 if (self->update_semantics_handler_destroy_notify) {
629 self->update_semantics_handler_destroy_notify(
630 self->update_semantics_handler_data);
633 self->update_semantics_handler = handler;
634 self->update_semantics_handler_data =
user_data;
635 self->update_semantics_handler_destroy_notify = destroy_notify;
642 GDestroyNotify destroy_notify) {
643 g_return_if_fail(FL_IS_ENGINE(
self));
645 if (self->on_pre_engine_restart_handler_destroy_notify) {
646 self->on_pre_engine_restart_handler_destroy_notify(
647 self->on_pre_engine_restart_handler_data);
650 self->on_pre_engine_restart_handler = handler;
651 self->on_pre_engine_restart_handler_data =
user_data;
652 self->on_pre_engine_restart_handler_destroy_notify = destroy_notify;
658 const FlutterPlatformMessageResponseHandle* handle,
661 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
662 g_return_val_if_fail(handle !=
nullptr, FALSE);
664 if (self->engine ==
nullptr) {
666 "No engine to send response to");
670 gsize data_length = 0;
671 const uint8_t* data =
nullptr;
672 if (response !=
nullptr) {
674 static_cast<const uint8_t*
>(g_bytes_get_data(response, &data_length));
676 FlutterEngineResult
result =
self->embedder_api.SendPlatformMessageResponse(
677 self->engine, handle, data, data_length);
681 "Failed to send platform message response");
689 const gchar* channel,
691 GCancellable* cancellable,
694 g_return_if_fail(FL_IS_ENGINE(
self));
696 GTask* task =
nullptr;
697 FlutterPlatformMessageResponseHandle* response_handle =
nullptr;
701 if (self->engine ==
nullptr) {
707 FlutterEngineResult
result =
708 self->embedder_api.PlatformMessageCreateResponseHandle(
714 "Failed to create response handle");
715 g_object_unref(task);
718 }
else if (self->engine ==
nullptr) {
722 FlutterPlatformMessage fl_message = {};
723 fl_message.struct_size =
sizeof(fl_message);
724 fl_message.channel = channel;
727 ?
static_cast<const uint8_t*
>(g_bytes_get_data(message,
nullptr))
729 fl_message.message_size = message !=
nullptr ? g_bytes_get_size(message) : 0;
730 fl_message.response_handle = response_handle;
731 FlutterEngineResult
result =
732 self->embedder_api.SendPlatformMessage(self->engine, &fl_message);
734 if (
result != kSuccess && task !=
nullptr) {
737 "Failed to send platform messages");
738 g_object_unref(task);
741 if (response_handle !=
nullptr) {
742 self->embedder_api.PlatformMessageReleaseResponseHandle(self->engine,
750 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
751 g_return_val_if_fail(g_task_is_valid(
result,
self), FALSE);
753 return static_cast<GBytes*
>(g_task_propagate_pointer(G_TASK(
result),
error));
759 if (visible && focused) {
761 }
else if (visible) {
771 double pixel_ratio) {
772 g_return_if_fail(FL_IS_ENGINE(
self));
774 if (self->engine ==
nullptr) {
778 FlutterWindowMetricsEvent
event = {};
779 event.struct_size =
sizeof(FlutterWindowMetricsEvent);
782 event.pixel_ratio = pixel_ratio;
786 event.view_id = flutter::kFlutterImplicitViewId;
787 self->embedder_api.SendWindowMetricsEvent(self->engine, &
event);
791 FlutterPointerPhase phase,
795 FlutterPointerDeviceKind device_kind,
796 double scroll_delta_x,
797 double scroll_delta_y,
799 g_return_if_fail(FL_IS_ENGINE(
self));
801 if (self->engine ==
nullptr) {
805 FlutterPointerEvent fl_event = {};
806 fl_event.struct_size =
sizeof(fl_event);
807 fl_event.phase = phase;
808 fl_event.timestamp = timestamp;
811 if (scroll_delta_x != 0 || scroll_delta_y != 0) {
812 fl_event.signal_kind = kFlutterPointerSignalKindScroll;
814 fl_event.scroll_delta_x = scroll_delta_x;
815 fl_event.scroll_delta_y = scroll_delta_y;
816 fl_event.device_kind = device_kind;
817 fl_event.buttons = buttons;
822 fl_event.view_id = flutter::kFlutterImplicitViewId;
823 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
830 FlutterPointerPhase phase,
835 g_return_if_fail(FL_IS_ENGINE(
self));
837 if (self->engine ==
nullptr) {
841 FlutterPointerEvent fl_event = {};
842 fl_event.struct_size =
sizeof(fl_event);
843 fl_event.timestamp = timestamp;
846 fl_event.phase = phase;
847 fl_event.pan_x = pan_x;
848 fl_event.pan_y = pan_y;
849 fl_event.scale = scale;
850 fl_event.rotation = rotation;
852 fl_event.device_kind = kFlutterPointerDeviceKindTrackpad;
856 fl_event.view_id = flutter::kFlutterImplicitViewId;
857 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
861 const FlutterKeyEvent*
event,
864 g_return_if_fail(FL_IS_ENGINE(
self));
866 if (self->engine ==
nullptr) {
875 FlutterSemanticsAction action,
877 g_return_if_fail(FL_IS_ENGINE(
self));
879 if (self->engine ==
nullptr) {
883 const uint8_t* action_data =
nullptr;
884 size_t action_data_length = 0;
885 if (data !=
nullptr) {
886 action_data =
static_cast<const uint8_t*
>(
887 g_bytes_get_data(data, &action_data_length));
890 self->embedder_api.DispatchSemanticsAction(self->engine,
id, action,
891 action_data, action_data_length);
896 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
897 return self->embedder_api.MarkExternalTextureFrameAvailable(
903 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
904 return self->embedder_api.RegisterExternalTexture(self->engine,
texture_id) ==
910 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
911 return self->embedder_api.UnregisterExternalTexture(self->engine,
917 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
918 return self->binary_messenger;
922 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
923 return self->task_runner;
927 g_return_if_fail(FL_IS_ENGINE(
self));
928 self->embedder_api.RunTask(self->engine, task);
933 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
934 return self->texture_registrar;
938 g_return_if_fail(FL_IS_ENGINE(
self));
940 if (self->engine ==
nullptr) {
944 self->embedder_api.UpdateAccessibilityFeatures(
945 self->engine,
static_cast<FlutterAccessibilityFeature
>(
flags));
949 GPtrArray* switches = g_ptr_array_new_with_free_func(g_free);
951 g_ptr_array_add(switches, g_strdup(env_switch.c_str()));