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");
580 return &(
self->embedder_api);
587 GDestroyNotify destroy_notify) {
588 g_return_if_fail(FL_IS_ENGINE(
self));
589 g_return_if_fail(handler !=
nullptr);
591 if (self->platform_message_handler_destroy_notify) {
592 self->platform_message_handler_destroy_notify(
593 self->platform_message_handler_data);
596 self->platform_message_handler = handler;
597 self->platform_message_handler_data =
user_data;
598 self->platform_message_handler_destroy_notify = destroy_notify;
605 GDestroyNotify destroy_notify) {
606 g_return_if_fail(FL_IS_ENGINE(
self));
608 if (self->update_semantics_handler_destroy_notify) {
609 self->update_semantics_handler_destroy_notify(
610 self->update_semantics_handler_data);
613 self->update_semantics_handler = handler;
614 self->update_semantics_handler_data =
user_data;
615 self->update_semantics_handler_destroy_notify = destroy_notify;
622 GDestroyNotify destroy_notify) {
623 g_return_if_fail(FL_IS_ENGINE(
self));
625 if (self->on_pre_engine_restart_handler_destroy_notify) {
626 self->on_pre_engine_restart_handler_destroy_notify(
627 self->on_pre_engine_restart_handler_data);
630 self->on_pre_engine_restart_handler = handler;
631 self->on_pre_engine_restart_handler_data =
user_data;
632 self->on_pre_engine_restart_handler_destroy_notify = destroy_notify;
638 const FlutterPlatformMessageResponseHandle* handle,
641 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
642 g_return_val_if_fail(handle !=
nullptr, FALSE);
644 if (self->engine ==
nullptr) {
646 "No engine to send response to");
650 gsize data_length = 0;
651 const uint8_t* data =
nullptr;
652 if (response !=
nullptr) {
654 static_cast<const uint8_t*
>(g_bytes_get_data(response, &data_length));
656 FlutterEngineResult
result =
self->embedder_api.SendPlatformMessageResponse(
657 self->engine, handle, data, data_length);
661 "Failed to send platform message response");
669 const gchar* channel,
671 GCancellable* cancellable,
674 g_return_if_fail(FL_IS_ENGINE(
self));
676 GTask* task =
nullptr;
677 FlutterPlatformMessageResponseHandle* response_handle =
nullptr;
681 if (self->engine ==
nullptr) {
687 FlutterEngineResult
result =
688 self->embedder_api.PlatformMessageCreateResponseHandle(
694 "Failed to create response handle");
695 g_object_unref(task);
698 }
else if (self->engine ==
nullptr) {
702 FlutterPlatformMessage fl_message = {};
703 fl_message.struct_size =
sizeof(fl_message);
704 fl_message.channel = channel;
707 ?
static_cast<const uint8_t*
>(g_bytes_get_data(message,
nullptr))
709 fl_message.message_size = message !=
nullptr ? g_bytes_get_size(message) : 0;
710 fl_message.response_handle = response_handle;
711 FlutterEngineResult
result =
712 self->embedder_api.SendPlatformMessage(self->engine, &fl_message);
714 if (
result != kSuccess && task !=
nullptr) {
717 "Failed to send platform messages");
718 g_object_unref(task);
721 if (response_handle !=
nullptr) {
722 self->embedder_api.PlatformMessageReleaseResponseHandle(self->engine,
730 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
731 g_return_val_if_fail(g_task_is_valid(
result,
self), FALSE);
733 return static_cast<GBytes*
>(g_task_propagate_pointer(G_TASK(
result),
error));
739 if (visible && focused) {
741 }
else if (visible) {
751 double pixel_ratio) {
752 g_return_if_fail(FL_IS_ENGINE(
self));
754 if (self->engine ==
nullptr) {
758 FlutterWindowMetricsEvent
event = {};
759 event.struct_size =
sizeof(FlutterWindowMetricsEvent);
762 event.pixel_ratio = pixel_ratio;
766 event.view_id = flutter::kFlutterImplicitViewId;
767 self->embedder_api.SendWindowMetricsEvent(self->engine, &
event);
771 FlutterPointerPhase phase,
775 double scroll_delta_x,
776 double scroll_delta_y,
778 g_return_if_fail(FL_IS_ENGINE(
self));
780 if (self->engine ==
nullptr) {
784 FlutterPointerEvent fl_event = {};
785 fl_event.struct_size =
sizeof(fl_event);
786 fl_event.phase = phase;
787 fl_event.timestamp = timestamp;
790 if (scroll_delta_x != 0 || scroll_delta_y != 0) {
791 fl_event.signal_kind = kFlutterPointerSignalKindScroll;
793 fl_event.scroll_delta_x = scroll_delta_x;
794 fl_event.scroll_delta_y = scroll_delta_y;
795 fl_event.device_kind = kFlutterPointerDeviceKindMouse;
796 fl_event.buttons = buttons;
801 fl_event.view_id = flutter::kFlutterImplicitViewId;
802 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
809 FlutterPointerPhase phase,
814 g_return_if_fail(FL_IS_ENGINE(
self));
816 if (self->engine ==
nullptr) {
820 FlutterPointerEvent fl_event = {};
821 fl_event.struct_size =
sizeof(fl_event);
822 fl_event.timestamp = timestamp;
825 fl_event.phase = phase;
826 fl_event.pan_x = pan_x;
827 fl_event.pan_y = pan_y;
828 fl_event.scale = scale;
829 fl_event.rotation = rotation;
831 fl_event.device_kind = kFlutterPointerDeviceKindTrackpad;
835 fl_event.view_id = flutter::kFlutterImplicitViewId;
836 self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
840 const FlutterKeyEvent*
event,
843 g_return_if_fail(FL_IS_ENGINE(
self));
845 if (self->engine ==
nullptr) {
854 FlutterSemanticsAction action,
856 g_return_if_fail(FL_IS_ENGINE(
self));
858 if (self->engine ==
nullptr) {
862 const uint8_t* action_data =
nullptr;
863 size_t action_data_length = 0;
864 if (data !=
nullptr) {
865 action_data =
static_cast<const uint8_t*
>(
866 g_bytes_get_data(data, &action_data_length));
869 self->embedder_api.DispatchSemanticsAction(self->engine,
id, action,
870 action_data, action_data_length);
875 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
876 return self->embedder_api.MarkExternalTextureFrameAvailable(
882 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
883 return self->embedder_api.RegisterExternalTexture(self->engine,
texture_id) ==
889 g_return_val_if_fail(FL_IS_ENGINE(
self), FALSE);
890 return self->embedder_api.UnregisterExternalTexture(self->engine,
896 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
897 return self->binary_messenger;
901 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
902 return self->task_runner;
906 g_return_if_fail(FL_IS_ENGINE(
self));
907 self->embedder_api.RunTask(self->engine, task);
912 g_return_val_if_fail(FL_IS_ENGINE(
self),
nullptr);
913 return self->texture_registrar;
917 g_return_if_fail(FL_IS_ENGINE(
self));
919 if (self->engine ==
nullptr) {
923 self->embedder_api.UpdateAccessibilityFeatures(
924 self->engine,
static_cast<FlutterAccessibilityFeature
>(
flags));
928 GPtrArray* switches = g_ptr_array_new_with_free_func(g_free);
930 g_ptr_array_add(switches, g_strdup(env_switch.c_str()));