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);
220 g_autoptr(GError)
error =
nullptr;
223 g_warning(
"%s",
error->message);
229 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
230 g_autoptr(GError)
error =
nullptr;
233 g_warning(
"%s",
error->message);
239 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
250 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
251 g_autoptr(GError)
error =
nullptr;
254 g_warning(
"%s",
error->message);
265 FlutterOpenGLTexture* opengl_texture) {
266 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
267 if (!
self->texture_registrar) {
273 if (texture ==
nullptr) {
274 g_warning(
"Unable to find texture %" G_GINT64_FORMAT,
texture_id);
279 g_autoptr(GError)
error =
nullptr;
280 if (FL_IS_TEXTURE_GL(texture)) {
282 opengl_texture, &
error);
283 }
else if (FL_IS_PIXEL_BUFFER_TEXTURE(texture)) {
288 g_warning(
"Unsupported texture type %" G_GINT64_FORMAT,
texture_id);
293 g_warning(
"%s",
error->message);
302 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
303 return self->thread == g_thread_self();
308 uint64_t target_time_nanos,
310 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
320 gboolean handled = FALSE;
321 if (
self->platform_message_handler !=
nullptr) {
322 g_autoptr(GBytes) data =
323 g_bytes_new(message->message, message->message_size);
324 handled =
self->platform_message_handler(
325 self, message->channel, data, message->response_handle,
326 self->platform_message_handler_data);
340 if (
self->update_semantics_node_handler !=
nullptr) {
341 self->update_semantics_node_handler(
342 self,
node,
self->update_semantics_node_handler_data);
354 if (
self->on_pre_engine_restart_handler !=
nullptr) {
355 self->on_pre_engine_restart_handler(
356 self,
self->on_pre_engine_restart_handler_data);
365 g_autoptr(GTask) task = G_TASK(
user_data);
366 g_task_return_pointer(task, g_bytes_new(data, data_length),
367 reinterpret_cast<GDestroyNotify
>(g_bytes_unref));
372 FlPluginRegistry* registry,
374 FlEngine*
self = FL_ENGINE(registry);
377 self->texture_registrar);
381 FlPluginRegistryInterface* iface) {
389 FlEngine*
self = FL_ENGINE(
object);
391 case kPropBinaryMessenger:
392 g_set_object(&
self->binary_messenger,
393 FL_BINARY_MESSENGER(g_value_get_object(
value)));
396 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
402 FlEngine*
self = FL_ENGINE(
object);
404 if (
self->engine !=
nullptr) {
405 self->embedder_api.Shutdown(
self->engine);
406 self->engine =
nullptr;
409 if (
self->aot_data !=
nullptr) {
410 self->embedder_api.CollectAOTData(
self->aot_data);
411 self->aot_data =
nullptr;
414 g_clear_object(&
self->project);
415 g_clear_object(&
self->renderer);
416 g_clear_object(&
self->texture_registrar);
417 g_clear_object(&
self->binary_messenger);
418 g_clear_object(&
self->settings_plugin);
419 g_clear_object(&
self->task_runner);
421 if (
self->platform_message_handler_destroy_notify) {
422 self->platform_message_handler_destroy_notify(
423 self->platform_message_handler_data);
425 self->platform_message_handler_data =
nullptr;
426 self->platform_message_handler_destroy_notify =
nullptr;
428 if (
self->update_semantics_node_handler_destroy_notify) {
429 self->update_semantics_node_handler_destroy_notify(
430 self->update_semantics_node_handler_data);
432 self->update_semantics_node_handler_data =
nullptr;
433 self->update_semantics_node_handler_destroy_notify =
nullptr;
435 if (
self->on_pre_engine_restart_handler_destroy_notify) {
436 self->on_pre_engine_restart_handler_destroy_notify(
437 self->on_pre_engine_restart_handler_data);
439 self->on_pre_engine_restart_handler_data =
nullptr;
440 self->on_pre_engine_restart_handler_destroy_notify =
nullptr;
442 G_OBJECT_CLASS(fl_engine_parent_class)->dispose(
object);
449 g_object_class_install_property(
450 G_OBJECT_CLASS(klass), kPropBinaryMessenger,
452 "binary-messenger",
"messenger",
"Binary messenger",
453 fl_binary_messenger_get_type(),
454 static_cast<GParamFlags
>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
455 G_PARAM_STATIC_STRINGS)));
459 self->thread = g_thread_self();
461 self->embedder_api.struct_size =
sizeof(FlutterEngineProcTable);
462 FlutterEngineGetProcAddresses(&
self->embedder_api);
468 g_return_val_if_fail(FL_IS_DART_PROJECT(project),
nullptr);
469 g_return_val_if_fail(FL_IS_RENDERER(renderer),
nullptr);
471 FlEngine*
self = FL_ENGINE(g_object_new(fl_engine_get_type(),
nullptr));
472 self->project = FL_DART_PROJECT(g_object_ref(project));
473 self->renderer = FL_RENDERER(g_object_ref(renderer));
484 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
488 FlutterRendererConfig config = {};
489 config.type = kOpenGL;
490 config.open_gl.struct_size =
sizeof(FlutterOpenGLRendererConfig);
497 config.open_gl.gl_external_texture_frame_callback =
500 FlutterTaskRunnerDescription platform_task_runner = {};
501 platform_task_runner.struct_size =
sizeof(FlutterTaskRunnerDescription);
502 platform_task_runner.user_data =
self;
503 platform_task_runner.runs_task_on_current_thread_callback =
508 FlutterCustomTaskRunners custom_task_runners = {};
509 custom_task_runners.struct_size =
sizeof(FlutterCustomTaskRunners);
510 custom_task_runners.platform_task_runner = &platform_task_runner;
511 custom_task_runners.render_task_runner = &platform_task_runner;
517 g_ptr_array_insert(command_line_args, 0, g_strdup(
"flutter"));
519 gchar** dart_entrypoint_args =
522 FlutterProjectArgs
args = {};
523 args.struct_size =
sizeof(FlutterProjectArgs);
526 args.command_line_argc = command_line_args->len;
527 args.command_line_argv =
528 reinterpret_cast<const char* const*
>(command_line_args->pdata);
531 args.custom_task_runners = &custom_task_runners;
532 args.shutdown_dart_vm_when_done =
true;
534 args.dart_entrypoint_argc =
535 dart_entrypoint_args !=
nullptr ? g_strv_length(dart_entrypoint_args) : 0;
536 args.dart_entrypoint_argv =
537 reinterpret_cast<const char* const*
>(dart_entrypoint_args);
539 FlutterCompositor compositor = {};
540 compositor.struct_size =
sizeof(FlutterCompositor);
541 compositor.user_data =
self->renderer;
542 compositor.create_backing_store_callback =
544 compositor.collect_backing_store_callback =
547 args.compositor = &compositor;
549 if (
self->embedder_api.RunsAOTCompiledDartCode()) {
550 FlutterEngineAOTDataSource source = {};
551 source.type = kFlutterEngineAOTDataSourceTypeElfPath;
553 if (
self->embedder_api.CreateAOTData(&source, &
self->aot_data) !=
556 "Failed to create AOT data");
559 args.aot_data =
self->aot_data;
562 FlutterEngineResult
result =
self->embedder_api.Initialize(
563 FLUTTER_ENGINE_VERSION, &config, &
args,
self, &
self->engine);
566 "Failed to initialize Flutter engine");
570 result =
self->embedder_api.RunInitialized(
self->engine);
573 "Failed to run Flutter engine");
583 result =
self->embedder_api.UpdateSemanticsEnabled(
self->engine,
TRUE);
585 g_warning(
"Failed to enable accessibility features on Flutter engine");
592 return &(
self->embedder_api);
599 GDestroyNotify destroy_notify) {
600 g_return_if_fail(FL_IS_ENGINE(
self));
601 g_return_if_fail(handler !=
nullptr);
603 if (
self->platform_message_handler_destroy_notify) {
604 self->platform_message_handler_destroy_notify(
605 self->platform_message_handler_data);
608 self->platform_message_handler = handler;
609 self->platform_message_handler_data =
user_data;
610 self->platform_message_handler_destroy_notify = destroy_notify;
617 GDestroyNotify destroy_notify) {
618 g_return_if_fail(FL_IS_ENGINE(
self));
620 if (
self->update_semantics_node_handler_destroy_notify) {
621 self->update_semantics_node_handler_destroy_notify(
622 self->update_semantics_node_handler_data);
625 self->update_semantics_node_handler = handler;
626 self->update_semantics_node_handler_data =
user_data;
627 self->update_semantics_node_handler_destroy_notify = destroy_notify;
634 GDestroyNotify destroy_notify) {
635 g_return_if_fail(FL_IS_ENGINE(
self));
637 if (
self->on_pre_engine_restart_handler_destroy_notify) {
638 self->on_pre_engine_restart_handler_destroy_notify(
639 self->on_pre_engine_restart_handler_data);
642 self->on_pre_engine_restart_handler = handler;
643 self->on_pre_engine_restart_handler_data =
user_data;
644 self->on_pre_engine_restart_handler_destroy_notify = destroy_notify;
650 const FlutterPlatformMessageResponseHandle* handle,
653 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
654 g_return_val_if_fail(handle !=
nullptr, FALSE);
656 if (
self->engine ==
nullptr) {
658 "No engine to send response to");
662 gsize data_length = 0;
663 const uint8_t* data =
nullptr;
664 if (response !=
nullptr) {
666 static_cast<const uint8_t*
>(g_bytes_get_data(response, &data_length));
668 FlutterEngineResult
result =
self->embedder_api.SendPlatformMessageResponse(
669 self->engine, handle, data, data_length);
673 "Failed to send platform message response");
681 const gchar* channel,
683 GCancellable* cancellable,
686 g_return_if_fail(FL_IS_ENGINE(
self));
688 GTask* task =
nullptr;
689 FlutterPlatformMessageResponseHandle* response_handle =
nullptr;
693 if (
self->engine ==
nullptr) {
699 FlutterEngineResult
result =
700 self->embedder_api.PlatformMessageCreateResponseHandle(
706 "Failed to create response handle");
707 g_object_unref(task);
710 }
else if (
self->engine ==
nullptr) {
714 FlutterPlatformMessage fl_message = {};
715 fl_message.struct_size =
sizeof(fl_message);
716 fl_message.channel = channel;
719 ?
static_cast<const uint8_t*
>(g_bytes_get_data(message,
nullptr))
721 fl_message.message_size = message !=
nullptr ? g_bytes_get_size(message) : 0;
722 fl_message.response_handle = response_handle;
723 FlutterEngineResult
result =
724 self->embedder_api.SendPlatformMessage(
self->engine, &fl_message);
726 if (
result != kSuccess && task !=
nullptr) {
729 "Failed to send platform messages");
730 g_object_unref(task);
733 if (response_handle !=
nullptr) {
734 self->embedder_api.PlatformMessageReleaseResponseHandle(
self->engine,
742 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
743 g_return_val_if_fail(g_task_is_valid(
result,
self), FALSE);
745 return static_cast<GBytes*
>(g_task_propagate_pointer(G_TASK(
result),
error));
751 if (visible && focused) {
753 }
else if (visible) {
763 double pixel_ratio) {
764 g_return_if_fail(FL_IS_ENGINE(
self));
766 if (
self->engine ==
nullptr) {
770 FlutterWindowMetricsEvent
event = {};
771 event.struct_size =
sizeof(FlutterWindowMetricsEvent);
774 event.pixel_ratio = pixel_ratio;
775 self->embedder_api.SendWindowMetricsEvent(
self->engine, &
event);
779 FlutterPointerPhase phase,
783 double scroll_delta_x,
784 double scroll_delta_y,
786 g_return_if_fail(FL_IS_ENGINE(
self));
788 if (
self->engine ==
nullptr) {
792 FlutterPointerEvent fl_event = {};
793 fl_event.struct_size =
sizeof(fl_event);
794 fl_event.phase = phase;
795 fl_event.timestamp = timestamp;
798 if (scroll_delta_x != 0 || scroll_delta_y != 0) {
799 fl_event.signal_kind = kFlutterPointerSignalKindScroll;
801 fl_event.scroll_delta_x = scroll_delta_x;
802 fl_event.scroll_delta_y = scroll_delta_y;
803 fl_event.device_kind = kFlutterPointerDeviceKindMouse;
804 fl_event.buttons = buttons;
809 fl_event.view_id = flutter::kFlutterImplicitViewId;
810 self->embedder_api.SendPointerEvent(
self->engine, &fl_event, 1);
817 FlutterPointerPhase phase,
822 g_return_if_fail(FL_IS_ENGINE(
self));
824 if (
self->engine ==
nullptr) {
828 FlutterPointerEvent fl_event = {};
829 fl_event.struct_size =
sizeof(fl_event);
830 fl_event.timestamp = timestamp;
833 fl_event.phase = phase;
834 fl_event.pan_x = pan_x;
835 fl_event.pan_y = pan_y;
836 fl_event.scale = scale;
837 fl_event.rotation = rotation;
839 fl_event.device_kind = kFlutterPointerDeviceKindTrackpad;
843 fl_event.view_id = flutter::kFlutterImplicitViewId;
844 self->embedder_api.SendPointerEvent(
self->engine, &fl_event, 1);
848 const FlutterKeyEvent*
event,
851 g_return_if_fail(FL_IS_ENGINE(
self));
853 if (
self->engine ==
nullptr) {
862 FlutterSemanticsAction action,
864 g_return_if_fail(FL_IS_ENGINE(
self));
866 if (
self->engine ==
nullptr) {
870 const uint8_t* action_data =
nullptr;
871 size_t action_data_length = 0;
872 if (data !=
nullptr) {
873 action_data =
static_cast<const uint8_t*
>(
874 g_bytes_get_data(data, &action_data_length));
877 self->embedder_api.DispatchSemanticsAction(
self->engine,
id, action,
878 action_data, action_data_length);
883 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
884 return self->embedder_api.MarkExternalTextureFrameAvailable(
890 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
891 return self->embedder_api.RegisterExternalTexture(
self->engine,
texture_id) ==
897 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
898 return self->embedder_api.UnregisterExternalTexture(
self->engine,
904 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
905 return self->binary_messenger;
909 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
910 return self->task_runner;
914 g_return_if_fail(FL_IS_ENGINE(
self));
915 self->embedder_api.RunTask(
self->engine, task);
920 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
921 return self->texture_registrar;
925 g_return_if_fail(FL_IS_ENGINE(
self));
927 if (
self->engine ==
nullptr) {
931 self->embedder_api.UpdateAccessibilityFeatures(
932 self->engine,
static_cast<FlutterAccessibilityFeature
>(
flags));
936 GPtrArray* switches = g_ptr_array_new_with_free_func(g_free);
938 g_ptr_array_add(switches, g_strdup(env_switch.c_str()));