diff --git a/shell/platform/linux/fl_renderer_gl.cc b/shell/platform/linux/fl_renderer_gl.cc index ec44b9b2dc5b8..7210e95954950 100644 --- a/shell/platform/linux/fl_renderer_gl.cc +++ b/shell/platform/linux/fl_renderer_gl.cc @@ -98,17 +98,16 @@ static gboolean fl_renderer_gl_present_layers(FlRenderer* renderer, if (!view || !context) { return FALSE; } - fl_view_begin_frame(view); + g_autoptr(GPtrArray) textures = g_ptr_array_new(); for (size_t i = 0; i < layers_count; ++i) { const FlutterLayer* layer = layers[i]; switch (layer->type) { case kFlutterLayerContentTypeBackingStore: { const FlutterBackingStore* backing_store = layer->backing_store; auto framebuffer = &backing_store->open_gl.framebuffer; - fl_view_add_gl_area( - view, context, - reinterpret_cast(framebuffer->user_data)); + g_ptr_array_add(textures, reinterpret_cast( + framebuffer->user_data)); } break; case kFlutterLayerContentTypePlatformView: { // Currently unsupported. @@ -116,7 +115,8 @@ static gboolean fl_renderer_gl_present_layers(FlRenderer* renderer, } } - fl_view_end_frame(view); + fl_view_set_textures(view, context, textures); + return TRUE; } diff --git a/shell/platform/linux/fl_view.cc b/shell/platform/linux/fl_view.cc index 5229d4d9f391f..5cd4714e77fda 100644 --- a/shell/platform/linux/fl_view.cc +++ b/shell/platform/linux/fl_view.cc @@ -50,13 +50,9 @@ struct _FlView { FlMouseCursorPlugin* mouse_cursor_plugin; FlPlatformPlugin* platform_plugin; - GList* gl_area_list; - GList* used_area_list; - GtkWidget* event_box; GList* children_list; - GList* pending_children_list; // Tracks whether mouse pointer is inside the view. gboolean pointer_inside; @@ -67,11 +63,6 @@ struct _FlView { gulong keymap_keys_changed_cb_id; // Signal connection ID. }; -typedef struct _FlViewChild { - GtkWidget* widget; - GdkRectangle geometry; -} FlViewChild; - enum { kPropFlutterProject = 1, kPropLast }; static void fl_view_plugin_registry_iface_init( @@ -213,33 +204,6 @@ static void handle_geometry_changed(FlView* self) { } } -// Adds a widget to render in this view. -static void add_pending_child(FlView* self, - GtkWidget* widget, - GdkRectangle* geometry) { - FlViewChild* child = g_new(FlViewChild, 1); - child->widget = widget; - if (geometry) { - child->geometry = *geometry; - } else { - child->geometry = {0, 0, 0, 0}; - } - - self->pending_children_list = - g_list_append(self->pending_children_list, child); -} - -// Finds the node with the specified widget in a list of FlViewChild. -static GList* find_child(GList* list, GtkWidget* widget) { - for (GList* i = list; i; i = i->next) { - FlViewChild* child = reinterpret_cast(i->data); - if (child && child->widget == widget) { - return i; - } - } - return nullptr; -} - // Called when the engine updates accessibility nodes. static void update_semantics_node_cb(FlEngine* engine, const FlutterSemanticsNode* node, @@ -627,8 +591,8 @@ static void fl_view_dispose(GObject* object) { } g_clear_object(&self->mouse_cursor_plugin); g_clear_object(&self->platform_plugin); - g_list_free_full(self->gl_area_list, g_object_unref); - self->gl_area_list = nullptr; + g_list_free_full(self->children_list, g_object_unref); + self->children_list = nullptr; G_OBJECT_CLASS(fl_view_parent_class)->dispose(object); } @@ -686,16 +650,16 @@ static void fl_view_get_preferred_width(GtkWidget* widget, for (GList* iterator = self->children_list; iterator; iterator = iterator->next) { - FlViewChild* child = reinterpret_cast(iterator->data); + GtkWidget* w = reinterpret_cast(iterator->data); - if (!gtk_widget_get_visible(child->widget)) { + if (!gtk_widget_get_visible(w)) { continue; } - gtk_widget_get_preferred_width(child->widget, &child_min, &child_nat); + gtk_widget_get_preferred_width(w, &child_min, &child_nat); - *minimum = MAX(*minimum, child->geometry.x + child_min); - *natural = MAX(*natural, child->geometry.x + child_nat); + *minimum = MAX(*minimum, child_min); + *natural = MAX(*natural, child_nat); } } @@ -711,16 +675,16 @@ static void fl_view_get_preferred_height(GtkWidget* widget, for (GList* iterator = self->children_list; iterator; iterator = iterator->next) { - FlViewChild* child = reinterpret_cast(iterator->data); + GtkWidget* w = reinterpret_cast(iterator->data); - if (!gtk_widget_get_visible(child->widget)) { + if (!gtk_widget_get_visible(w)) { continue; } - gtk_widget_get_preferred_height(child->widget, &child_min, &child_nat); + gtk_widget_get_preferred_height(w, &child_min, &child_nat); - *minimum = MAX(*minimum, child->geometry.y + child_min); - *natural = MAX(*natural, child->geometry.y + child_nat); + *minimum = MAX(*minimum, child_min); + *natural = MAX(*natural, child_nat); } } @@ -741,14 +705,14 @@ static void fl_view_size_allocate(GtkWidget* widget, for (GList* iterator = self->children_list; iterator; iterator = iterator->next) { - FlViewChild* child = reinterpret_cast(iterator->data); - if (!gtk_widget_get_visible(child->widget)) { + GtkWidget* w = reinterpret_cast(iterator->data); + if (!gtk_widget_get_visible(w)) { continue; } - GtkAllocation child_allocation = child->geometry; + GtkAllocation child_allocation = {0, 0, 0, 0}; GtkRequisition child_requisition; - gtk_widget_get_preferred_size(child->widget, &child_requisition, NULL); + gtk_widget_get_preferred_size(w, &child_requisition, nullptr); if (!gtk_widget_get_has_window(widget)) { child_allocation.x += allocation->x; @@ -760,7 +724,7 @@ static void fl_view_size_allocate(GtkWidget* widget, child_allocation.height = allocation->height; } - gtk_widget_size_allocate(child->widget, &child_allocation); + gtk_widget_size_allocate(w, &child_allocation); } GtkAllocation event_box_allocation = { @@ -778,22 +742,6 @@ static void fl_view_size_allocate(GtkWidget* widget, handle_geometry_changed(self); } -struct _ReorderData { - GdkWindow* parent_window; - GdkWindow* last_window; -}; - -static void fl_view_reorder_forall(GtkWidget* widget, gpointer user_data) { - _ReorderData* data = reinterpret_cast<_ReorderData*>(user_data); - GdkWindow* window = gtk_widget_get_window(widget); - if (window && window != data->parent_window) { - if (data->last_window) { - gdk_window_restack(window, data->last_window, TRUE); - } - data->last_window = window; - } -} - // Implements GtkWidget::key_press_event. static gboolean fl_view_key_press_event(GtkWidget* widget, GdkEventKey* event) { FlView* self = FL_VIEW(widget); @@ -812,26 +760,12 @@ static gboolean fl_view_key_release_event(GtkWidget* widget, reinterpret_cast(event)))); } -static void put_widget(FlView* self, - GtkWidget* widget, - GdkRectangle* geometry) { - FlViewChild* child = g_new(FlViewChild, 1); - child->widget = widget; - child->geometry = *geometry; - - gtk_widget_set_parent(widget, GTK_WIDGET(self)); - self->children_list = g_list_append(self->children_list, child); -} - // Implements GtkContainer::add static void fl_view_add(GtkContainer* container, GtkWidget* widget) { - GdkRectangle geometry = { - .x = 0, - .y = 0, - .width = 0, - .height = 0, - }; - put_widget(FL_VIEW(container), widget, &geometry); + FlView* self = FL_VIEW(container); + + gtk_widget_set_parent(widget, GTK_WIDGET(self)); + self->children_list = g_list_append(self->children_list, widget); } // Implements GtkContainer::remove @@ -839,13 +773,12 @@ static void fl_view_remove(GtkContainer* container, GtkWidget* widget) { FlView* self = FL_VIEW(container); for (GList* iterator = self->children_list; iterator; iterator = iterator->next) { - FlViewChild* child = reinterpret_cast(iterator->data); - if (child->widget == widget) { + GtkWidget* w = reinterpret_cast(iterator->data); + if (w == widget) { g_object_ref(widget); gtk_widget_unparent(widget); self->children_list = g_list_remove_link(self->children_list, iterator); g_list_free(iterator); - g_free(child); break; } @@ -864,8 +797,8 @@ static void fl_view_forall(GtkContainer* container, FlView* self = FL_VIEW(container); for (GList* iterator = self->children_list; iterator; iterator = iterator->next) { - FlViewChild* child = reinterpret_cast(iterator->data); - (*callback)(child->widget, callback_data); + GtkWidget* w = reinterpret_cast(iterator->data); + (*callback)(w, callback_data); } if (include_internals) { @@ -937,84 +870,47 @@ G_MODULE_EXPORT FlView* fl_view_new(FlDartProject* project) { g_object_new(fl_view_get_type(), "flutter-project", project, nullptr)); } -G_MODULE_EXPORT FlEngine* fl_view_get_engine(FlView* view) { - g_return_val_if_fail(FL_IS_VIEW(view), nullptr); - return view->engine; +G_MODULE_EXPORT FlEngine* fl_view_get_engine(FlView* self) { + g_return_val_if_fail(FL_IS_VIEW(self), nullptr); + return self->engine; } -void fl_view_begin_frame(FlView* view) { - g_return_if_fail(FL_IS_VIEW(view)); - FlView* self = FL_VIEW(view); +void fl_view_set_textures(FlView* self, + GdkGLContext* context, + GPtrArray* textures) { + g_return_if_fail(FL_IS_VIEW(self)); - self->used_area_list = self->gl_area_list; - g_list_free_full(self->pending_children_list, g_free); - self->pending_children_list = nullptr; -} + guint children_length = g_list_length(self->children_list); -void fl_view_add_gl_area(FlView* view, - GdkGLContext* context, - FlBackingStoreProvider* texture) { - g_return_if_fail(FL_IS_VIEW(view)); + // Add more GL areas if we need them. + for (guint i = children_length; i < textures->len; i++) { + FlGLArea* area = FL_GL_AREA(fl_gl_area_new(context)); - FlGLArea* area; - if (view->used_area_list) { - area = reinterpret_cast(view->used_area_list->data); - view->used_area_list = view->used_area_list->next; - } else { - area = FL_GL_AREA(fl_gl_area_new(context)); - view->gl_area_list = g_list_append(view->gl_area_list, area); - } + gtk_widget_set_parent(GTK_WIDGET(area), GTK_WIDGET(self)); + gtk_widget_show(GTK_WIDGET(area)); - gtk_widget_show(GTK_WIDGET(area)); - add_pending_child(view, GTK_WIDGET(area), nullptr); - fl_gl_area_queue_render(area, texture); -} + // Stack above previous areas but below the event box. + gdk_window_restack(gtk_widget_get_window(GTK_WIDGET(area)), + gtk_widget_get_window(self->event_box), FALSE); -void fl_view_add_widget(FlView* view, - GtkWidget* widget, - GdkRectangle* geometry) { - gtk_widget_show(widget); - add_pending_child(view, widget, geometry); -} - -void fl_view_end_frame(FlView* view) { - for (GList* pending_child = view->pending_children_list; pending_child; - pending_child = pending_child->next) { - FlViewChild* pending_view_child = - reinterpret_cast(pending_child->data); - GList* child = find_child(view->children_list, pending_view_child->widget); - - if (child) { - // existing child - g_free(child->data); - child->data = nullptr; - } else { - // newly added child - gtk_widget_set_parent(pending_view_child->widget, GTK_WIDGET(view)); - } + self->children_list = g_list_append(self->children_list, area); } - for (GList* child = view->children_list; child; child = child->next) { - FlViewChild* view_child = reinterpret_cast(child->data); - if (view_child) { - // removed child - g_object_ref(view_child->widget); - gtk_widget_unparent(view_child->widget); - g_free(view_child); - child->data = nullptr; - } + // Remove unused GL areas. + for (guint i = textures->len; i < children_length; i++) { + FlGLArea* area = FL_GL_AREA(g_list_first(self->children_list)->data); + gtk_widget_unparent(GTK_WIDGET(area)); + g_object_unref(area); + self->children_list = + g_list_remove_link(self->children_list, self->children_list); } - g_list_free(view->children_list); - view->children_list = view->pending_children_list; - view->pending_children_list = nullptr; - - struct _ReorderData data = { - .parent_window = gtk_widget_get_window(GTK_WIDGET(view)), - .last_window = nullptr, - }; - - gtk_container_forall(GTK_CONTAINER(view), fl_view_reorder_forall, &data); + GList* area_link = self->children_list; + for (guint i = 0; i < textures->len; i++, area_link = area_link->next) { + FlBackingStoreProvider* texture = + FL_BACKING_STORE_PROVIDER(g_ptr_array_index(textures, i)); + fl_gl_area_queue_render(FL_GL_AREA(area_link->data), texture); + } - gtk_widget_queue_draw(GTK_WIDGET(view)); + gtk_widget_queue_draw(GTK_WIDGET(self)); } diff --git a/shell/platform/linux/fl_view_private.h b/shell/platform/linux/fl_view_private.h index 693c937231528..f9650227a88e5 100644 --- a/shell/platform/linux/fl_view_private.h +++ b/shell/platform/linux/fl_view_private.h @@ -10,46 +10,16 @@ #include "flutter/shell/platform/linux/fl_gl_area.h" /** - * fl_view_begin_frame: + * fl_view_set_textures: * @view: an #FlView. + * @context: a #GdkGLContext, for #FlGLArea to render. + * @textures: (transfer none) (element-type FlBackingStoreProvider): a list of + * #FlBackingStoreProvider. * - * Reset children of #FlView a stacked #GtkContainer. - * This function is always paired with fl_view_end_frame. + * Set the textures for this view to render. */ -void fl_view_begin_frame(FlView* view); - -/** - * fl_view_add_gl_area: - * @view: an #FlView. - * @context: (transfer full): a #GdkGLContext, for #FlGLArea to render. - * @texture: (transfer full): texture for OpenGL area to render. - * - * Append an #FlGLArea at top of stacked children of #FlView. - * This function must be called after fl_view_begin_frame, and - * before fl_view_end_frame. - */ -void fl_view_add_gl_area(FlView* view, - GdkGLContext* context, - FlBackingStoreProvider* texture); - -/** - * fl_view_add_widget: - * @view: an #FlView. - * @widget: a #GtkWidget. - * @geometry: geometry of the widget. - * - * Append a #GtkWidget at top of stacked children of #FlView. - */ -void fl_view_add_widget(FlView* view, - GtkWidget* widget, - GdkRectangle* geometry); - -/** - * fl_view_end_frame: - * @view: an #FlView. - * - * Apply changes made by fl_view_add_gl_area and fl_view_add_widget. - */ -void fl_view_end_frame(FlView* view); +void fl_view_set_textures(FlView* view, + GdkGLContext* context, + GPtrArray* textures); #endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_VIEW_PRIVATE_H_