diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 4497a763ed419..29b47a92fdc43 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1239,6 +1239,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar_private.h FILE: ../../../flutter/shell/platform/linux/fl_plugin_registry.cc FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc FILE: ../../../flutter/shell/platform/linux/fl_renderer.h +FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc +FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.h FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.cc FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.h FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec.cc diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index b64394e94e792..08b81bb6a10c5 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -94,6 +94,7 @@ source_set("flutter_linux_sources") { "fl_plugin_registrar.cc", "fl_plugin_registry.cc", "fl_renderer.cc", + "fl_renderer_headless.cc", "fl_renderer_x11.cc", "fl_standard_message_codec.cc", "fl_standard_method_codec.cc", diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index c1fd69e48f706..dd292d5f3b184 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -6,7 +6,10 @@ #include "flutter/shell/platform/linux/fl_engine_private.h" #include "flutter/shell/platform/linux/fl_binary_messenger_private.h" +#include "flutter/shell/platform/linux/fl_plugin_registrar_private.h" #include "flutter/shell/platform/linux/fl_renderer.h" +#include "flutter/shell/platform/linux/fl_renderer_headless.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h" #include @@ -35,7 +38,15 @@ struct _FlEngine { G_DEFINE_QUARK(fl_engine_error_quark, fl_engine_error) -G_DEFINE_TYPE(FlEngine, fl_engine, G_TYPE_OBJECT) +static void fl_engine_plugin_registry_iface_init( + FlPluginRegistryInterface* iface); + +G_DEFINE_TYPE_WITH_CODE( + FlEngine, + fl_engine, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(), + fl_engine_plugin_registry_iface_init)) // Subclass of GSource that integrates Flutter tasks into the GLib main loop. typedef struct { @@ -169,6 +180,20 @@ static void fl_engine_platform_message_response_cb(const uint8_t* data, (GDestroyNotify)g_bytes_unref); } +// Implements FlPluginRegistry::get_registrar_for_plugin. +static FlPluginRegistrar* fl_engine_get_registrar_for_plugin( + FlPluginRegistry* registry, + const gchar* name) { + FlEngine* self = FL_ENGINE(registry); + + return fl_plugin_registrar_new(nullptr, self->binary_messenger); +} + +static void fl_engine_plugin_registry_iface_init( + FlPluginRegistryInterface* iface) { + iface->get_registrar_for_plugin = fl_engine_get_registrar_for_plugin; +} + static void fl_engine_dispose(GObject* object) { FlEngine* self = FL_ENGINE(object); @@ -210,13 +235,17 @@ FlEngine* fl_engine_new(FlDartProject* project, FlRenderer* renderer) { g_return_val_if_fail(FL_IS_DART_PROJECT(project), nullptr); g_return_val_if_fail(FL_IS_RENDERER(renderer), nullptr); - FlEngine* self = - static_cast(g_object_new(fl_engine_get_type(), nullptr)); - self->project = static_cast(g_object_ref(project)); - self->renderer = static_cast(g_object_ref(renderer)); + FlEngine* self = FL_ENGINE(g_object_new(fl_engine_get_type(), nullptr)); + self->project = FL_DART_PROJECT(g_object_ref(project)); + self->renderer = FL_RENDERER(g_object_ref(renderer)); return self; } +G_MODULE_EXPORT FlEngine* fl_engine_new_headless(FlDartProject* project) { + g_autoptr(FlRendererHeadless) renderer = fl_renderer_headless_new(); + return fl_engine_new(project, FL_RENDERER(renderer)); +} + gboolean fl_engine_start(FlEngine* self, GError** error) { g_return_val_if_fail(FL_IS_ENGINE(self), FALSE); diff --git a/shell/platform/linux/fl_plugin_registrar.cc b/shell/platform/linux/fl_plugin_registrar.cc index 093a16e0e9bd5..9ca72258b6e73 100644 --- a/shell/platform/linux/fl_plugin_registrar.cc +++ b/shell/platform/linux/fl_plugin_registrar.cc @@ -48,14 +48,15 @@ static void fl_plugin_registrar_init(FlPluginRegistrar* self) {} FlPluginRegistrar* fl_plugin_registrar_new(FlView* view, FlBinaryMessenger* messenger) { - g_return_val_if_fail(FL_IS_VIEW(view), nullptr); + g_return_val_if_fail(view == nullptr || FL_IS_VIEW(view), nullptr); g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr); FlPluginRegistrar* self = FL_PLUGIN_REGISTRAR( g_object_new(fl_plugin_registrar_get_type(), nullptr)); self->view = view; - g_object_weak_ref(G_OBJECT(view), view_weak_notify_cb, self); + if (view != nullptr) + g_object_weak_ref(G_OBJECT(view), view_weak_notify_cb, self); self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger)); return self; diff --git a/shell/platform/linux/fl_plugin_registrar_private.h b/shell/platform/linux/fl_plugin_registrar_private.h index 3a3b753d8a3fe..712f32a3d98c3 100644 --- a/shell/platform/linux/fl_plugin_registrar_private.h +++ b/shell/platform/linux/fl_plugin_registrar_private.h @@ -12,7 +12,8 @@ G_BEGIN_DECLS /** * fl_plugin_registrar_new: - * @view: the #FlView that is being plugged into. + * @view: (allow-none): the #FlView that is being plugged into or %NULL for + * headless mode. * @messenger: the #FlBinaryMessenger to communicate with. * * Creates a new #FlPluginRegistrar. diff --git a/shell/platform/linux/fl_renderer_headless.cc b/shell/platform/linux/fl_renderer_headless.cc new file mode 100644 index 0000000000000..90f917a2b316f --- /dev/null +++ b/shell/platform/linux/fl_renderer_headless.cc @@ -0,0 +1,29 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fl_renderer_headless.h" + +struct _FlRendererHeadless { + FlRenderer parent_instance; +}; + +G_DEFINE_TYPE(FlRendererHeadless, fl_renderer_headless, fl_renderer_get_type()) + +static EGLSurface fl_renderer_headless_create_surface(FlRenderer* renderer, + EGLDisplay display, + EGLConfig config) { + return EGL_NO_SURFACE; +} + +static void fl_renderer_headless_class_init(FlRendererHeadlessClass* klass) { + FL_RENDERER_CLASS(klass)->create_surface = + fl_renderer_headless_create_surface; +} + +static void fl_renderer_headless_init(FlRendererHeadless* self) {} + +FlRendererHeadless* fl_renderer_headless_new() { + return FL_RENDERER_HEADLESS( + g_object_new(fl_renderer_headless_get_type(), nullptr)); +} diff --git a/shell/platform/linux/fl_renderer_headless.h b/shell/platform/linux/fl_renderer_headless.h new file mode 100644 index 0000000000000..7fac33d818f58 --- /dev/null +++ b/shell/platform/linux/fl_renderer_headless.h @@ -0,0 +1,36 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ + +#include "flutter/shell/platform/linux/fl_renderer.h" + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE(FlRendererHeadless, + fl_renderer_headless, + FL, + RENDERER_HEADLESS, + FlRenderer) + +/** + * FlRendererHeadless: + * + * #FlRendererHeadless is an implementation of #FlRenderer that works without a + * display. + */ + +/** + * fl_renderer_headless_new: + * + * Creates an object that allows Flutter to operate without a display. + * + * Returns: a new #FlRendererHeadless. + */ +FlRendererHeadless* fl_renderer_headless_new(); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ diff --git a/shell/platform/linux/public/flutter_linux/fl_engine.h b/shell/platform/linux/public/flutter_linux/fl_engine.h index 62997228781d8..201c38f4a06d2 100644 --- a/shell/platform/linux/public/flutter_linux/fl_engine.h +++ b/shell/platform/linux/public/flutter_linux/fl_engine.h @@ -24,6 +24,16 @@ G_DECLARE_FINAL_TYPE(FlEngine, fl_engine, FL, ENGINE, GObject) * #FlEngine is an object that contains a running Flutter engine. */ +/** + * fl_engine_new_headless: + * @project: an #FlDartProject. + * + * Creates new Flutter engine running in headless mode. + * + * Returns: a new #FlEngine. + */ +FlEngine* fl_engine_new_headless(FlDartProject* project); + /** * fl_engine_get_binary_messenger: * @engine: an #FlEngine.