27 GTK_TYPE_CONTAINER_ACCESSIBLE)
29 static
void init_engine(FlViewAccessible*
self, FlEngine*
engine) {
30 g_assert(
self->engine ==
nullptr);
33 reinterpret_cast<gpointer*
>(&
self->engine));
37 if (
self->engine ==
nullptr) {
38 FlView* view = FL_VIEW(gtk_accessible_get_widget(GTK_ACCESSIBLE(
self)));
45 const FlutterSemanticsNode* semantics) {
48 if (semantics->flags & kFlutterSemanticsFlagIsTextField) {
55 static FlAccessibleNode*
lookup_node(FlViewAccessible*
self, int32_t
id) {
56 return FL_ACCESSIBLE_NODE(
57 g_hash_table_lookup(
self->semantics_nodes_by_id, GINT_TO_POINTER(
id)));
62 static FlAccessibleNode*
get_node(FlViewAccessible*
self,
63 const FlutterSemanticsNode* semantics) {
65 if (
node !=
nullptr) {
70 if (semantics->id == 0) {
72 g_signal_emit_by_name(
self,
"children-changed::add", 0,
node,
nullptr);
74 g_hash_table_insert(
self->semantics_nodes_by_id,
75 GINT_TO_POINTER(semantics->id),
76 reinterpret_cast<gpointer
>(
node));
82 g_hash_table_foreach_remove(
83 self->pending_children,
85 FlViewAccessible* self = FL_VIEW_ACCESSIBLE(user_data);
87 FlAccessibleNode* parent = FL_ACCESSIBLE_NODE(key);
89 size_t child_count = fl_value_get_length(static_cast<FlValue*>(value));
90 const int32_t* children_in_traversal_order =
91 fl_value_get_int32_list(static_cast<FlValue*>(value));
93 g_autoptr(GPtrArray) children = g_ptr_array_new();
94 for (size_t i = 0; i < child_count; i++) {
95 FlAccessibleNode* child =
96 lookup_node(self, children_in_traversal_order[i]);
97 g_assert(child != nullptr);
98 fl_accessible_node_set_parent(child, ATK_OBJECT(parent), i);
99 g_ptr_array_add(children, child);
110 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(accessible);
113 if (
node ==
nullptr) {
122 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(accessible);
125 if (i != 0 ||
node ==
nullptr) {
129 return ATK_OBJECT(g_object_ref(
node));
134 return ATK_ROLE_PANEL;
142 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(
object);
145 init_engine(
self, FL_ENGINE(g_value_get_object(
value)));
148 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
154 FlViewAccessible*
self = FL_VIEW_ACCESSIBLE(
object);
156 g_clear_pointer(&
self->semantics_nodes_by_id, g_hash_table_unref);
157 g_clear_pointer(&
self->pending_children, g_hash_table_unref);
159 if (
self->engine !=
nullptr) {
160 g_object_remove_weak_pointer(
object,
161 reinterpret_cast<gpointer*
>(&
self->engine));
162 self->engine =
nullptr;
165 G_OBJECT_CLASS(fl_view_accessible_parent_class)->dispose(
object);
176 g_object_class_install_property(
179 "engine",
"engine",
"Flutter engine", fl_engine_get_type(),
180 static_cast<GParamFlags
>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
181 G_PARAM_STATIC_STRINGS)));
185 self->semantics_nodes_by_id = g_hash_table_new_full(
186 g_direct_hash, g_direct_equal,
nullptr, g_object_unref);
187 self->pending_children =
188 g_hash_table_new_full(g_direct_hash, g_direct_equal,
nullptr,
193 FlViewAccessible*
self,
194 const FlutterSemanticsNode*
node) {
195 if (
node->id == kFlutterSemanticsNodeIdBatchEnd) {
206 atk_node,
node->rect.left +
node->transform.transX,
207 node->rect.top +
node->transform.transY,
211 node->text_selection_extent);
216 g_hash_table_insert(
self->pending_children, atk_node, children);