1 #include "AccessibleNode.h"
9 std::map<AtspiAccessible *, AccessibleNode *> AccessibleNode::mNodeMap{};
11 AccessibleNode::~AccessibleNode()
16 AccessibleNode::AccessibleNode() : AccessibleNode(nullptr)
18 // No meaning without AtspiAccessbile object
19 // prohibited to create this object with this constructor
22 AccessibleNode::AccessibleNode(AtspiAccessible *node)
23 : mNode(make_gobj_ref_unique(node)), mBoundingBox{0,0,0,0}, mSupportingIfaces(0), mFeatureProperty(0), mIsAlive(true)
25 // prohibited to create this object this constructor
26 // better to use AccessibleNode::get factory method.
28 LOG_SCOPE_F(1, "AccessibleNode constructor %p", mNode.get());
29 GArray *ifaces = atspi_accessible_get_interfaces(mNode.get());
31 for (unsigned int i = 0; i < ifaces->len; i++) {
32 char *iface = g_array_index(ifaces, char *, i);
33 if (!strcmp(iface, "Action"))
35 static_cast<int>(AccessibleNodeInterface::ACTION);
36 else if (!strcmp(iface, "Collection"))
38 static_cast<int>(AccessibleNodeInterface::COLLECTION);
39 else if (!strcmp(iface, "Component"))
41 static_cast<int>(AccessibleNodeInterface::COMPONENT);
42 else if (!strcmp(iface, "Document"))
44 static_cast<int>(AccessibleNodeInterface::DOCUMENT);
45 else if (!strcmp(iface, "EditableText"))
47 static_cast<int>(AccessibleNodeInterface::EDITABLETEXT);
48 else if (!strcmp(iface, "Hypertext"))
50 static_cast<int>(AccessibleNodeInterface::HYPERTEXT);
51 else if (!strcmp(iface, "Image"))
53 static_cast<int>(AccessibleNodeInterface::IMAGE);
54 else if (!strcmp(iface, "Selection"))
56 static_cast<int>(AccessibleNodeInterface::SELECTION);
57 else if (!strcmp(iface, "Text"))
59 static_cast<int>(AccessibleNodeInterface::TEXT);
60 else if (!strcmp(iface, "Value"))
62 static_cast<int>(AccessibleNodeInterface::VALUE);
63 else if (!strcmp(iface, "Accessible"))
65 static_cast<int>(AccessibleNodeInterface::ACCESSIBLE);
66 else if (!strcmp(iface, "Table"))
68 static_cast<int>(AccessibleNodeInterface::TABLE);
69 else if (!strcmp(iface, "TableCell"))
71 static_cast<int>(AccessibleNodeInterface::TABLECELL);
73 LOG_F(WARNING, "Not Supported interface found %s", iface);
78 g_array_free(ifaces, FALSE);
83 std::unique_ptr<AccessibleNode> AccessibleNode::get(AtspiAccessible *node)
85 return std::make_unique<AccessibleNode>(node);
88 void AccessibleNode::refresh() const
90 gchar *rolename = atspi_accessible_get_role_name(mNode.get(), NULL);
96 gchar *uID = atspi_accessible_get_unique_id(mNode.get(), NULL);
102 GHashTable *attributes = atspi_accessible_get_attributes(mNode.get(), NULL);
103 char *t = (char*)g_hash_table_lookup(attributes, "type");
104 char *s = (char*)g_hash_table_lookup(attributes, "style");
106 if (t) mType = std::string(t);
107 if (s) mStyle = std::string(s);
112 g_hash_table_unref(attributes);
114 AtspiStateSet *st = atspi_accessible_get_state_set(mNode.get());
115 GArray *states = atspi_state_set_get_states(st);
117 char *state_name = NULL;
119 for (int i = 0; states && (i < states->len); ++i) {
120 stat = g_array_index(states, AtspiStateType, i);
121 setFeatureProperty(stat);
124 if (states) g_array_free(states, 0);
128 int AccessibleNode::getChildCount() const
130 return atspi_accessible_get_child_count(mNode.get(), NULL);
133 std::unique_ptr<AccessibleNode> AccessibleNode::getChildAt(int index) const
135 AtspiAccessible *child =
136 atspi_accessible_get_child_at_index(mNode.get(), index, NULL);
138 auto node = AccessibleNode::get(child);
139 g_object_unref(child);
142 return AccessibleNode::get(nullptr);
145 std::unique_ptr<AccessibleNode> AccessibleNode::getParent() const
147 AtspiAccessible *parent = atspi_accessible_get_parent(mNode.get(), NULL);
148 auto node = AccessibleNode::get(parent);
149 if (parent) g_object_unref(parent);
153 void AccessibleNode::print(int d, int m) const
155 if (m <= 0 || d > m) return;
161 for (int i = 0; i < n; i++) {
162 auto child = getChildAt(i);
163 if (child) child->print(d + 1, m);
167 void AccessibleNode::print(int d) const
169 char *name = atspi_accessible_get_name(mNode.get(), NULL);
170 char *role = atspi_accessible_get_role_name(mNode.get(), NULL);
171 LOG_F(INFO, "%s - %p(%s) / role:%s, pkg:%s, text:%s",
172 std::string(d, ' ').c_str(), mNode.get(), name, role, getPkg().c_str(),
178 bool AccessibleNode::isSupporting(AccessibleNodeInterface thisIface) const
180 return (mSupportingIfaces & static_cast<int>(thisIface)) != 0;
183 bool AccessibleNode::hasFeatureProperty(NodeFeatureProperties prop) const
185 return (mFeatureProperty & static_cast<int>(prop)) != 0;
188 void AccessibleNode::setFeatureProperty(AtspiStateType type) const
191 LONGCLICKABLE = 0X0040,
195 case ATSPI_STATE_CHECKED:
196 setFeatureProperty(NodeFeatureProperties::CHECKED, true);
198 case ATSPI_STATE_CHECKABLE:
199 setFeatureProperty(NodeFeatureProperties::CHECKABLE, true);
201 case ATSPI_STATE_ENABLED:
202 setFeatureProperty(NodeFeatureProperties::ENABLED, true);
204 case ATSPI_STATE_FOCUSABLE:
205 setFeatureProperty(NodeFeatureProperties::FOCUSABLE, true);
207 case ATSPI_STATE_FOCUSED:
208 setFeatureProperty(NodeFeatureProperties::FOCUSED, true);
210 case ATSPI_STATE_SELECTABLE:
211 setFeatureProperty(NodeFeatureProperties::SELECTABLE, true);
213 case ATSPI_STATE_SELECTED:
214 setFeatureProperty(NodeFeatureProperties::SELECTED, true);
216 case ATSPI_STATE_SHOWING:
217 setFeatureProperty(NodeFeatureProperties::SHOWING, true);
219 case ATSPI_STATE_VISIBLE:
220 setFeatureProperty(NodeFeatureProperties::VISIBLE, true);
222 case ATSPI_STATE_ACTIVE:
223 setFeatureProperty(NodeFeatureProperties::ACTIVE, true);
225 case ATSPI_STATE_SENSITIVE:
226 setFeatureProperty(NodeFeatureProperties::CLICKABLE, true);
229 case ATSPI_STATE_TRANSIENT:
230 case ATSPI_STATE_TRUNCATED:
231 case ATSPI_STATE_ANIMATED:
232 case ATSPI_STATE_INVALID:
233 case ATSPI_STATE_ARMED:
234 case ATSPI_STATE_BUSY:
235 case ATSPI_STATE_COLLAPSED:
236 case ATSPI_STATE_DEFUNCT:
237 case ATSPI_STATE_EDITABLE:
238 case ATSPI_STATE_EXPANDABLE:
239 case ATSPI_STATE_EXPANDED:
240 case ATSPI_STATE_HAS_TOOLTIP:
241 case ATSPI_STATE_HORIZONTAL:
242 case ATSPI_STATE_ICONIFIED:
243 case ATSPI_STATE_MODAL:
244 case ATSPI_STATE_MULTI_LINE:
245 case ATSPI_STATE_MULTISELECTABLE:
246 case ATSPI_STATE_OPAQUE:
247 case ATSPI_STATE_PRESSED:
248 case ATSPI_STATE_RESIZABLE:
249 case ATSPI_STATE_SINGLE_LINE:
250 case ATSPI_STATE_STALE:
251 case ATSPI_STATE_VERTICAL:
252 case ATSPI_STATE_MANAGES_DESCENDANTS:
253 case ATSPI_STATE_INDETERMINATE:
254 case ATSPI_STATE_REQUIRED:
255 case ATSPI_STATE_INVALID_ENTRY:
256 case ATSPI_STATE_SUPPORTS_AUTOCOMPLETION:
257 case ATSPI_STATE_SELECTABLE_TEXT:
258 case ATSPI_STATE_IS_DEFAULT:
259 case ATSPI_STATE_VISITED:
260 case ATSPI_STATE_HAS_POPUP:
261 case ATSPI_STATE_READ_ONLY:
262 case ATSPI_STATE_LAST_DEFINED:
267 void AccessibleNode::setFeatureProperty(NodeFeatureProperties prop, bool has) const
270 mFeatureProperty |= static_cast<int>(prop);
272 mFeatureProperty &= ~static_cast<int>(prop);
275 std::string AccessibleNode::getDesc() const
280 std::string AccessibleNode::getText() const
282 gchar *name = atspi_accessible_get_name(mNode.get(), NULL);
290 std::string AccessibleNode::getPkg() const
295 std::string AccessibleNode::getRes() const
300 std::string AccessibleNode::getType() const
305 std::string AccessibleNode::getStyle() const
310 Rect<int> AccessibleNode::getBoundingBox() const
312 AtspiComponent *component = atspi_accessible_get_component_iface(mNode.get());
314 AtspiRect *extent = atspi_component_get_extents(
315 component, ATSPI_COORD_TYPE_SCREEN, NULL);
318 Rect<int>{extent->x, extent->y, extent->x + extent->width,
319 extent->y + extent->height};
322 g_object_unref(component);
328 bool AccessibleNode::isCheckable() const
330 return hasFeatureProperty(NodeFeatureProperties::CHECKABLE);
333 bool AccessibleNode::isChecked() const
335 return hasFeatureProperty(NodeFeatureProperties::CHECKED);
338 bool AccessibleNode::isClickable() const
340 return hasFeatureProperty(NodeFeatureProperties::CLICKABLE);
343 bool AccessibleNode::isEnabled() const
345 return hasFeatureProperty(NodeFeatureProperties::ENABLED);
348 bool AccessibleNode::isFocusable() const
350 return hasFeatureProperty(NodeFeatureProperties::FOCUSABLE);
353 bool AccessibleNode::isFocused() const
355 return hasFeatureProperty(NodeFeatureProperties::FOCUSED);
358 bool AccessibleNode::isLongClickable() const
360 return hasFeatureProperty(NodeFeatureProperties::LONGCLICKABLE);
363 bool AccessibleNode::isScrollable() const
365 return hasFeatureProperty(NodeFeatureProperties::SCROLLABLE);
368 bool AccessibleNode::isSelectable() const
370 return hasFeatureProperty(NodeFeatureProperties::SELECTABLE);
373 bool AccessibleNode::isSelected() const
375 return hasFeatureProperty(NodeFeatureProperties::SELECTED);
378 bool AccessibleNode::isVisible() const
380 return hasFeatureProperty(NodeFeatureProperties::VISIBLE);
383 bool AccessibleNode::isShowing() const
385 return hasFeatureProperty(NodeFeatureProperties::SHOWING);
388 bool AccessibleNode::isActive() const
390 return hasFeatureProperty(NodeFeatureProperties::ACTIVE);
393 AtspiAccessible *AccessibleNode::getAccessible() const
398 void AccessibleNode::setValue(std::string text) const
400 AtspiEditableText *iface = atspi_accessible_get_editable_text(mNode.get());
401 LOG_F(INFO,"set Value iface:%p obj:%p text:%s", iface, mNode.get(), text.c_str() );
403 int len = getText().length();
404 atspi_editable_text_delete_text(iface, 0, len, NULL);
405 atspi_editable_text_insert_text(iface, 0, text.c_str(), text.length(),
410 std::vector<std::string> AccessibleNode::getActions() const
412 std::vector<std::string> result{};
416 action = atspi_accessible_get_action_iface(mNode.get());
419 int n_actions = atspi_action_get_n_actions(action, NULL);
421 for (a = 0; a < n_actions; a++) {
422 char *action_name = atspi_action_get_action_name(action, a, NULL);
423 if (!action_name) continue;
424 result.push_back(std::string{action_name});
427 g_object_unref(action);
432 bool AccessibleNode::doAction(std::string actionName) const
437 action = atspi_accessible_get_action_iface(mNode.get());
440 int n_actions = atspi_action_get_n_actions(action, NULL);
442 for (a = 0; a < n_actions; a++) {
443 char *action_name = atspi_action_get_action_name(action, a, NULL);
444 if (!action_name) return false;
446 if (!strcmp(actionName.c_str(), action_name)) {
447 atspi_action_do_action(action, a, NULL);
449 g_object_unref(action);
454 g_object_unref(action);