15 #include "flutter/shell/platform/embedder/embedder.h"
74 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) {
136 g_autoptr(GBytes) message =
139 if (message ==
nullptr) {
145 nullptr,
nullptr,
nullptr);
150 const gchar*
const* languages = g_get_language_names();
151 g_autoptr(GPtrArray) locales_array = g_ptr_array_new_with_free_func(g_free);
153 g_autoptr(GPtrArray) locale_strings = g_ptr_array_new_with_free_func(g_free);
154 for (
int i = 0; languages[i] !=
nullptr; i++) {
155 gchar *language, *territory;
156 parse_locale(languages[i], &language, &territory,
nullptr,
nullptr);
157 if (language !=
nullptr) {
158 g_ptr_array_add(locale_strings, language);
160 if (territory !=
nullptr) {
161 g_ptr_array_add(locale_strings, territory);
164 FlutterLocale* locale =
165 static_cast<FlutterLocale*
>(g_malloc0(
sizeof(FlutterLocale)));
166 g_ptr_array_add(locales_array, locale);
167 locale->struct_size =
sizeof(FlutterLocale);
168 locale->language_code = language;
169 locale->country_code = territory;
170 locale->script_code =
nullptr;
171 locale->variant_code =
nullptr;
173 FlutterLocale** locales =
174 reinterpret_cast<FlutterLocale**
>(locales_array->pdata);
175 FlutterEngineResult
result =
self->embedder_api.UpdateLocales(
176 self->engine,
const_cast<const FlutterLocale**
>(locales),
179 g_warning(
"Failed to set up Flutter locales");
185 const FlutterBackingStoreConfig* config,
186 FlutterBackingStore* backing_store_out,
188 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
195 const FlutterBackingStore* renderer,
197 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
205 g_return_val_if_fail(FL_IS_RENDERER(
user_data),
false);
213 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
218 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
219 g_autoptr(GError)
error =
nullptr;
222 g_warning(
"%s",
error->message);
228 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
229 g_autoptr(GError)
error =
nullptr;
232 g_warning(
"%s",
error->message);
238 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
249 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
250 g_autoptr(GError)
error =
nullptr;
253 g_warning(
"%s",
error->message);
264 FlutterOpenGLTexture* opengl_texture) {
265 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
266 if (!
self->texture_registrar) {
272 if (texture ==
nullptr) {
273 g_warning(
"Unable to find texture %" G_GINT64_FORMAT,
texture_id);
278 g_autoptr(GError)
error =
nullptr;
279 if (FL_IS_TEXTURE_GL(texture)) {
281 opengl_texture, &
error);
282 }
else if (FL_IS_PIXEL_BUFFER_TEXTURE(texture)) {
287 g_warning(
"Unsupported texture type %" G_GINT64_FORMAT,
texture_id);
292 g_warning(
"%s",
error->message);
301 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
302 return self->thread == g_thread_self();
307 uint64_t target_time_nanos,
309 FlEngine*
self =
static_cast<FlEngine*
>(
user_data);
319 gboolean handled = FALSE;
320 if (
self->platform_message_handler !=
nullptr) {
321 g_autoptr(GBytes) data =
322 g_bytes_new(message->message, message->message_size);
323 handled =
self->platform_message_handler(
324 self, message->channel, data, message->response_handle,
325 self->platform_message_handler_data);
339 if (
self->update_semantics_node_handler !=
nullptr) {
340 self->update_semantics_node_handler(
341 self,
node,
self->update_semantics_node_handler_data);
353 if (
self->on_pre_engine_restart_handler !=
nullptr) {
354 self->on_pre_engine_restart_handler(
355 self,
self->on_pre_engine_restart_handler_data);
364 g_autoptr(GTask) task = G_TASK(
user_data);
365 g_task_return_pointer(task, g_bytes_new(data, data_length),
366 reinterpret_cast<GDestroyNotify
>(g_bytes_unref));
371 FlPluginRegistry* registry,
373 FlEngine*
self = FL_ENGINE(registry);
376 self->texture_registrar);
380 FlPluginRegistryInterface* iface) {
388 FlEngine*
self = FL_ENGINE(
object);
390 case kPropBinaryMessenger:
391 g_set_object(&
self->binary_messenger,
392 FL_BINARY_MESSENGER(g_value_get_object(
value)));
395 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
401 FlEngine*
self = FL_ENGINE(
object);
403 if (
self->engine !=
nullptr) {
404 self->embedder_api.Shutdown(
self->engine);
405 self->engine =
nullptr;
408 if (
self->aot_data !=
nullptr) {
409 self->embedder_api.CollectAOTData(
self->aot_data);
410 self->aot_data =
nullptr;
413 g_clear_object(&
self->project);
414 g_clear_object(&
self->renderer);
415 g_clear_object(&
self->texture_registrar);
416 g_clear_object(&
self->binary_messenger);
417 g_clear_object(&
self->settings_plugin);
418 g_clear_object(&
self->task_runner);
420 if (
self->platform_message_handler_destroy_notify) {
421 self->platform_message_handler_destroy_notify(
422 self->platform_message_handler_data);
424 self->platform_message_handler_data =
nullptr;
425 self->platform_message_handler_destroy_notify =
nullptr;
427 if (
self->update_semantics_node_handler_destroy_notify) {
428 self->update_semantics_node_handler_destroy_notify(
429 self->update_semantics_node_handler_data);
431 self->update_semantics_node_handler_data =
nullptr;
432 self->update_semantics_node_handler_destroy_notify =
nullptr;
434 if (
self->on_pre_engine_restart_handler_destroy_notify) {
435 self->on_pre_engine_restart_handler_destroy_notify(
436 self->on_pre_engine_restart_handler_data);
438 self->on_pre_engine_restart_handler_data =
nullptr;
439 self->on_pre_engine_restart_handler_destroy_notify =
nullptr;
441 G_OBJECT_CLASS(fl_engine_parent_class)->dispose(
object);
448 g_object_class_install_property(
449 G_OBJECT_CLASS(klass), kPropBinaryMessenger,
451 "binary-messenger",
"messenger",
"Binary messenger",
452 fl_binary_messenger_get_type(),
453 static_cast<GParamFlags
>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
454 G_PARAM_STATIC_STRINGS)));
458 self->thread = g_thread_self();
460 self->embedder_api.struct_size =
sizeof(FlutterEngineProcTable);
461 FlutterEngineGetProcAddresses(&
self->embedder_api);
467 g_return_val_if_fail(FL_IS_DART_PROJECT(project),
nullptr);
468 g_return_val_if_fail(FL_IS_RENDERER(renderer),
nullptr);
470 FlEngine*
self = FL_ENGINE(g_object_new(fl_engine_get_type(),
nullptr));
471 self->project = FL_DART_PROJECT(g_object_ref(project));
472 self->renderer = FL_RENDERER(g_object_ref(renderer));
483 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
487 FlutterRendererConfig config = {};
488 config.type = kOpenGL;
489 config.open_gl.struct_size =
sizeof(FlutterOpenGLRendererConfig);
496 config.open_gl.gl_external_texture_frame_callback =
499 FlutterTaskRunnerDescription platform_task_runner = {};
500 platform_task_runner.struct_size =
sizeof(FlutterTaskRunnerDescription);
501 platform_task_runner.user_data =
self;
502 platform_task_runner.runs_task_on_current_thread_callback =
507 FlutterCustomTaskRunners custom_task_runners = {};
508 custom_task_runners.struct_size =
sizeof(FlutterCustomTaskRunners);
509 custom_task_runners.platform_task_runner = &platform_task_runner;
510 custom_task_runners.render_task_runner = &platform_task_runner;
516 g_ptr_array_insert(command_line_args, 0, g_strdup(
"flutter"));
518 gchar** dart_entrypoint_args =
521 FlutterProjectArgs
args = {};
522 args.struct_size =
sizeof(FlutterProjectArgs);
525 args.command_line_argc = command_line_args->len;
526 args.command_line_argv =
527 reinterpret_cast<const char* const*
>(command_line_args->pdata);
530 args.custom_task_runners = &custom_task_runners;
531 args.shutdown_dart_vm_when_done =
true;
533 args.dart_entrypoint_argc =
534 dart_entrypoint_args !=
nullptr ? g_strv_length(dart_entrypoint_args) : 0;
535 args.dart_entrypoint_argv =
536 reinterpret_cast<const char* const*
>(dart_entrypoint_args);
538 FlutterCompositor compositor = {};
539 compositor.struct_size =
sizeof(FlutterCompositor);
540 compositor.user_data =
self->renderer;
541 compositor.create_backing_store_callback =
543 compositor.collect_backing_store_callback =
546 args.compositor = &compositor;
548 if (
self->embedder_api.RunsAOTCompiledDartCode()) {
549 FlutterEngineAOTDataSource source = {};
550 source.type = kFlutterEngineAOTDataSourceTypeElfPath;
552 if (
self->embedder_api.CreateAOTData(&source, &
self->aot_data) !=
555 "Failed to create AOT data");
558 args.aot_data =
self->aot_data;
561 FlutterEngineResult
result =
self->embedder_api.Initialize(
562 FLUTTER_ENGINE_VERSION, &config, &
args,
self, &
self->engine);
565 "Failed to initialize Flutter engine");
569 result =
self->embedder_api.RunInitialized(
self->engine);
572 "Failed to run Flutter engine");
582 result =
self->embedder_api.UpdateSemanticsEnabled(
self->engine,
TRUE);
584 g_warning(
"Failed to enable accessibility features on Flutter engine");
591 return &(
self->embedder_api);
598 GDestroyNotify destroy_notify) {
599 g_return_if_fail(FL_IS_ENGINE(
self));
600 g_return_if_fail(handler !=
nullptr);
602 if (
self->platform_message_handler_destroy_notify) {
603 self->platform_message_handler_destroy_notify(
604 self->platform_message_handler_data);
607 self->platform_message_handler = handler;
608 self->platform_message_handler_data =
user_data;
609 self->platform_message_handler_destroy_notify = destroy_notify;
616 GDestroyNotify destroy_notify) {
617 g_return_if_fail(FL_IS_ENGINE(
self));
619 if (
self->update_semantics_node_handler_destroy_notify) {
620 self->update_semantics_node_handler_destroy_notify(
621 self->update_semantics_node_handler_data);
624 self->update_semantics_node_handler = handler;
625 self->update_semantics_node_handler_data =
user_data;
626 self->update_semantics_node_handler_destroy_notify = destroy_notify;
633 GDestroyNotify destroy_notify) {
634 g_return_if_fail(FL_IS_ENGINE(
self));
636 if (
self->on_pre_engine_restart_handler_destroy_notify) {
637 self->on_pre_engine_restart_handler_destroy_notify(
638 self->on_pre_engine_restart_handler_data);
641 self->on_pre_engine_restart_handler = handler;
642 self->on_pre_engine_restart_handler_data =
user_data;
643 self->on_pre_engine_restart_handler_destroy_notify = destroy_notify;
649 const FlutterPlatformMessageResponseHandle* handle,
652 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
653 g_return_val_if_fail(handle !=
nullptr, FALSE);
655 if (
self->engine ==
nullptr) {
657 "No engine to send response to");
661 gsize data_length = 0;
662 const uint8_t* data =
nullptr;
663 if (response !=
nullptr) {
665 static_cast<const uint8_t*
>(g_bytes_get_data(response, &data_length));
667 FlutterEngineResult
result =
self->embedder_api.SendPlatformMessageResponse(
668 self->engine, handle, data, data_length);
672 "Failed to send platform message response");
680 const gchar* channel,
682 GCancellable* cancellable,
685 g_return_if_fail(FL_IS_ENGINE(
self));
687 GTask* task =
nullptr;
688 FlutterPlatformMessageResponseHandle* response_handle =
nullptr;
692 if (
self->engine ==
nullptr) {
698 FlutterEngineResult
result =
699 self->embedder_api.PlatformMessageCreateResponseHandle(
705 "Failed to create response handle");
706 g_object_unref(task);
709 }
else if (
self->engine ==
nullptr) {
713 FlutterPlatformMessage fl_message = {};
714 fl_message.struct_size =
sizeof(fl_message);
715 fl_message.channel = channel;
718 ?
static_cast<const uint8_t*
>(g_bytes_get_data(message,
nullptr))
720 fl_message.message_size = message !=
nullptr ? g_bytes_get_size(message) : 0;
721 fl_message.response_handle = response_handle;
722 FlutterEngineResult
result =
723 self->embedder_api.SendPlatformMessage(
self->engine, &fl_message);
725 if (
result != kSuccess && task !=
nullptr) {
728 "Failed to send platform messages");
729 g_object_unref(task);
732 if (response_handle !=
nullptr) {
733 self->embedder_api.PlatformMessageReleaseResponseHandle(
self->engine,
741 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
742 g_return_val_if_fail(g_task_is_valid(
result,
self), FALSE);
744 return static_cast<GBytes*
>(g_task_propagate_pointer(G_TASK(
result),
error));
750 if (visible && focused) {
752 }
else if (visible) {
762 double pixel_ratio) {
763 g_return_if_fail(FL_IS_ENGINE(
self));
765 if (
self->engine ==
nullptr) {
769 FlutterWindowMetricsEvent
event = {};
770 event.struct_size =
sizeof(FlutterWindowMetricsEvent);
773 event.pixel_ratio = pixel_ratio;
774 self->embedder_api.SendWindowMetricsEvent(
self->engine, &
event);
778 FlutterPointerPhase phase,
782 double scroll_delta_x,
783 double scroll_delta_y,
785 g_return_if_fail(FL_IS_ENGINE(
self));
787 if (
self->engine ==
nullptr) {
791 FlutterPointerEvent fl_event = {};
792 fl_event.struct_size =
sizeof(fl_event);
793 fl_event.phase = phase;
794 fl_event.timestamp = timestamp;
797 if (scroll_delta_x != 0 || scroll_delta_y != 0) {
798 fl_event.signal_kind = kFlutterPointerSignalKindScroll;
800 fl_event.scroll_delta_x = scroll_delta_x;
801 fl_event.scroll_delta_y = scroll_delta_y;
802 fl_event.device_kind = kFlutterPointerDeviceKindMouse;
803 fl_event.buttons = buttons;
805 self->embedder_api.SendPointerEvent(
self->engine, &fl_event, 1);
812 FlutterPointerPhase phase,
817 g_return_if_fail(FL_IS_ENGINE(
self));
819 if (
self->engine ==
nullptr) {
823 FlutterPointerEvent fl_event = {};
824 fl_event.struct_size =
sizeof(fl_event);
825 fl_event.timestamp = timestamp;
828 fl_event.phase = phase;
829 fl_event.pan_x = pan_x;
830 fl_event.pan_y = pan_y;
831 fl_event.scale = scale;
832 fl_event.rotation = rotation;
834 fl_event.device_kind = kFlutterPointerDeviceKindTrackpad;
835 self->embedder_api.SendPointerEvent(
self->engine, &fl_event, 1);
839 const FlutterKeyEvent*
event,
842 g_return_if_fail(FL_IS_ENGINE(
self));
844 if (
self->engine ==
nullptr) {
853 FlutterSemanticsAction action,
855 g_return_if_fail(FL_IS_ENGINE(
self));
857 if (
self->engine ==
nullptr) {
861 const uint8_t* action_data =
nullptr;
862 size_t action_data_length = 0;
863 if (data !=
nullptr) {
864 action_data =
static_cast<const uint8_t*
>(
865 g_bytes_get_data(data, &action_data_length));
868 self->embedder_api.DispatchSemanticsAction(
self->engine,
id, action,
869 action_data, action_data_length);
874 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
875 return self->embedder_api.MarkExternalTextureFrameAvailable(
881 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
882 return self->embedder_api.RegisterExternalTexture(
self->engine,
texture_id) ==
888 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
889 return self->embedder_api.UnregisterExternalTexture(
self->engine,
895 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
896 return self->binary_messenger;
900 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
901 return self->task_runner;
905 g_return_if_fail(FL_IS_ENGINE(
self));
906 self->embedder_api.RunTask(
self->engine, task);
911 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
912 return self->texture_registrar;
916 g_return_if_fail(FL_IS_ENGINE(
self));
918 if (
self->engine ==
nullptr) {
922 self->embedder_api.UpdateAccessibilityFeatures(
923 self->engine,
static_cast<FlutterAccessibilityFeature
>(
flags));
927 GPtrArray* switches = g_ptr_array_new_with_free_func(g_free);
929 g_ptr_array_add(switches, g_strdup(env_switch.c_str()));