24 GTK_TYPE_CONTAINER_ACCESSIBLE)
26 static
void init_engine(FlViewAccessible* self, FlEngine*
engine) {
27 g_assert(self->engine ==
nullptr);
30 reinterpret_cast<gpointer*
>(&self->engine));
34 if (self->engine ==
nullptr) {
35 FlView* view = FL_VIEW(gtk_accessible_get_widget(GTK_ACCESSIBLE(
self)));
42 FlutterSemanticsNode2* semantics) {
45 if (semantics->flags & kFlutterSemanticsFlagIsTextField) {
52 static FlAccessibleNode*
lookup_node(FlViewAccessible*
self, int32_t
id) {
53 return FL_ACCESSIBLE_NODE(
54 g_hash_table_lookup(self->semantics_nodes_by_id, GINT_TO_POINTER(
id)));
59 static FlAccessibleNode*
get_node(FlViewAccessible*
self,
60 FlutterSemanticsNode2* semantics) {
61 FlAccessibleNode* node =
lookup_node(
self, semantics->id);
62 if (node !=
nullptr) {
67 if (semantics->id == 0) {
69 g_signal_emit_by_name(
self,
"children-changed::add", 0, node,
nullptr);
71 g_hash_table_insert(self->semantics_nodes_by_id,
72 GINT_TO_POINTER(semantics->id),
73 reinterpret_cast<gpointer
>(node));
80 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(accessible);
83 if (node ==
nullptr) {
92 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(accessible);
95 if (i != 0 || node ==
nullptr) {
99 return ATK_OBJECT(g_object_ref(node));
104 return ATK_ROLE_PANEL;
112 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(
object);
115 init_engine(
self, FL_ENGINE(g_value_get_object(
value)));
118 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object,
prop_id,
pspec);
124 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(
object);
126 g_clear_pointer(&self->semantics_nodes_by_id, g_hash_table_unref);
128 if (self->engine !=
nullptr) {
129 g_object_remove_weak_pointer(
object,
130 reinterpret_cast<gpointer*
>(&self->engine));
131 self->engine =
nullptr;
134 G_OBJECT_CLASS(fl_view_accessible_parent_class)->dispose(
object);
145 g_object_class_install_property(
148 "engine",
"engine",
"Flutter engine", fl_engine_get_type(),
149 static_cast<GParamFlags
>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
150 G_PARAM_STATIC_STRINGS)));
154 self->semantics_nodes_by_id = g_hash_table_new_full(
155 g_direct_hash, g_direct_equal,
nullptr, g_object_unref);
159 FlViewAccessible*
self,
160 const FlutterSemanticsUpdate2*
update) {
161 g_autoptr(GHashTable) pending_children =
162 g_hash_table_new_full(g_direct_hash, g_direct_equal,
nullptr,
165 for (
size_t i = 0; i <
update->node_count; i++) {
166 FlutterSemanticsNode2* node =
update->nodes[i];
167 FlAccessibleNode* atk_node =
get_node(
self, node);
173 atk_node, node->rect.left + node->transform.transX,
174 node->rect.top + node->transform.transY,
175 node->rect.right - node->rect.left, node->rect.bottom - node->rect.top);
178 node->text_selection_extent);
182 node->children_in_traversal_order, node->child_count);
183 g_hash_table_insert(pending_children, atk_node, children);
186 g_hash_table_foreach_remove(
188 [](gpointer key, gpointer
value, gpointer
user_data) -> gboolean {
189 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(
user_data);
191 FlAccessibleNode* parent = FL_ACCESSIBLE_NODE(key);
194 const int32_t* children_in_traversal_order =
197 g_autoptr(GPtrArray) children = g_ptr_array_new();
198 for (
size_t i = 0; i < child_count; i++) {
199 FlAccessibleNode* child =
201 g_assert(child !=
nullptr);
203 g_ptr_array_add(children, child);