Flutter Linux Embedder
fl_view_accessible.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
10 
11 static constexpr int32_t kRootSemanticsNodeId = 0;
12 
14  AtkPlug parent_instance;
15 
16  FlEngine* engine;
17 
18  // Semantics nodes keyed by ID
19  GHashTable* semantics_nodes_by_id;
20 
21  // Flag to track when root node is created.
23 };
24 
26 
27 G_DEFINE_TYPE(FlViewAccessible, fl_view_accessible, ATK_TYPE_PLUG)
28 
29 static FlAccessibleNode* create_node(FlViewAccessible* self,
30  FlutterSemanticsNode2* semantics) {
31  if (semantics->flags & kFlutterSemanticsFlagIsTextField) {
32  return fl_accessible_text_field_new(self->engine, semantics->id);
33  }
34 
35  return fl_accessible_node_new(self->engine, semantics->id);
36 }
37 
38 static FlAccessibleNode* lookup_node(FlViewAccessible* self, int32_t id) {
39  return FL_ACCESSIBLE_NODE(
40  g_hash_table_lookup(self->semantics_nodes_by_id, GINT_TO_POINTER(id)));
41 }
42 
43 // Gets the ATK node for the given id.
44 // If the node doesn't exist it will be created.
45 static FlAccessibleNode* get_node(FlViewAccessible* self,
46  FlutterSemanticsNode2* semantics) {
47  FlAccessibleNode* node = lookup_node(self, semantics->id);
48  if (node != nullptr) {
49  return node;
50  }
51 
52  node = create_node(self, semantics);
53  if (semantics->id == kRootSemanticsNodeId) {
54  fl_accessible_node_set_parent(node, ATK_OBJECT(self), 0);
55  }
56  g_hash_table_insert(self->semantics_nodes_by_id,
57  GINT_TO_POINTER(semantics->id),
58  reinterpret_cast<gpointer>(node));
59 
60  // Update when root node is created.
61  if (!self->root_node_created && semantics->id == kRootSemanticsNodeId) {
62  g_signal_emit_by_name(self, "children-changed::add", 0, node, nullptr);
63  self->root_node_created = true;
64  }
65 
66  return node;
67 }
68 
69 // Implements AtkObject::get_n_children
70 static gint fl_view_accessible_get_n_children(AtkObject* accessible) {
71  FlViewAccessible* self = FL_VIEW_ACCESSIBLE(accessible);
72  FlAccessibleNode* node = lookup_node(self, 0);
73 
74  if (node == nullptr) {
75  return 0;
76  }
77 
78  return 1;
79 }
80 
81 // Implements AtkObject::ref_child
82 static AtkObject* fl_view_accessible_ref_child(AtkObject* accessible, gint i) {
83  FlViewAccessible* self = FL_VIEW_ACCESSIBLE(accessible);
84  FlAccessibleNode* node = lookup_node(self, 0);
85 
86  if (i != 0 || node == nullptr) {
87  return nullptr;
88  }
89 
90  return ATK_OBJECT(g_object_ref(node));
91 }
92 
93 // Implements AtkObject::get_role
94 static AtkRole fl_view_accessible_get_role(AtkObject* accessible) {
95  return ATK_ROLE_PANEL;
96 }
97 
98 // Implements AtkObject::ref_state_set
99 static AtkStateSet* fl_view_accessible_ref_state_set(AtkObject* accessible) {
100  FlViewAccessible* self = FL_VIEW_ACCESSIBLE(accessible);
101  FlAccessibleNode* node = lookup_node(self, 0);
102  return node != nullptr ? atk_object_ref_state_set(ATK_OBJECT(node)) : nullptr;
103 }
104 
105 static void fl_view_accessible_dispose(GObject* object) {
106  FlViewAccessible* self = FL_VIEW_ACCESSIBLE(object);
107 
108  g_clear_pointer(&self->semantics_nodes_by_id, g_hash_table_unref);
109 
110  if (self->engine != nullptr) {
111  g_object_remove_weak_pointer(object,
112  reinterpret_cast<gpointer*>(&self->engine));
113  self->engine = nullptr;
114  }
115 
116  G_OBJECT_CLASS(fl_view_accessible_parent_class)->dispose(object);
117 }
118 
119 static void fl_view_accessible_class_init(FlViewAccessibleClass* klass) {
120  ATK_OBJECT_CLASS(klass)->get_n_children = fl_view_accessible_get_n_children;
121  ATK_OBJECT_CLASS(klass)->ref_child = fl_view_accessible_ref_child;
122  ATK_OBJECT_CLASS(klass)->get_role = fl_view_accessible_get_role;
123  ATK_OBJECT_CLASS(klass)->ref_state_set = fl_view_accessible_ref_state_set;
124 
125  G_OBJECT_CLASS(klass)->dispose = fl_view_accessible_dispose;
126 }
127 
128 static void fl_view_accessible_init(FlViewAccessible* self) {
129  self->semantics_nodes_by_id = g_hash_table_new_full(
130  g_direct_hash, g_direct_equal, nullptr, g_object_unref);
131 }
132 
133 FlViewAccessible* fl_view_accessible_new(FlEngine* engine) {
134  FlViewAccessible* self =
135  FL_VIEW_ACCESSIBLE(g_object_new(fl_view_accessible_get_type(), nullptr));
136  self->engine = engine;
137  g_object_add_weak_pointer(G_OBJECT(self),
138  reinterpret_cast<gpointer*>(&self->engine));
139  return self;
140 }
141 
143  FlViewAccessible* self,
144  const FlutterSemanticsUpdate2* update) {
145  g_autoptr(GHashTable) pending_children =
146  g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
147  reinterpret_cast<GDestroyNotify>(fl_value_unref));
148  for (size_t i = 0; i < update->node_count; i++) {
149  FlutterSemanticsNode2* node = update->nodes[i];
150  FlAccessibleNode* atk_node = get_node(self, node);
151 
152  fl_accessible_node_set_flags(atk_node, node->flags);
153  fl_accessible_node_set_actions(atk_node, node->actions);
154  fl_accessible_node_set_name(atk_node, node->label);
156  atk_node, node->rect.left + node->transform.transX,
157  node->rect.top + node->transform.transY,
158  node->rect.right - node->rect.left, node->rect.bottom - node->rect.top);
159  fl_accessible_node_set_value(atk_node, node->value);
160  fl_accessible_node_set_text_selection(atk_node, node->text_selection_base,
161  node->text_selection_extent);
162  fl_accessible_node_set_text_direction(atk_node, node->text_direction);
163 
164  FlValue* children = fl_value_new_int32_list(
165  node->children_in_traversal_order, node->child_count);
166  g_hash_table_insert(pending_children, atk_node, children);
167  }
168 
169  g_hash_table_foreach_remove(
170  pending_children,
171  [](gpointer key, gpointer value, gpointer user_data) -> gboolean {
172  FlViewAccessible* self = FL_VIEW_ACCESSIBLE(user_data);
173 
174  FlAccessibleNode* parent = FL_ACCESSIBLE_NODE(key);
175 
176  size_t child_count = fl_value_get_length(static_cast<FlValue*>(value));
177  const int32_t* children_in_traversal_order =
178  fl_value_get_int32_list(static_cast<FlValue*>(value));
179 
180  g_autoptr(GPtrArray) children = g_ptr_array_new();
181  for (size_t i = 0; i < child_count; i++) {
182  FlAccessibleNode* child =
183  lookup_node(self, children_in_traversal_order[i]);
184  g_assert(child != nullptr);
185  fl_accessible_node_set_parent(child, ATK_OBJECT(parent), i);
186  g_ptr_array_add(children, child);
187  }
188  fl_accessible_node_set_children(parent, children);
189 
190  return TRUE;
191  },
192  self);
193 }
kPropLast
@ kPropLast
Definition: fl_view_accessible.cc:25
fl_value_get_int32_list
const G_MODULE_EXPORT int32_t * fl_value_get_int32_list(FlValue *self)
Definition: fl_value.cc:696
get_node
static FlAccessibleNode * get_node(FlViewAccessible *self, FlutterSemanticsNode2 *semantics)
Definition: fl_view_accessible.cc:45
fl_view_accessible.h
kProp0
@ kProp0
Definition: fl_view_accessible.cc:25
fl_view_accessible_handle_update_semantics
void fl_view_accessible_handle_update_semantics(FlViewAccessible *self, const FlutterSemanticsUpdate2 *update)
Definition: fl_view_accessible.cc:142
fl_accessible_node_set_text_selection
void fl_accessible_node_set_text_selection(FlAccessibleNode *self, gint base, gint extent)
Definition: fl_accessible_node.cc:563
fl_view_accessible_ref_child
static AtkObject * fl_view_accessible_ref_child(AtkObject *accessible, gint i)
Definition: fl_view_accessible.cc:82
fl_accessible_node_set_flags
void fl_accessible_node_set_flags(FlAccessibleNode *self, FlutterSemanticsFlag flags)
Definition: fl_accessible_node.cc:543
fl_accessible_node_set_parent
void fl_accessible_node_set_parent(FlAccessibleNode *self, AtkObject *parent, gint index)
Definition: fl_accessible_node.cc:488
fl_accessible_text_field_new
FlAccessibleNode * fl_accessible_text_field_new(FlEngine *engine, int32_t id)
Definition: fl_accessible_text_field.cc:618
i
int i
Definition: fl_socket_accessible.cc:18
_FlViewAccessible::engine
FlEngine * engine
Definition: fl_view_accessible.cc:16
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
_FlViewAccessible::semantics_nodes_by_id
GHashTable * semantics_nodes_by_id
Definition: fl_view_accessible.cc:19
fl_accessible_node_set_children
void fl_accessible_node_set_children(FlAccessibleNode *self, GPtrArray *children)
Definition: fl_accessible_node.cc:499
fl_view_accessible_init
static void fl_view_accessible_init(FlViewAccessible *self)
Definition: fl_view_accessible.cc:128
fl_value_unref
G_MODULE_EXPORT void fl_value_unref(FlValue *self)
Definition: fl_value.cc:400
create_node
static FlAccessibleNode * create_node(FlViewAccessible *self, FlutterSemanticsNode2 *semantics)
Definition: fl_view_accessible.cc:29
fl_view_accessible_dispose
static void fl_view_accessible_dispose(GObject *object)
Definition: fl_view_accessible.cc:105
fl_accessible_node_set_extents
void fl_accessible_node_set_extents(FlAccessibleNode *self, gint x, gint y, gint width, gint height)
Definition: fl_accessible_node.cc:532
kPropEngine
@ kPropEngine
Definition: fl_view_accessible.cc:25
fl_accessible_node_set_text_direction
void fl_accessible_node_set_text_direction(FlAccessibleNode *self, FlutterTextDirection direction)
Definition: fl_accessible_node.cc:572
G_DEFINE_TYPE
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
Definition: fl_basic_message_channel.cc:37
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_accessible_node_set_value
void fl_accessible_node_set_value(FlAccessibleNode *self, const gchar *value)
Definition: fl_accessible_node.cc:557
fl_value_new_int32_list
G_MODULE_EXPORT FlValue * fl_value_new_int32_list(const int32_t *data, size_t data_length)
Definition: fl_value.cc:309
fl_value_get_length
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:724
fl_accessible_node.h
fl_accessible_node_new
FlAccessibleNode * fl_accessible_node_new(FlEngine *engine, int32_t id)
Definition: fl_accessible_node.cc:482
fl_view.h
fl_view_accessible_ref_state_set
static AtkStateSet * fl_view_accessible_ref_state_set(AtkObject *accessible)
Definition: fl_view_accessible.cc:99
_FlViewAccessible
Definition: fl_view_accessible.cc:13
fl_accessible_text_field.h
fl_view_accessible_get_n_children
static gint fl_view_accessible_get_n_children(AtkObject *accessible)
Definition: fl_view_accessible.cc:70
fl_value.h
kRootSemanticsNodeId
static constexpr int32_t kRootSemanticsNodeId
Definition: fl_view_accessible.cc:11
fl_accessible_node_set_name
void fl_accessible_node_set_name(FlAccessibleNode *self, const gchar *name)
Definition: fl_accessible_node.cc:526
fl_accessible_node_set_actions
void fl_accessible_node_set_actions(FlAccessibleNode *self, FlutterSemanticsAction actions)
Definition: fl_accessible_node.cc:550
_FlViewAccessible::parent_instance
AtkPlug parent_instance
Definition: fl_view_accessible.cc:14
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
fl_view_accessible_new
FlViewAccessible * fl_view_accessible_new(FlEngine *engine)
Definition: fl_view_accessible.cc:133
lookup_node
static FlAccessibleNode * lookup_node(FlViewAccessible *self, int32_t id)
Definition: fl_view_accessible.cc:38
fl_view_accessible_get_role
static AtkRole fl_view_accessible_get_role(AtkObject *accessible)
Definition: fl_view_accessible.cc:94
_FlViewAccessible::root_node_created
gboolean root_node_created
Definition: fl_view_accessible.cc:22
fl_view_accessible_class_init
static void fl_view_accessible_class_init(FlViewAccessibleClass *klass)
Definition: fl_view_accessible.cc:119