From 6f6f57f38fe05147da73d0e4eb724bb04ed42686 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Fri, 11 Mar 2022 19:50:06 +1300 Subject: [PATCH] Fix signals adding/removing a11y nodes in Linux. (flutter/engine#31601) --- .../platform/linux/fl_accessible_node.cc | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/engine/src/flutter/shell/platform/linux/fl_accessible_node.cc b/engine/src/flutter/shell/platform/linux/fl_accessible_node.cc index aec50aef872..71ce50c16df 100644 --- a/engine/src/flutter/shell/platform/linux/fl_accessible_node.cc +++ b/engine/src/flutter/shell/platform/linux/fl_accessible_node.cc @@ -121,6 +121,17 @@ static ActionData* get_action(FlAccessibleNode* self, gint index) { return static_cast(g_ptr_array_index(self->actions, index)); } +// Checks if [object] is in [children]. +static gboolean has_child(GPtrArray* children, AtkObject* object) { + for (guint i = 0; i < children->len; i++) { + if (g_ptr_array_index(children, i) == object) { + return TRUE; + } + } + + return FALSE; +} + static void fl_accessible_node_dispose(GObject* object) { FlAccessibleNode* self = FL_ACCESSIBLE_NODE(object); @@ -340,11 +351,25 @@ void fl_accessible_node_set_children(FlAccessibleNode* self, GPtrArray* children) { g_return_if_fail(FL_IS_ACCESSIBLE_NODE(self)); - g_ptr_array_remove_range(self->children, 0, self->children->len); + // Remove nodes that are no longer required. + for (guint i = 0; i < self->children->len;) { + AtkObject* object = ATK_OBJECT(g_ptr_array_index(self->children, i)); + if (has_child(children, object)) { + i++; + } else { + g_signal_emit_by_name(self, "children-changed::remove", i, object, + nullptr); + g_ptr_array_remove_index(self->children, i); + } + } + + // Add new nodes. for (guint i = 0; i < children->len; i++) { AtkObject* object = ATK_OBJECT(g_ptr_array_index(children, i)); - g_ptr_array_add(self->children, g_object_ref(object)); - g_signal_emit_by_name(self, "children-changed::add", i, object, nullptr); + if (!has_child(self->children, object)) { + g_ptr_array_add(self->children, g_object_ref(object)); + g_signal_emit_by_name(self, "children-changed::add", i, object, nullptr); + } } }