2 # include "elementary_config.h"
5 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
6 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
7 #define ELM_INTERFACE_ATSPI_ACTION_PROTECTED
8 #define ELM_INTERFACE_ATSPI_VALUE_PROTECTED
9 #define ELM_INTERFACE_ATSPI_IMAGE_PROTECTED
10 #define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED
11 #define ELM_INTERFACE_ATSPI_TEXT_PROTECTED
12 #define ELM_INTERFACE_ATSPI_EDITABLE_TEXT_PROTECTED
14 #include "atspi/atspi-constants.h"
17 #include <Elementary.h>
21 * Accessibility Bus info not defined in atspi-constants.h
23 #define A11Y_DBUS_NAME "org.a11y.Bus"
24 #define A11Y_DBUS_PATH "/org/a11y/bus"
25 #define A11Y_DBUS_INTERFACE "org.a11y.Bus"
26 #define A11Y_DBUS_STATUS_INTERFACE "org.a11y.Status"
27 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
28 #define A11Y_DBUS_ENABLED_PROPERTY "IsEnabled"
30 #define ATSPI_DBUS_INTERFACE_EVENT_WINDOW "org.a11y.atspi.Event.Window"
32 #define CACHE_ITEM_SIGNATURE "((so)(so)(so)a(so)assusau)"
33 #define CACHE_INTERFACE_PATH "/org/a11y/atspi/cache"
35 #define ELM_ACCESS_OBJECT_PATH_ROOT "root"
36 #define ELM_ACCESS_OBJECT_PATH_PREFIX "/org/a11y/atspi/accessible/"
37 #define ELM_ACCESS_OBJECT_PATH_PREFIX2 "/org/a11y/atspi/accessible"
38 #define ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE ELM_ACCESS_OBJECT_PATH_PREFIX "%llu"
40 #define ELM_ATSPI_DBUS_INTERFACE_PROXY "elm.atspi.bridge.proxy.Socket"
41 //TIZEN_ONLY(20160527) - Add direct reading feature
42 #define ELM_ATSPI_DIRECT_READ_BUS "org.tizen.ScreenReader"
43 #define ELM_ATSPI_DIRECT_READ_PATH "/org/tizen/DirectReading"
44 #define ELM_ATSPI_DIRECT_READ_INTERFACE "org.tizen.DirectReading"
45 struct _Elm_Atspi_Say_Info
48 Elm_Atspi_Say_Signal_Cb func; //this function will be called when state of related reading is changed
50 typedef struct _Elm_Atspi_Say_Info Elm_Atspi_Say_Info;
51 static Eina_Hash *read_command_id = NULL;
53 #define SIZE(x) sizeof(x)/sizeof(x[0])
54 #define ELM_ATSPI_BRIDGE_CLASS_NAME "__Elm_Atspi_Bridge"
56 #define ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, sd) \
57 Elm_Atspi_Bridge_Data *sd = eo_data_scope_get(obj, ELM_ATSPI_BRIDGE_CLASS); \
60 #define ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(obj, sd, val) \
61 Elm_Atspi_Bridge_Data *sd = eo_data_scope_get(obj, ELM_ATSPI_BRIDGE_CLASS); \
64 #define ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, class, msg, error) \
65 if (!(obj) || !eo_isa(obj, class)) \
67 *(error) = _dbus_invalid_ref_error_new(msg); \
71 #define ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, class, msg) \
72 if (!(obj) || !eo_isa(obj, class)) \
73 return _dbus_invalid_ref_error_new(msg);
75 typedef struct Key_Event_Info {
76 Ecore_Event_Key event;
81 typedef struct _Elm_Atspi_Bridge_Data
83 Eldbus_Connection *session_bus;
84 Eldbus_Connection *a11y_bus;
85 Eina_List *reemited_events;
88 Eldbus_Service_Interface *cache_interface;
89 Eldbus_Signal_Handler *register_hdl;
90 Eldbus_Signal_Handler *unregister_hdl;
91 //TIZEN_ONLY(20160614):apply callbacks on direct reading stop/cancel/skipp
92 Eldbus_Signal_Handler *reading_state_changed_hdl;
94 unsigned long object_broadcast_mask;
95 unsigned long object_property_broadcast_mask;
96 unsigned long object_children_broadcast_mask;
97 unsigned long long object_state_broadcast_mask;
98 unsigned long long window_signal_broadcast_mask;
99 Ecore_Event_Filter *key_flr;
100 Eldbus_Object *bus_obj;
101 Eina_List *pending_requests;
103 Eina_Hash *state_hash;
105 Eldbus_Service_Interface *accessible;
106 Eldbus_Service_Interface *application;
107 Eldbus_Service_Interface *action;
108 Eldbus_Service_Interface *component;
109 Eldbus_Service_Interface *collection;
110 Eldbus_Service_Interface *editable_text;
111 Eldbus_Service_Interface *image;
112 Eldbus_Service_Interface *selection;
113 Eldbus_Service_Interface *text;
114 Eldbus_Service_Interface *value;
115 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
116 Eldbus_Service_Interface *socket;
119 Elm_Atspi_Event_Handler *event_hdlr;
120 Eina_Hash *event_hash;
121 Eina_List *socket_queue;
122 Eina_List *plug_queue;
123 Eina_Bool connected : 1;
124 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
125 Eina_Bool window_activated : 1;
126 // TIZEN_ONLY(20170512): send window activated event to at_spi2 only once per session
127 Eina_Bool window_activated_broadcast_needed : 1;
128 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
129 Eina_Bool screen_reader_enabled : 1;
131 } Elm_Atspi_Bridge_Data;
134 struct collection_match_rule {
135 Elm_Atspi_State_Set states;
136 AtspiCollectionMatchType statematchtype;
137 Eina_List *attributes;
138 AtspiCollectionMatchType attributematchtype;
140 AtspiCollectionMatchType rolematchtype;
142 AtspiCollectionMatchType interfacematchtype;
143 Eina_Bool reverse : 1;
146 static Eo *_instance;
147 static int _init_count = 0;
148 static const char *_a11y_socket_address;
150 // Object Event handlers
151 static Eina_Bool _state_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
152 static Eina_Bool _property_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
153 static Eina_Bool _bounds_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
154 static Eina_Bool _children_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
155 static Eina_Bool _window_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
156 static Eina_Bool _visible_data_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
157 static Eina_Bool _active_descendant_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
158 static Eina_Bool _selection_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
159 static Eina_Bool _text_text_inserted_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
160 static Eina_Bool _text_text_removed_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
161 static Eina_Bool _text_caret_moved_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
162 static Eina_Bool _text_selection_changed_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info EINA_UNUSED);
163 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
164 static Eina_Bool _move_outed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
167 // bridge private methods
168 static void _bridge_cache_build(Eo *bridge, void *obj);
169 static void _bridge_object_register(Eo *bridge, Eo *obj);
170 static void _bridge_object_unregister(Eo *bridge, Eo *obj);
171 static const char * _bridge_path_from_object(Eo *bridge, const Eo *eo);
172 static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *ifc, const Eldbus_Signal *signal, const char *minor, unsigned int det1, unsigned int det2, const char *variant_sig, ...);
173 static Eo * _bridge_object_from_path(Eo *bridge, const char *path);
174 static void _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj);
177 static void _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj);
178 static Eina_Bool _elm_atspi_bridge_key_filter(void *data, void *loop, int type, void *event);
179 static void _object_desktop_reference_append(Eldbus_Message_Iter *iter);
180 static Eina_Bool _on_object_add(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED);
181 static Eina_Bool _on_object_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED);
182 static void _plug_connect(Eldbus_Connection *conn, Eo *proxy);
183 static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy);
184 static void _object_get_bus_name_and_path(Eo *bridge, const Eo *obj, const char **bus_name, const char **path);
185 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
186 static Eo *_calculate_navigable_accessible_at_point(Eo *bridge, Eo *root, Eina_Bool coord_type, int x, int y);
187 static Eo *_calculate_neighbor(Eo *bridge, Eo *root, Eo *current, Eina_Bool forward, int search_mode);
191 const Eo_Event_Description *desc;
192 const Eo_Event_Cb callback;
193 } Elm_Atspi_Bridge_Event_Handler;
195 static const Elm_Atspi_Bridge_Event_Handler event_handlers[] = {
196 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_CHILDREN_CHANGED, _children_changed_signal_send},
197 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_PROPERTY_CHANGED, _property_changed_signal_send},
198 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_BOUNDS_CHANGED, _bounds_changed_signal_send},
199 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_STATE_CHANGED, _state_changed_signal_send},
200 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_VISIBLE_DATA_CHANGED, _visible_data_changed_signal_send},
201 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_ACTIVE_DESCENDANT_CHANGED, _active_descendant_changed_signal_send},
202 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_ADDED, _on_object_add},
203 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_REMOVED, _on_object_del},
204 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED, _window_signal_send},
205 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED, _window_signal_send},
206 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED, _window_signal_send},
207 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DEACTIVATED, _window_signal_send},
208 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MAXIMIZED, _window_signal_send},
209 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MINIMIZED, _window_signal_send},
210 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_RESTORED, _window_signal_send},
211 { ELM_INTERFACE_ATSPI_SELECTION_EVENT_SELECTION_CHANGED, _selection_signal_send},
212 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_CARET_MOVED, _text_caret_moved_send },
213 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_INSERTED, _text_text_inserted_send },
214 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_REMOVED, _text_text_removed_send },
215 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_SELECTION_CHANGED, _text_selection_changed_send },
216 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
217 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_MOVE_OUTED, _move_outed_signal_send}
221 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
224 ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED = 0,
225 ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_DISABLED = 1 << 0,
226 ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_KEYBOARD = 1 << 1,
230 enum _Atspi_Object_Child_Event_Type
232 ATSPI_OBJECT_CHILD_ADDED = 0,
233 ATSPI_OBJECT_CHILD_REMOVED
236 enum _Atspi_Object_Property
238 ATSPI_OBJECT_PROPERTY_NAME = 0,
239 ATSPI_OBJECT_PROPERTY_DESCRIPTION,
240 ATSPI_OBJECT_PROPERTY_VALUE,
241 ATSPI_OBJECT_PROPERTY_ROLE,
242 ATSPI_OBJECT_PROPERTY_PARENT,
243 ATSPI_OBJECT_PROPERTY_LAST
246 enum _Atspi_Object_Signals {
247 ATSPI_OBJECT_EVENT_PROPERTY_CHANGED = 0,
248 ATSPI_OBJECT_EVENT_BOUNDS_CHANGED,
249 ATSPI_OBJECT_EVENT_LINK_SELECTED,
250 ATSPI_OBJECT_EVENT_STATE_CHANGED,
251 ATSPI_OBJECT_EVENT_CHILDREN_CHANGED,
252 ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED,
253 ATSPI_OBJECT_EVENT_SELECTION_CHANGED,
254 ATSPI_OBJECT_EVENT_MODEL_CHANGED,
255 ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED,
256 ATSPI_OBJECT_EVENT_ROW_INSERTED,
257 ATSPI_OBJECT_EVENT_ROW_REORDERED,
258 ATSPI_OBJECT_EVENT_ROW_DELETED,
259 ATSPI_OBJECT_EVENT_COLUMN_INSERTED,
260 ATSPI_OBJECT_EVENT_COLUMN_REORDERED,
261 ATSPI_OBJECT_EVENT_COLUMN_DELETED,
262 ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED,
263 ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED,
264 ATSPI_OBJECT_EVENT_TEXT_CHANGED,
265 ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED,
266 ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED,
267 ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED,
268 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
269 ATSPI_OBJECT_EVENT_MOVE_OUTED
273 enum _Atspi_Window_Signals
275 ATSPI_WINDOW_EVENT_PROPERTY_CHANGE = 0,
276 ATSPI_WINDOW_EVENT_MINIMIZE,
277 ATSPI_WINDOW_EVENT_MAXIMIZE,
278 ATSPI_WINDOW_EVENT_RESTORE,
279 ATSPI_WINDOW_EVENT_CLOSE,
280 ATSPI_WINDOW_EVENT_CREATE,
281 ATSPI_WINDOW_EVENT_REPARENT,
282 ATSPI_WINDOW_EVENT_DESKTOPCREATE,
283 ATSPI_WINDOW_EVENT_DESKTOPDESTROY,
284 ATSPI_WINDOW_EVENT_DESTROY,
285 ATSPI_WINDOW_EVENT_ACTIVATE,
286 ATSPI_WINDOW_EVENT_DEACTIVATE,
287 ATSPI_WINDOW_EVENT_RAISE,
288 ATSPI_WINDOW_EVENT_LOWER,
289 ATSPI_WINDOW_EVENT_MOVE,
290 ATSPI_WINDOW_EVENT_RESIZE,
291 ATSPI_WINDOW_EVENT_SHADE,
292 ATSPI_WINDOW_EVENT_UUSHADE,
293 ATSPI_WINDOW_EVENT_RESTYLE,
296 static const Eldbus_Signal _event_obj_signals[] = {
297 [ATSPI_OBJECT_EVENT_PROPERTY_CHANGED] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
298 [ATSPI_OBJECT_EVENT_BOUNDS_CHANGED] = {"BoundsChanged", ELDBUS_ARGS({"siiv(iiii)", NULL}), 0},
299 [ATSPI_OBJECT_EVENT_LINK_SELECTED] = {"LinkSelected", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
300 [ATSPI_OBJECT_EVENT_STATE_CHANGED] = {"StateChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
301 [ATSPI_OBJECT_EVENT_CHILDREN_CHANGED] = {"ChildrenChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
302 [ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED] = {"VisibleDataChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
303 [ATSPI_OBJECT_EVENT_SELECTION_CHANGED] = {"SelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
304 [ATSPI_OBJECT_EVENT_MODEL_CHANGED] = {"ModelChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
305 [ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED] = {"ActiveDescendantChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
306 [ATSPI_OBJECT_EVENT_ROW_INSERTED] = {"RowInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
307 [ATSPI_OBJECT_EVENT_ROW_REORDERED] = {"RowReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
308 [ATSPI_OBJECT_EVENT_ROW_DELETED] = {"RowDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
309 [ATSPI_OBJECT_EVENT_COLUMN_INSERTED] = {"ColumnInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
310 [ATSPI_OBJECT_EVENT_COLUMN_REORDERED] = {"ColumnReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
311 [ATSPI_OBJECT_EVENT_COLUMN_DELETED] = {"ColumnDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
312 [ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED] = {"TextBoundsChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
313 [ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED] = {"TextSelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
314 [ATSPI_OBJECT_EVENT_TEXT_CHANGED] = {"TextChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
315 [ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED] = {"TextAttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
316 [ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED] = {"TextCaretMoved", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
317 [ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED] = {"AttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
318 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
319 [ATSPI_OBJECT_EVENT_MOVE_OUTED] = {"MoveOuted", ELDBUS_ARGS({"siiv(i)", NULL}), 0},
321 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
324 static const Eldbus_Signal _window_obj_signals[] = {
325 [ATSPI_WINDOW_EVENT_PROPERTY_CHANGE] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
326 [ATSPI_WINDOW_EVENT_MINIMIZE] = {"Minimize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
327 [ATSPI_WINDOW_EVENT_MAXIMIZE] = {"Maximize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
328 [ATSPI_WINDOW_EVENT_RESTORE] = {"Restore", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
329 [ATSPI_WINDOW_EVENT_CLOSE] = {"Close", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
330 [ATSPI_WINDOW_EVENT_CREATE] = {"Create", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
331 [ATSPI_WINDOW_EVENT_REPARENT] = {"Reparent", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
332 [ATSPI_WINDOW_EVENT_DESKTOPCREATE] = {"DesktopCreate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
333 [ATSPI_WINDOW_EVENT_DESKTOPDESTROY] = {"DesktopDestroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
334 [ATSPI_WINDOW_EVENT_DESTROY] = {"Destroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
335 [ATSPI_WINDOW_EVENT_ACTIVATE] = {"Activate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
336 [ATSPI_WINDOW_EVENT_DEACTIVATE] = {"Deactivate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
337 [ATSPI_WINDOW_EVENT_RAISE] = {"Raise", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
338 [ATSPI_WINDOW_EVENT_LOWER] = {"Lower", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
339 [ATSPI_WINDOW_EVENT_MOVE] = {"Move", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
340 [ATSPI_WINDOW_EVENT_RESIZE] = {"Resize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
341 [ATSPI_WINDOW_EVENT_SHADE] = {"Shade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
342 [ATSPI_WINDOW_EVENT_UUSHADE] = {"uUshade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
343 [ATSPI_WINDOW_EVENT_RESTYLE] = {"Restyle", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
344 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
347 const int elm_roles_to_atspi_roles[][2] = {
348 { ELM_ATSPI_ROLE_INVALID, ATSPI_ROLE_INVALID },
349 { ELM_ATSPI_ROLE_ACCELERATOR_LABEL, ATSPI_ROLE_ACCELERATOR_LABEL },
350 { ELM_ATSPI_ROLE_ALERT, ATSPI_ROLE_ALERT },
351 { ELM_ATSPI_ROLE_ANIMATION, ATSPI_ROLE_ANIMATION },
352 { ELM_ATSPI_ROLE_ARROW, ATSPI_ROLE_ARROW },
353 { ELM_ATSPI_ROLE_CALENDAR, ATSPI_ROLE_CALENDAR },
354 { ELM_ATSPI_ROLE_CANVAS, ATSPI_ROLE_CANVAS },
355 { ELM_ATSPI_ROLE_CHECK_BOX, ATSPI_ROLE_CHECK_BOX },
356 { ELM_ATSPI_ROLE_CHECK_MENU_ITEM, ATSPI_ROLE_CHECK_MENU_ITEM },
357 { ELM_ATSPI_ROLE_COLOR_CHOOSER, ATSPI_ROLE_COLOR_CHOOSER },
358 { ELM_ATSPI_ROLE_COLUMN_HEADER, ATSPI_ROLE_COLUMN_HEADER },
359 { ELM_ATSPI_ROLE_COMBO_BOX, ATSPI_ROLE_COMBO_BOX },
360 { ELM_ATSPI_ROLE_DATE_EDITOR, ATSPI_ROLE_DATE_EDITOR },
361 { ELM_ATSPI_ROLE_DESKTOP_ICON, ATSPI_ROLE_DESKTOP_ICON },
362 { ELM_ATSPI_ROLE_DESKTOP_FRAME, ATSPI_ROLE_DESKTOP_FRAME },
363 { ELM_ATSPI_ROLE_DIAL, ATSPI_ROLE_DIAL },
364 { ELM_ATSPI_ROLE_DIALOG, ATSPI_ROLE_DIALOG },
365 { ELM_ATSPI_ROLE_DIRECTORY_PANE, ATSPI_ROLE_DIRECTORY_PANE },
366 { ELM_ATSPI_ROLE_DRAWING_AREA, ATSPI_ROLE_DRAWING_AREA },
367 { ELM_ATSPI_ROLE_FILE_CHOOSER, ATSPI_ROLE_FILE_CHOOSER },
368 { ELM_ATSPI_ROLE_FILLER, ATSPI_ROLE_FILLER },
369 { ELM_ATSPI_ROLE_FOCUS_TRAVERSABLE, ATSPI_ROLE_FOCUS_TRAVERSABLE },
370 { ELM_ATSPI_ROLE_FONT_CHOOSER, ATSPI_ROLE_FONT_CHOOSER },
371 { ELM_ATSPI_ROLE_FRAME, ATSPI_ROLE_FRAME },
372 { ELM_ATSPI_ROLE_GLASS_PANE, ATSPI_ROLE_GLASS_PANE },
373 { ELM_ATSPI_ROLE_HTML_CONTAINER, ATSPI_ROLE_HTML_CONTAINER },
374 { ELM_ATSPI_ROLE_ICON, ATSPI_ROLE_ICON },
375 { ELM_ATSPI_ROLE_IMAGE, ATSPI_ROLE_IMAGE },
376 { ELM_ATSPI_ROLE_INTERNAL_FRAME, ATSPI_ROLE_INTERNAL_FRAME },
377 { ELM_ATSPI_ROLE_LABEL, ATSPI_ROLE_LABEL },
378 { ELM_ATSPI_ROLE_LAYERED_PANE, ATSPI_ROLE_LAYERED_PANE },
379 { ELM_ATSPI_ROLE_LIST, ATSPI_ROLE_LIST },
380 { ELM_ATSPI_ROLE_LIST_ITEM, ATSPI_ROLE_LIST_ITEM },
381 { ELM_ATSPI_ROLE_MENU, ATSPI_ROLE_MENU },
382 { ELM_ATSPI_ROLE_MENU_BAR, ATSPI_ROLE_MENU_BAR },
383 { ELM_ATSPI_ROLE_MENU_ITEM, ATSPI_ROLE_MENU_ITEM },
384 { ELM_ATSPI_ROLE_OPTION_PANE, ATSPI_ROLE_OPTION_PANE },
385 { ELM_ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_PAGE_TAB },
386 { ELM_ATSPI_ROLE_PAGE_TAB_LIST, ATSPI_ROLE_PAGE_TAB_LIST },
387 { ELM_ATSPI_ROLE_PANEL, ATSPI_ROLE_PANEL },
388 { ELM_ATSPI_ROLE_PASSWORD_TEXT, ATSPI_ROLE_PASSWORD_TEXT },
389 { ELM_ATSPI_ROLE_POPUP_MENU, ATSPI_ROLE_POPUP_MENU },
390 { ELM_ATSPI_ROLE_PROGRESS_BAR, ATSPI_ROLE_PROGRESS_BAR },
391 { ELM_ATSPI_ROLE_PUSH_BUTTON, ATSPI_ROLE_PUSH_BUTTON },
392 { ELM_ATSPI_ROLE_RADIO_BUTTON, ATSPI_ROLE_RADIO_BUTTON },
393 { ELM_ATSPI_ROLE_RADIO_MENU_ITEM, ATSPI_ROLE_RADIO_MENU_ITEM },
394 { ELM_ATSPI_ROLE_ROOT_PANE, ATSPI_ROLE_ROOT_PANE },
395 { ELM_ATSPI_ROLE_ROW_HEADER, ATSPI_ROLE_ROW_HEADER },
396 { ELM_ATSPI_ROLE_SCROLL_BAR, ATSPI_ROLE_SCROLL_BAR },
397 { ELM_ATSPI_ROLE_SCROLL_PANE, ATSPI_ROLE_SCROLL_PANE },
398 { ELM_ATSPI_ROLE_SEPARATOR, ATSPI_ROLE_SEPARATOR },
399 { ELM_ATSPI_ROLE_SLIDER, ATSPI_ROLE_SLIDER },
400 { ELM_ATSPI_ROLE_SPIN_BUTTON, ATSPI_ROLE_SPIN_BUTTON },
401 { ELM_ATSPI_ROLE_SPLIT_PANE, ATSPI_ROLE_SPLIT_PANE },
402 { ELM_ATSPI_ROLE_STATUS_BAR, ATSPI_ROLE_STATUS_BAR },
403 { ELM_ATSPI_ROLE_TABLE, ATSPI_ROLE_TABLE },
404 { ELM_ATSPI_ROLE_TABLE_CELL, ATSPI_ROLE_TABLE_CELL },
405 { ELM_ATSPI_ROLE_TABLE_COLUMN_HEADER, ATSPI_ROLE_TABLE_COLUMN_HEADER },
406 { ELM_ATSPI_ROLE_TABLE_ROW_HEADER, ATSPI_ROLE_TABLE_ROW_HEADER },
407 { ELM_ATSPI_ROLE_TEAROFF_MENU_ITEM, ATSPI_ROLE_TEAROFF_MENU_ITEM },
408 { ELM_ATSPI_ROLE_TERMINAL, ATSPI_ROLE_TERMINAL },
409 { ELM_ATSPI_ROLE_TEXT, ATSPI_ROLE_TEXT },
410 { ELM_ATSPI_ROLE_TOGGLE_BUTTON, ATSPI_ROLE_TOGGLE_BUTTON },
411 { ELM_ATSPI_ROLE_TOOL_BAR, ATSPI_ROLE_TOOL_BAR },
412 { ELM_ATSPI_ROLE_TOOL_TIP, ATSPI_ROLE_TOOL_TIP },
413 { ELM_ATSPI_ROLE_TREE, ATSPI_ROLE_TREE },
414 { ELM_ATSPI_ROLE_TREE_TABLE, ATSPI_ROLE_TREE_TABLE },
415 { ELM_ATSPI_ROLE_UNKNOWN, ATSPI_ROLE_UNKNOWN },
416 { ELM_ATSPI_ROLE_VIEWPORT, ATSPI_ROLE_VIEWPORT },
417 { ELM_ATSPI_ROLE_WINDOW, ATSPI_ROLE_WINDOW },
418 { ELM_ATSPI_ROLE_EXTENDED, ATSPI_ROLE_EXTENDED },
419 { ELM_ATSPI_ROLE_HEADER, ATSPI_ROLE_HEADER },
420 { ELM_ATSPI_ROLE_FOOTER, ATSPI_ROLE_FOOTER },
421 { ELM_ATSPI_ROLE_PARAGRAPH, ATSPI_ROLE_PARAGRAPH },
422 { ELM_ATSPI_ROLE_RULER, ATSPI_ROLE_RULER },
423 { ELM_ATSPI_ROLE_APPLICATION, ATSPI_ROLE_APPLICATION },
424 { ELM_ATSPI_ROLE_AUTOCOMPLETE, ATSPI_ROLE_AUTOCOMPLETE },
425 { ELM_ATSPI_ROLE_EDITBAR, ATSPI_ROLE_EDITBAR },
426 { ELM_ATSPI_ROLE_EMBEDDED, ATSPI_ROLE_EMBEDDED },
427 { ELM_ATSPI_ROLE_ENTRY, ATSPI_ROLE_ENTRY },
428 { ELM_ATSPI_ROLE_CHART, ATSPI_ROLE_CHART },
429 { ELM_ATSPI_ROLE_CAPTION, ATSPI_ROLE_CAPTION },
430 { ELM_ATSPI_ROLE_DOCUMENT_FRAME, ATSPI_ROLE_DOCUMENT_FRAME },
431 { ELM_ATSPI_ROLE_HEADING, ATSPI_ROLE_HEADING },
432 { ELM_ATSPI_ROLE_PAGE, ATSPI_ROLE_PAGE },
433 { ELM_ATSPI_ROLE_SECTION, ATSPI_ROLE_SECTION },
434 { ELM_ATSPI_ROLE_REDUNDANT_OBJECT, ATSPI_ROLE_REDUNDANT_OBJECT },
435 { ELM_ATSPI_ROLE_FORM, ATSPI_ROLE_FORM },
436 { ELM_ATSPI_ROLE_LINK, ATSPI_ROLE_LINK },
437 { ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW, ATSPI_ROLE_INPUT_METHOD_WINDOW },
438 { ELM_ATSPI_ROLE_TABLE_ROW, ATSPI_ROLE_TABLE_ROW },
439 { ELM_ATSPI_ROLE_TREE_ITEM, ATSPI_ROLE_TREE_ITEM },
440 { ELM_ATSPI_ROLE_DOCUMENT_SPREADSHEET, ATSPI_ROLE_DOCUMENT_SPREADSHEET },
441 { ELM_ATSPI_ROLE_DOCUMENT_PRESENTATION, ATSPI_ROLE_DOCUMENT_PRESENTATION },
442 { ELM_ATSPI_ROLE_DOCUMENT_TEXT, ATSPI_ROLE_DOCUMENT_TEXT },
443 { ELM_ATSPI_ROLE_DOCUMENT_WEB, ATSPI_ROLE_DOCUMENT_WEB },
444 { ELM_ATSPI_ROLE_DOCUMENT_EMAIL, ATSPI_ROLE_DOCUMENT_EMAIL },
445 { ELM_ATSPI_ROLE_COMMENT, ATSPI_ROLE_COMMENT },
446 { ELM_ATSPI_ROLE_LIST_BOX, ATSPI_ROLE_LIST_BOX },
447 { ELM_ATSPI_ROLE_GROUPING, ATSPI_ROLE_GROUPING },
448 { ELM_ATSPI_ROLE_IMAGE_MAP, ATSPI_ROLE_IMAGE_MAP },
449 { ELM_ATSPI_ROLE_NOTIFICATION, ATSPI_ROLE_NOTIFICATION },
450 { ELM_ATSPI_ROLE_INFO_BAR, ATSPI_ROLE_INFO_BAR },
451 { ELM_ATSPI_ROLE_LAST_DEFINED, ATSPI_ROLE_LAST_DEFINED },
454 struct atspi_state_desc
456 Elm_Atspi_State_Type elm_state;
457 AtspiStateType atspi_state;
461 const struct atspi_state_desc elm_states_to_atspi_state[] = {
462 { ELM_ATSPI_STATE_INVALID, ATSPI_STATE_INVALID, "invalid" },
463 { ELM_ATSPI_STATE_ACTIVE, ATSPI_STATE_ACTIVE, "active" },
464 { ELM_ATSPI_STATE_ARMED, ATSPI_STATE_ARMED, "armed" },
465 { ELM_ATSPI_STATE_BUSY, ATSPI_STATE_BUSY, "busy" },
466 { ELM_ATSPI_STATE_CHECKED, ATSPI_STATE_CHECKED, "checked" },
467 { ELM_ATSPI_STATE_COLLAPSED, ATSPI_STATE_COLLAPSED, "collapsed" },
468 { ELM_ATSPI_STATE_DEFUNCT, ATSPI_STATE_DEFUNCT, "defunct" },
469 { ELM_ATSPI_STATE_EDITABLE, ATSPI_STATE_EDITABLE, "editable" },
470 { ELM_ATSPI_STATE_ENABLED, ATSPI_STATE_ENABLED, "enabled" },
471 { ELM_ATSPI_STATE_EXPANDABLE, ATSPI_STATE_EXPANDABLE, "expandable" },
472 { ELM_ATSPI_STATE_EXPANDED, ATSPI_STATE_EXPANDED, "expanded" },
473 { ELM_ATSPI_STATE_FOCUSABLE, ATSPI_STATE_FOCUSABLE, "focusable" },
474 { ELM_ATSPI_STATE_FOCUSED, ATSPI_STATE_FOCUSED, "focused" },
475 { ELM_ATSPI_STATE_HAS_TOOLTIP, ATSPI_STATE_HAS_TOOLTIP, "has-tooltip" },
476 { ELM_ATSPI_STATE_HORIZONTAL, ATSPI_STATE_HORIZONTAL, "horizontal" },
477 { ELM_ATSPI_STATE_ICONIFIED, ATSPI_STATE_ICONIFIED, "iconified" },
478 { ELM_ATSPI_STATE_MODAL, ATSPI_STATE_MODAL, "modal" },
479 { ELM_ATSPI_STATE_MULTI_LINE, ATSPI_STATE_MULTI_LINE, "multi-line" },
480 { ELM_ATSPI_STATE_MULTISELECTABLE, ATSPI_STATE_MULTISELECTABLE, "multiselectable" },
481 { ELM_ATSPI_STATE_OPAQUE, ATSPI_STATE_OPAQUE, "opaque" },
482 { ELM_ATSPI_STATE_PRESSED, ATSPI_STATE_PRESSED, "pressed" },
483 { ELM_ATSPI_STATE_RESIZABLE, ATSPI_STATE_RESIZABLE, "resizable" },
484 { ELM_ATSPI_STATE_SELECTABLE, ATSPI_STATE_SELECTABLE, "selectable" },
485 { ELM_ATSPI_STATE_SELECTED, ATSPI_STATE_SELECTED, "selected" },
486 { ELM_ATSPI_STATE_SENSITIVE, ATSPI_STATE_SENSITIVE, "sensitive" },
487 { ELM_ATSPI_STATE_SHOWING, ATSPI_STATE_SHOWING, "showing" },
488 { ELM_ATSPI_STATE_SINGLE_LINE, ATSPI_STATE_SINGLE_LINE, "single-line" },
489 { ELM_ATSPI_STATE_STALE, ATSPI_STATE_STALE, "stale" },
490 { ELM_ATSPI_STATE_TRANSIENT, ATSPI_STATE_TRANSIENT, "transient" },
491 { ELM_ATSPI_STATE_VERTICAL, ATSPI_STATE_VERTICAL, "vertical" },
492 { ELM_ATSPI_STATE_VISIBLE, ATSPI_STATE_VISIBLE, "visible" },
493 { ELM_ATSPI_STATE_MANAGES_DESCENDANTS, ATSPI_STATE_MANAGES_DESCENDANTS, "manages-descendants" },
494 { ELM_ATSPI_STATE_INDETERMINATE, ATSPI_STATE_INDETERMINATE, "indeterminate" },
495 { ELM_ATSPI_STATE_REQUIRED, ATSPI_STATE_REQUIRED, "required" },
496 { ELM_ATSPI_STATE_TRUNCATED, ATSPI_STATE_TRUNCATED, "truncated" },
497 { ELM_ATSPI_STATE_ANIMATED, ATSPI_STATE_ANIMATED, "animated" },
498 { ELM_ATSPI_STATE_INVALID_ENTRY, ATSPI_STATE_INVALID_ENTRY, "invalid-entry" },
499 { ELM_ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, "supports-autocompletion" },
500 { ELM_ATSPI_STATE_SELECTABLE_TEXT, ATSPI_STATE_SELECTABLE_TEXT, "selectable-text" },
501 { ELM_ATSPI_STATE_IS_DEFAULT, ATSPI_STATE_IS_DEFAULT, "is-default" },
502 { ELM_ATSPI_STATE_VISITED, ATSPI_STATE_VISITED, "visited" },
503 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
504 { ELM_ATSPI_STATE_CHECKABLE, ATSPI_STATE_CHECKABLE, "checkable" },
505 { ELM_ATSPI_STATE_HAS_POPUP, ATSPI_STATE_HAS_POPUP, "has-popup" },
506 { ELM_ATSPI_STATE_READ_ONLY, ATSPI_STATE_READ_ONLY, "read-only" },
507 { ELM_ATSPI_STATE_HIGHLIGHTED, ATSPI_STATE_HIGHLIGHTED, "highlighted" },
508 { ELM_ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_HIGHLIGHTABLE, "highlightable" },
510 { ELM_ATSPI_STATE_LAST_DEFINED, ATSPI_STATE_LAST_DEFINED, "last-defined" }
513 const int elm_relation_to_atspi_relation_mapping[] = {
514 [ELM_ATSPI_RELATION_NULL] = ATSPI_RELATION_NULL,
515 [ELM_ATSPI_RELATION_LABEL_FOR] = ATSPI_RELATION_LABEL_FOR,
516 [ELM_ATSPI_RELATION_LABELLED_BY] = ATSPI_RELATION_LABELLED_BY,
517 [ELM_ATSPI_RELATION_CONTROLLER_FOR] = ATSPI_RELATION_CONTROLLER_FOR,
518 [ELM_ATSPI_RELATION_CONTROLLED_BY] = ATSPI_RELATION_CONTROLLED_BY,
519 [ELM_ATSPI_RELATION_MEMBER_OF] = ATSPI_RELATION_MEMBER_OF,
520 [ELM_ATSPI_RELATION_TOOLTIP_FOR] = ATSPI_RELATION_TOOLTIP_FOR,
521 [ELM_ATSPI_RELATION_NODE_CHILD_OF] = ATSPI_RELATION_NODE_CHILD_OF,
522 [ELM_ATSPI_RELATION_NODE_PARENT_OF] = ATSPI_RELATION_NODE_PARENT_OF,
523 [ELM_ATSPI_RELATION_EXTENDED] = ATSPI_RELATION_EXTENDED,
524 [ELM_ATSPI_RELATION_FLOWS_TO] = ATSPI_RELATION_FLOWS_TO,
525 [ELM_ATSPI_RELATION_FLOWS_FROM] = ATSPI_RELATION_FLOWS_FROM,
526 [ELM_ATSPI_RELATION_SUBWINDOW_OF] = ATSPI_RELATION_SUBWINDOW_OF,
527 [ELM_ATSPI_RELATION_EMBEDS] = ATSPI_RELATION_EMBEDS,
528 [ELM_ATSPI_RELATION_EMBEDDED_BY] = ATSPI_RELATION_EMBEDDED_BY,
529 [ELM_ATSPI_RELATION_POPUP_FOR] = ATSPI_RELATION_POPUP_FOR,
530 [ELM_ATSPI_RELATION_PARENT_WINDOW_OF] = ATSPI_RELATION_PARENT_WINDOW_OF,
531 [ELM_ATSPI_RELATION_DESCRIPTION_FOR] = ATSPI_RELATION_DESCRIPTION_FOR,
532 [ELM_ATSPI_RELATION_DESCRIBED_BY] = ATSPI_RELATION_DESCRIBED_BY,
533 [ELM_ATSPI_RELATION_LAST_DEFINED] = ATSPI_RELATION_LAST_DEFINED,
536 static inline Eldbus_Message *_dbus_invalid_ref_error_new(const Eldbus_Message *msg)
538 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.UnknownObject", "Path is not valid accessible object reference.");
541 static AtspiRelationType _elm_relation_to_atspi_relation(Elm_Atspi_Relation_Type type)
543 if ((type < ELM_ATSPI_RELATION_LAST_DEFINED) && (type > ELM_ATSPI_RELATION_NULL))
544 return elm_relation_to_atspi_relation_mapping[type];
545 return ATSPI_RELATION_NULL;
548 static Elm_Atspi_Relation_Type _atspi_relation_to_elm_relation(AtspiRelationType type)
551 for(i = 0; i < sizeof(elm_relation_to_atspi_relation_mapping) / sizeof(elm_relation_to_atspi_relation_mapping[0]); ++i)
553 if (elm_relation_to_atspi_relation_mapping[i] == (int)type) return (Elm_Atspi_Relation_Type)i;
555 return ELM_ATSPI_RELATION_NULL;
558 static AtspiRole _elm_role_to_atspi_role(Elm_Atspi_Role role)
560 return role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
563 static Eldbus_Message *
564 _accessible_get_role(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
566 const char *obj_path = eldbus_message_path_get(msg);
567 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
568 Eo *obj = _bridge_object_from_path(bridge, obj_path);
571 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
573 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
575 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
576 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
578 AtspiRole atspi_role = _elm_role_to_atspi_role(role);
579 eldbus_message_arguments_append(ret, "u", atspi_role);
583 static Eldbus_Message *
584 _accessible_get_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
586 const char *role_name = NULL, *obj_path = eldbus_message_path_get(msg);
587 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
588 Eo *obj = _bridge_object_from_path(bridge, obj_path);
590 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
592 eo_do(obj, role_name = elm_interface_atspi_accessible_role_name_get());
594 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
595 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
596 eldbus_message_arguments_append(ret, "s", role_name);
601 static Eldbus_Message *
602 _accessible_get_localized_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
604 const char *l_role_name = NULL, *obj_path = eldbus_message_path_get(msg);
605 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
606 Eo *obj = _bridge_object_from_path(bridge, obj_path);
608 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
610 eo_do(obj, l_role_name = elm_interface_atspi_accessible_localized_role_name_get());
611 EINA_SAFETY_ON_NULL_RETURN_VAL(l_role_name, NULL);
613 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
614 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
615 eldbus_message_arguments_append(ret, "s", l_role_name);
620 static Eldbus_Message *
621 _accessible_get_children(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
623 const char *obj_path = eldbus_message_path_get(msg);
624 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
625 Eo *obj = _bridge_object_from_path(bridge, obj_path);
626 Eina_List *children_list = NULL, *l;
628 Eldbus_Message_Iter *iter, *iter_array;
631 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
633 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
635 ret = eldbus_message_method_return_new(msg);
636 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
638 iter = eldbus_message_iter_get(ret);
639 iter_array = eldbus_message_iter_container_new(iter, 'a', "(so)");
640 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
642 EINA_LIST_FOREACH(children_list, l, children)
644 _bridge_iter_object_reference_append(bridge, iter_array, children);
645 _bridge_object_register(bridge, children);
648 eldbus_message_iter_container_close(iter, iter_array);
649 eina_list_free(children_list);
654 if (ret) eldbus_message_unref(ret);
658 static Eldbus_Message *
659 _accessible_get_application(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
662 const char *obj_path = eldbus_message_path_get(msg);
663 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
664 Eo *obj = _bridge_object_from_path(bridge, obj_path);
666 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
668 ret = eldbus_message_method_return_new(msg);
669 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
671 Eldbus_Message_Iter *iter = eldbus_message_iter_get(ret);
672 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
677 static Eldbus_Message *
678 _accessible_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
680 Eina_List *attrs, *l;
681 Elm_Atspi_Attribute *attr;
682 Eldbus_Message_Iter *iter, *iter_dict, *iter_entry;
685 const char *obj_path = eldbus_message_path_get(msg);
686 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
687 Eo *obj = _bridge_object_from_path(bridge, obj_path);
689 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
691 ret = eldbus_message_method_return_new(msg);
692 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
694 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
696 iter = eldbus_message_iter_get(ret);
697 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
698 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
700 EINA_LIST_FOREACH(attrs, l, attr)
702 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
703 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
704 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
705 eldbus_message_iter_container_close(iter_dict, iter_entry);
708 eldbus_message_iter_container_close(iter, iter_dict);
709 elm_atspi_attributes_list_free(attrs);
714 static Eldbus_Message *
715 _accessible_interfaces_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
718 Eldbus_Message_Iter *iter;
719 const char *obj_path = eldbus_message_path_get(msg);
720 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
721 Eo *obj = _bridge_object_from_path(bridge, obj_path);
723 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
725 ret = eldbus_message_method_return_new(msg);
726 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
728 iter = eldbus_message_iter_get(ret);
729 _iter_interfaces_append(iter, obj);
735 _elm_atspi_state_set_to_atspi_state_set(Elm_Atspi_State_Set states)
740 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
742 if (STATE_TYPE_GET(states, elm_states_to_atspi_state[i].elm_state))
743 STATE_TYPE_SET(ret, elm_states_to_atspi_state[i].atspi_state);
748 static Elm_Atspi_State_Set
749 _atspi_state_set_to_elm_atspi_state_set(uint64_t states)
751 //Currently Elm_Atspi_State and Atspi_State_Set are binary compatible,
752 //implement proper coversion when it will be needed.
753 Elm_Atspi_State_Set ret = states;
758 _elm_atspi_state_hash_build(void)
760 Eina_Hash *ret = eina_hash_string_superfast_new(NULL);
763 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
764 eina_hash_add(ret, elm_states_to_atspi_state[i].name, &elm_states_to_atspi_state[i]);
770 _elm_atspi_event_hash_build(void)
772 Eina_Hash *ret = eina_hash_pointer_new(NULL);
775 for (i = 0; i < SIZE(event_handlers); i++)
776 eina_hash_add(ret, &(event_handlers[i].desc), event_handlers[i].callback);
781 static Eldbus_Message *
782 _accessible_get_state(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
785 Eldbus_Message_Iter *iter, *iter_array;
786 Elm_Atspi_State_Set states;
787 uint64_t atspi_states = 0;
789 const char *obj_path = eldbus_message_path_get(msg);
790 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
791 Eo *obj = _bridge_object_from_path(bridge, obj_path);
793 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
795 ret = eldbus_message_method_return_new(msg);
796 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
798 iter = eldbus_message_iter_get(ret);
799 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
800 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
802 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
804 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
806 unsigned int s1 = atspi_states & 0xFFFFFFFF;
807 unsigned int s2 = (atspi_states >> 32) & 0xFFFFFFFF;
809 eldbus_message_iter_basic_append(iter_array, 'u', s1);
810 eldbus_message_iter_basic_append(iter_array, 'u', s2);
811 eldbus_message_iter_container_close(iter, iter_array);
816 if (ret) eldbus_message_unref(ret);
820 static Eldbus_Message *
821 _accessible_get_index_in_parent(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
823 const char *obj_path = eldbus_message_path_get(msg);
824 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
825 Eo *obj = _bridge_object_from_path(bridge, obj_path);
829 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
831 ret = eldbus_message_method_return_new(msg);
832 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
834 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
836 eldbus_message_arguments_append(ret, "i", idx);
841 static Eldbus_Message *
842 _accessible_child_at_index(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
844 const char *obj_path = eldbus_message_path_get(msg);
845 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
846 Eo *obj = _bridge_object_from_path(bridge, obj_path);
848 Eina_List *children = NULL;
851 Eldbus_Message_Iter *iter;
853 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
855 if (!eldbus_message_arguments_get(msg, "i", &idx))
856 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
858 ret = eldbus_message_method_return_new(msg);
859 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
861 iter = eldbus_message_iter_get(ret);
862 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
864 child = eina_list_nth(children, idx);
865 _bridge_iter_object_reference_append(bridge, iter, child);
866 _bridge_object_register(bridge, child);
867 eina_list_free(children);
872 static Eldbus_Message *
873 _accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
875 const char *obj_path = eldbus_message_path_get(msg);
876 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
877 Eo *rel_obj, *obj = _bridge_object_from_path(bridge, obj_path);
878 Eldbus_Message *ret = NULL;
879 Eldbus_Message_Iter *iter = NULL, *iter_array = NULL, *iter_array2 = NULL, *iter_struct;
880 Elm_Atspi_Relation *rel;
882 Elm_Atspi_Relation_Set rels;
884 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
886 ret = eldbus_message_method_return_new(msg);
887 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
889 iter = eldbus_message_iter_get(ret);
890 iter_array = eldbus_message_iter_container_new(iter, 'a', "(ua(so))");
891 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
893 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
895 EINA_LIST_FOREACH(rels, l, rel)
897 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
898 eldbus_message_iter_basic_append(iter_struct, 'u', _elm_relation_to_atspi_relation(rel->type));
899 iter_array2 = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
900 EINA_SAFETY_ON_NULL_GOTO(iter_array2, fail);
901 EINA_LIST_FOREACH(rel->objects, l2, rel_obj)
903 _bridge_iter_object_reference_append(bridge, iter_array2, rel_obj);
904 _bridge_object_register(bridge, rel_obj);
906 eldbus_message_iter_container_close(iter_struct, iter_array2);
907 eldbus_message_iter_container_close(iter_array, iter_struct);
909 elm_atspi_relation_set_free(&rels);
910 eldbus_message_iter_container_close(iter, iter_array);
915 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get relation set.");
918 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
919 static Eldbus_Message *
920 _accessible_gesture_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
922 const char *obj_path = eldbus_message_path_get(msg);
923 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
924 Eo *obj = _bridge_object_from_path(bridge, obj_path);
925 int type, x_beg, y_beg, x_end, y_end, state;
926 unsigned int event_time;
928 Eina_Bool result = EINA_FALSE;
930 if (!eldbus_message_arguments_get(msg, "iiiiiiu", &type, &x_beg, &y_beg,
931 &x_end, &y_end, &state, &event_time))
932 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
934 ret = eldbus_message_method_return_new(msg);
935 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
937 Elm_Atspi_Gesture_Info gesture_info;
938 gesture_info.type = (Elm_Atspi_Gesture_Type)type;
939 gesture_info.x_beg = x_beg;
940 gesture_info.y_beg = y_beg;
941 gesture_info.x_end = x_end;
942 gesture_info.y_end = y_end;
943 gesture_info.state = (Elm_Atspi_Gesture_State)state;
944 gesture_info.event_time = event_time;
945 eo_do(obj, result = elm_interface_atspi_accessible_gesture_do(gesture_info));
946 eldbus_message_arguments_append(ret, "b", result);
951 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
952 static Eldbus_Message *
953 _accessible_get_neighbor(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
955 const char *start_path = eldbus_message_path_get(msg);
956 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
957 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
958 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
960 Eo *start = _bridge_object_from_path(bridge, start_path);
962 Eldbus_Message_Iter *iter;
963 int direction, search_mode;
965 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(start, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
967 char *root_path = "";
968 if (!eldbus_message_arguments_get(msg, "sii", &root_path, &direction, &search_mode))
969 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
971 Eo *root = _bridge_object_from_path(bridge, root_path);
973 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
976 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(root));
977 if (ecore_evas_obscured_get(ee))
978 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
982 ret = eldbus_message_method_return_new(msg);
983 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
985 iter = eldbus_message_iter_get(ret);
987 Eo *accessible = _calculate_neighbor(bridge, root, start, direction == 1, search_mode);
988 _bridge_iter_object_reference_append(bridge, iter, accessible);
989 _bridge_object_register(bridge, accessible);
991 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
992 _object_get_bus_name_and_path(bridge, start, &obj_bus_name, NULL);
993 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
995 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
996 eldbus_message_iter_basic_append(iter, 'y', recurse);
1000 static Eldbus_Message *
1001 _accessible_get_navigable_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1003 const char *obj_path = eldbus_message_path_get(msg);
1004 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1005 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
1006 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
1008 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1010 Eldbus_Message *ret;
1011 AtspiCoordType coord_type;
1012 Eldbus_Message_Iter *iter;
1014 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1016 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
1017 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
1018 if (ecore_evas_obscured_get(ee))
1019 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
1022 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
1023 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1025 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
1026 Evas_Object *top = elm_object_top_widget_get(obj);
1029 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
1034 ret = eldbus_message_method_return_new(msg);
1035 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1037 iter = eldbus_message_iter_get(ret);
1039 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1040 Eo *accessible = _calculate_navigable_accessible_at_point(bridge, obj, type, x, y);
1044 if (accessible && eo_isa(accessible, ELM_ACCESS_CLASS))
1046 Evas_Object *parent = elm_widget_parent_get(accessible);
1048 Elm_Widget_Smart_Data *wd;
1049 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
1053 Evas_Object *widget;
1055 EINA_LIST_FOREACH(wd->subobjs, l, widget)
1059 proxy = evas_object_data_get(widget, "__widget_proxy");
1063 evas_object_geometry_get(widget, &px, &py, &pw, &ph);
1064 if (x >= px && x <= px + pw && y >= py && y <= py +ph)
1066 /* proxy is also selectable */
1067 deputy = accessible;
1076 _bridge_iter_object_reference_append(bridge, iter, accessible);
1077 _bridge_object_register(bridge, accessible);
1079 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
1080 _object_get_bus_name_and_path(bridge, obj, &obj_bus_name, NULL);
1081 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
1082 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
1083 eldbus_message_iter_basic_append(iter, 'y', recurse);
1086 _bridge_iter_object_reference_append(bridge, iter, deputy);
1087 if (deputy) _bridge_object_register(bridge, deputy);
1093 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1095 _list_children_count_check(Eo *obj)
1099 Eina_List *children;
1101 Elm_Atspi_Role role;
1106 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1107 if (role == ELM_ATSPI_ROLE_LIST)
1109 int children_count = 0;
1110 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1111 children_count = eina_list_count(children);
1113 for (i = 0; i < children_count; i++)
1115 child = eina_list_nth(children, i);
1116 eo_do(child, role = elm_interface_atspi_accessible_role_get());
1117 if (role == ELM_ATSPI_ROLE_LIST_ITEM)
1120 eina_list_free(children);
1127 _list_children_count(Eo *obj)
1129 Eina_List *children;
1130 int list_items_count = 0;
1131 int children_count = 0;
1133 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1134 children_count = eina_list_count(children);
1139 list_items_count = _list_children_count_check(obj);
1140 if (list_items_count > 0)
1142 eina_list_free(children);
1143 return list_items_count;
1146 for (i = 0; i < children_count; i++)
1148 child = eina_list_nth(children, i);
1149 list_items_count = _list_children_count(child);
1150 if (list_items_count > 0)
1152 eina_list_free(children);
1153 return list_items_count;
1160 static Eldbus_Message *
1161 _accessible_reading_material_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1163 Eldbus_Message *ret;
1164 Eldbus_Message_Iter *iter, *iter_array, *iter_dict, *iter_entry;
1165 Eina_List *attrs, *l, *children;
1166 const char *name = NULL;
1167 unsigned int s1, s2;
1169 double increment = 0;
1170 double max_value = 0;
1171 double min_value = 0;
1173 int child_count = 0;
1174 int selected_child_count = 0;
1175 uint64_t atspi_states = 0;
1176 Elm_Atspi_Role role;
1177 Elm_Atspi_Attribute *attr;
1178 Elm_Atspi_State_Set states;
1179 Elm_Atspi_Relation_Set rels = NULL;
1180 Elm_Atspi_Relation *rel;
1181 Eo *relation_obj = NULL;
1184 Eina_Bool is_selected = EINA_FALSE;
1185 AtspiRole atspi_role = ATSPI_ROLE_INVALID;
1187 const char *obj_path = eldbus_message_path_get(msg);
1188 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1189 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1191 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1193 ret = eldbus_message_method_return_new(msg);
1194 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1196 iter = eldbus_message_iter_get(ret);
1198 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
1199 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
1200 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
1201 EINA_LIST_FOREACH(attrs, l, attr)
1203 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
1204 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
1205 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
1206 eldbus_message_iter_container_close(iter_dict, iter_entry);
1209 eldbus_message_iter_container_close(iter, iter_dict);
1210 elm_atspi_attributes_list_free(attrs);
1213 eo_do(obj, name = elm_interface_atspi_accessible_name_get());
1216 eldbus_message_iter_basic_append(iter, 's', name);
1218 /* name - LABELED_BY relation */
1219 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
1220 EINA_LIST_FOREACH(rels, l, rel)
1222 if (rel->type == ELM_ATSPI_RELATION_LABELLED_BY)
1224 int last_index = eina_list_count(rel->objects) - 1;
1225 relation_obj = eina_list_nth(rel->objects, last_index);
1229 eo_do(relation_obj, name = elm_interface_atspi_accessible_name_get());
1232 eldbus_message_iter_basic_append(iter, 's', name);
1234 /* name - text interface */
1236 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
1239 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
1240 eo_do(obj, name = elm_interface_atspi_text_get(0, val));
1244 eldbus_message_iter_basic_append(iter, 's', name);
1247 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1248 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1249 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1252 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1253 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1254 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1255 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1256 s1 = atspi_states & 0xFFFFFFFF;
1257 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1258 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1259 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1260 eldbus_message_iter_container_close(iter, iter_array);
1262 /* localized role name */
1263 eo_do(obj, name = elm_interface_atspi_accessible_localized_role_name_get());
1266 eldbus_message_iter_basic_append(iter, 's', name);
1269 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
1270 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1273 /* current value, increment, max, min */
1278 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
1280 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
1281 eo_do(obj, increment = elm_interface_atspi_value_increment_get());
1282 eo_do(obj, elm_interface_atspi_value_range_get(&min_value, &max_value, NULL));
1284 eldbus_message_iter_basic_append(iter, 'd', value);
1285 eldbus_message_iter_basic_append(iter, 'd', increment);
1286 eldbus_message_iter_basic_append(iter, 'd', max_value);
1287 eldbus_message_iter_basic_append(iter, 'd', min_value);
1290 eo_do(obj, name = elm_interface_atspi_accessible_description_get());
1293 eldbus_message_iter_basic_append(iter, 's', name);
1295 /* index in parent */
1296 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
1297 eldbus_message_iter_basic_append(iter, 'i', idx);
1299 /* is selected in parent */
1300 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
1301 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1303 eo_do(parent, is_selected = elm_interface_atspi_selection_is_child_selected(idx));
1305 eldbus_message_arguments_append(ret, "b", is_selected);
1307 /* has checkbox child */
1308 is_selected = EINA_FALSE;
1309 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1310 EINA_LIST_FOREACH(children, l, child)
1312 if (eo_isa(child, ELM_CHECK_CLASS))
1314 is_selected = EINA_TRUE;
1318 eldbus_message_iter_basic_append(iter, 'b', is_selected);
1319 eina_list_free(children);
1321 /* list children count */
1323 if (role == ELM_ATSPI_ROLE_DIALOG)
1325 child_count = _list_children_count(obj);
1327 eldbus_message_iter_basic_append(iter, 'i', child_count);
1329 /* first selected child index */
1331 if (eo_isa(obj, ELM_INDEX_CLASS))
1333 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1334 EINA_LIST_FOREACH(children, l, child)
1336 eo_do(child, states = elm_interface_atspi_accessible_state_set_get());
1337 if (STATE_TYPE_GET(states, ELM_ATSPI_STATE_SELECTED))
1341 eina_list_free(children);
1343 eldbus_message_iter_basic_append(iter, 'i', idx);
1346 role = ELM_ATSPI_ROLE_INVALID;
1347 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1348 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
1349 _object_desktop_reference_append(iter);
1351 _bridge_iter_object_reference_append(bridge, iter, parent);
1353 /* parent - states */
1354 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1355 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1356 eo_do(parent, states = elm_interface_atspi_accessible_state_set_get());
1357 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1358 s1 = atspi_states & 0xFFFFFFFF;
1359 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1360 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1361 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1362 eldbus_message_iter_container_close(iter, iter_array);
1364 /* parent - child count */
1365 eo_do(parent, l = elm_interface_atspi_accessible_children_get());
1366 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1370 eo_do(parent, role = elm_interface_atspi_accessible_role_get());
1371 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1372 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1374 /* parent - child count */
1375 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1377 eo_do(parent, selected_child_count = elm_interface_atspi_selection_selected_children_count_get());
1379 eldbus_message_iter_basic_append(iter, 'i', selected_child_count);
1381 /* relation object - DESCRIBED_BY */
1382 relation_obj = NULL;
1383 EINA_LIST_FOREACH(rels, l, rel)
1385 if (rel->type == ELM_ATSPI_RELATION_DESCRIBED_BY)
1387 int last_index = eina_list_count(rel->objects) - 1;
1388 relation_obj = eina_list_nth(rel->objects, last_index);
1392 _bridge_iter_object_reference_append(bridge, iter, relation_obj);
1393 elm_atspi_relation_set_free(&rels);
1398 if (rels) elm_atspi_relation_set_free(&rels);
1399 if (ret) eldbus_message_unref(ret);
1403 //TIZEN_ONLY(20170919): Handle default label object
1404 static Eldbus_Message *
1405 _accessible_default_label_info_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1407 Eldbus_Message *ret;
1408 Eldbus_Message_Iter *iter;
1409 const char *obj_path = eldbus_message_path_get(msg);
1410 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1411 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1412 Eo *default_label_obj;
1413 Elm_Atspi_Role role;
1414 AtspiRole atspi_role = ATSPI_ROLE_INVALID;
1416 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1418 ret = eldbus_message_method_return_new(msg);
1419 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1421 iter = eldbus_message_iter_get(ret);
1423 default_label_obj = _elm_win_default_label_obj_get(obj);
1424 if (!default_label_obj) default_label_obj = obj;
1425 _bridge_iter_object_reference_append(bridge, iter, default_label_obj);
1426 _bridge_object_register(bridge, default_label_obj);
1428 eo_do(default_label_obj, role = elm_interface_atspi_accessible_role_get());
1429 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1430 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1436 static const Eldbus_Method accessible_methods[] = {
1437 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
1438 { "GetNavigableAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)y", "accessible"}, {"(so)", "deputy"}), _accessible_get_navigable_at_point, 0 },
1439 { "GetNeighbor", ELDBUS_ARGS({"s", "current"}, {"i", "direction"}, {"i", "force_next"}), ELDBUS_ARGS({"(so)y", "accessible"}), _accessible_get_neighbor, 0 },
1441 { "GetChildAtIndex", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"(so)", "Accessible"}), _accessible_child_at_index, 0 },
1442 { "GetChildren", NULL, ELDBUS_ARGS({"a(so)", "children"}), _accessible_get_children, 0 },
1443 { "GetIndexInParent", NULL, ELDBUS_ARGS({"i", "index"}), _accessible_get_index_in_parent, 0 },
1444 { "GetRelationSet", NULL, ELDBUS_ARGS({"a(ua(so))", NULL}), _accessible_get_relation_set, 0 },
1445 { "GetRole", NULL, ELDBUS_ARGS({"u", "Role"}), _accessible_get_role, 0 },
1446 { "GetRoleName", NULL, ELDBUS_ARGS({"s", "Name"}), _accessible_get_role_name, 0 },
1447 { "GetLocalizedRoleName", NULL, ELDBUS_ARGS({"s", "LocalizedName"}), _accessible_get_localized_role_name, 0},
1448 { "GetState", NULL, ELDBUS_ARGS({"au", NULL}), _accessible_get_state, 0},
1449 { "GetApplication", NULL, ELDBUS_ARGS({"(so)", NULL}), _accessible_get_application, 0},
1450 { "GetAttributes", NULL, ELDBUS_ARGS({"a{ss}", NULL}), _accessible_attributes_get, 0},
1451 { "GetInterfaces", NULL, ELDBUS_ARGS({"as", NULL}), _accessible_interfaces_get, 0},
1452 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
1454 ELDBUS_ARGS({"i", "type"}, {"i", "x_beg"}, {"i", "y_beg"},
1455 {"i", "x_end"}, {"i", "y_end"}, {"i", "state"},
1456 {"u", "event_time"}),
1457 ELDBUS_ARGS({"b", "result"}), _accessible_gesture_do, 0},
1459 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1460 { "GetReadingMaterial",
1462 ELDBUS_ARGS({"a{ss}", "attributes"}, {"s", "name"},
1463 {"s", "labledByName"},{"s", "textIfceName"},
1464 {"u", "role"}, {"au", "stateSet"},
1465 {"s", "localizedName"}, {"i", "childCount"},
1466 {"d", "currentValue"},{"d", "minimumIncrement"},
1467 {"d", "maximumValue"},{"d", "minimumValue"},
1468 {"s", "description"}, {"i", "indexInParent"},
1469 {"b", "isSelectedInParent"}, {"b", "hasCheckboxChild"},
1470 {"i", "listChildrenCount"},
1471 {"i", "firstSelectedChildIndex"},
1472 {"(so)", "parent"}, {"au", "parentStateSet"},
1473 {"i", "parentChildCount"}, {"u", "parentRole"},
1474 {"i", "selectedChildCount"},
1475 {"(so)", "describecByObject"}),
1476 _accessible_reading_material_get, 0},
1478 //TIZEN_ONLY(20170919): Handle default label object
1479 { "GetDefaultLabelInfo",
1480 NULL, ELDBUS_ARGS({"(so)", "defaultLabelObject"}, {"u", "defaultLabelRole"}),
1481 _accessible_default_label_info_get, 0},
1483 { NULL, NULL, NULL, NULL, 0 }
1487 _is_operation_permitted(Eo *obj)
1489 Elm_Atspi_State_Set states;
1490 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1492 if (!STATE_TYPE_GET(states, ELM_ATSPI_STATE_SHOWING)) return EINA_FALSE;
1497 if (evas_object_freeze_events_get(parent)) return EINA_FALSE;
1498 parent = evas_object_smart_parent_get(parent);
1503 static Eldbus_Message *
1504 _selection_selected_child_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1506 const char *obj_path = eldbus_message_path_get(msg);
1507 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1508 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1512 Eldbus_Message *ret;
1513 Eldbus_Message_Iter *iter;
1515 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1517 if (!eldbus_message_arguments_get(msg, "i", &idx))
1518 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1520 ret = eldbus_message_method_return_new(msg);
1521 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1523 iter = eldbus_message_iter_get(ret);
1524 eo_do(obj, child = elm_interface_atspi_selection_selected_child_get(idx));
1526 _bridge_iter_object_reference_append(bridge, iter, child);
1527 _bridge_object_register(bridge, child);
1532 static Eldbus_Message *
1533 _selection_child_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1535 const char *obj_path = eldbus_message_path_get(msg);
1536 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1537 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1539 Eldbus_Message *ret;
1540 Eina_Bool result = EINA_FALSE;
1542 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1544 if (!eldbus_message_arguments_get(msg, "i", &idx))
1545 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1547 ret = eldbus_message_method_return_new(msg);
1548 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1550 if (_is_operation_permitted(obj))
1551 eo_do(obj, result = elm_interface_atspi_selection_child_select(idx));
1552 eldbus_message_arguments_append(ret, "b", result);
1557 static Eldbus_Message *
1558 _selection_selected_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1560 const char *obj_path = eldbus_message_path_get(msg);
1561 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1562 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1564 Eldbus_Message *ret;
1565 Eina_Bool result = EINA_FALSE;
1567 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1569 if (!eldbus_message_arguments_get(msg, "i", &idx))
1570 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1572 ret = eldbus_message_method_return_new(msg);
1573 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1575 if (_is_operation_permitted(obj))
1576 eo_do(obj, result = elm_interface_atspi_selection_selected_child_deselect(idx));
1577 eldbus_message_arguments_append(ret, "b", result);
1582 static Eldbus_Message *
1583 _selection_is_child_selected(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1585 const char *obj_path = eldbus_message_path_get(msg);
1586 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1587 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1589 Eldbus_Message *ret;
1592 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1594 if (!eldbus_message_arguments_get(msg, "i", &idx))
1595 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1597 ret = eldbus_message_method_return_new(msg);
1598 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1600 eo_do(obj, result = elm_interface_atspi_selection_is_child_selected(idx));
1601 eldbus_message_arguments_append(ret, "b", result);
1606 static Eldbus_Message *
1607 _selection_all_children_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1609 const char *obj_path = eldbus_message_path_get(msg);
1610 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1611 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1612 Eldbus_Message *ret;
1613 Eina_Bool result = EINA_FALSE;
1615 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1617 ret = eldbus_message_method_return_new(msg);
1618 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1620 if (_is_operation_permitted(obj))
1621 eo_do(obj, result = elm_interface_atspi_selection_all_children_select());
1622 eldbus_message_arguments_append(ret, "b", result);
1627 static Eldbus_Message *
1628 _selection_clear(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1630 const char *obj_path = eldbus_message_path_get(msg);
1631 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1632 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1633 Eldbus_Message *ret;
1634 Eina_Bool result = EINA_FALSE;
1636 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1638 ret = eldbus_message_method_return_new(msg);
1639 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1641 if (_is_operation_permitted(obj))
1642 eo_do(obj, result = elm_interface_atspi_selection_clear());
1643 eldbus_message_arguments_append(ret, "b", result);
1648 static Eldbus_Message *
1649 _selection_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1651 const char *obj_path = eldbus_message_path_get(msg);
1652 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1653 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1655 Eldbus_Message *ret;
1656 Eina_Bool result = EINA_FALSE;
1658 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1660 if (!eldbus_message_arguments_get(msg, "i", &idx))
1661 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1663 ret = eldbus_message_method_return_new(msg);
1664 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1666 if (_is_operation_permitted(obj))
1667 eo_do(obj, result = elm_interface_atspi_selection_child_deselect(idx));
1668 eldbus_message_arguments_append(ret, "b", result);
1673 static const Eldbus_Method selection_methods[] = {
1674 { "GetSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"(so)", "Accessible"}), _selection_selected_child_get, 0 },
1675 { "SelectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_select, 0 },
1676 { "DeselectSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_selected_child_deselect, 0 },
1677 { "IsChildSelected", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_is_child_selected, 0 },
1678 { "SelectAll", NULL, ELDBUS_ARGS({"b", "result"}), _selection_all_children_select, 0},
1679 { "ClearSelection", NULL, ELDBUS_ARGS({"b", "result"}), _selection_clear, 0},
1680 { "DeselectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_deselect, 0 },
1681 { NULL, NULL, NULL, NULL, 0 }
1684 static Eldbus_Message *
1685 _action_description_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1687 const char *description, *obj_path = eldbus_message_path_get(msg);
1688 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1689 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1691 Eldbus_Message *ret;
1693 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1695 if (!eldbus_message_arguments_get(msg, "i", &idx))
1696 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1698 ret = eldbus_message_method_return_new(msg);
1699 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1701 eo_do(obj, description = elm_interface_atspi_action_description_get(idx));
1702 description = description ? description : "";
1703 eldbus_message_arguments_append(ret, "s", description);
1708 static Eldbus_Message *
1709 _action_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1711 const char *name, *obj_path = eldbus_message_path_get(msg);
1712 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1713 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1715 Eldbus_Message *ret;
1717 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1719 if (!eldbus_message_arguments_get(msg, "i", &idx))
1720 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1722 ret = eldbus_message_method_return_new(msg);
1723 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1725 eo_do(obj, name = elm_interface_atspi_action_name_get(idx));
1726 name = name ? name : "";
1727 eldbus_message_arguments_append(ret, "s", name);
1732 static Eldbus_Message *
1733 _action_localized_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1735 const char *name, *obj_path = eldbus_message_path_get(msg);
1736 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1737 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1739 Eldbus_Message *ret;
1741 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1743 if (!eldbus_message_arguments_get(msg, "i", &idx))
1744 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1746 ret = eldbus_message_method_return_new(msg);
1747 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1749 eo_do(obj, name = elm_interface_atspi_action_localized_name_get(idx));
1750 name = name ? name : "";
1751 eldbus_message_arguments_append(ret, "s", name);
1756 static Eldbus_Message *
1757 _action_key_binding_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1759 const char *obj_path = eldbus_message_path_get(msg);
1761 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1762 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1764 Eldbus_Message *ret;
1766 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1768 if (!eldbus_message_arguments_get(msg, "i", &idx))
1769 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1771 ret = eldbus_message_method_return_new(msg);
1772 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1774 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(idx));
1775 eldbus_message_arguments_append(ret, "s", key ? key : "");
1781 static Eldbus_Message *
1782 _action_actions_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1784 const char *action, *obj_path = eldbus_message_path_get(msg);
1785 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1786 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1788 Eldbus_Message *ret;
1789 Eldbus_Message_Iter *iter, *iter_array;
1791 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1793 ret = eldbus_message_method_return_new(msg);
1794 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1796 iter = eldbus_message_iter_get(ret);
1797 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
1799 iter_array = eldbus_message_iter_container_new(iter, 'a', "sss");
1800 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_array, NULL);
1802 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1805 EINA_LIST_FREE(actions, action)
1809 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(id));
1810 eo_do(obj, descr = elm_interface_atspi_action_description_get(id));
1811 descr = descr ? descr : "";
1812 eldbus_message_iter_arguments_append(iter_array, "sss", action, descr, key ? key : "");
1817 eldbus_message_iter_container_close(iter, iter_array);
1822 static Eldbus_Message *
1823 _action_action_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1825 const char *obj_path = eldbus_message_path_get(msg);
1826 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1827 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1829 Eldbus_Message *ret;
1830 Eina_Bool result = EINA_FALSE;
1832 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1834 if (!eldbus_message_arguments_get(msg, "i", &idx))
1835 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1837 ret = eldbus_message_method_return_new(msg);
1838 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1840 if (_is_operation_permitted(obj))
1841 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1843 eldbus_message_arguments_append(ret, "b", result);
1848 static Eldbus_Message *
1849 _action_action_name_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1851 const char *obj_path = eldbus_message_path_get(msg);
1852 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1853 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1858 Eldbus_Message *ret;
1859 Eina_Bool result = EINA_FALSE;
1861 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1863 if (!eldbus_message_arguments_get(msg, "s", &action_name))
1864 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1866 ret = eldbus_message_method_return_new(msg);
1867 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1869 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1870 EINA_LIST_FREE(actions, action)
1872 if (!result && action && !strcmp(action, action_name))
1880 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1882 eldbus_message_arguments_append(ret, "b", result);
1887 static const Eldbus_Method action_methods[] = {
1888 { "GetDescription", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "description"}), _action_description_get, 0 },
1889 { "GetName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_name_get, 0 },
1890 { "GetLocalizedName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_localized_name_get, 0 },
1891 { "GetKeyBinding", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "key"}), _action_key_binding_get, 0 },
1892 { "GetActions", NULL, ELDBUS_ARGS({"a(sss)", "actions"}), _action_actions_get, 0 },
1893 { "DoAction", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"b", "result"}), _action_action_do, 0 },
1894 { "DoActionName", ELDBUS_ARGS({"s", "name"}), ELDBUS_ARGS({"b", "result"}), _action_action_name_do, 0 },
1895 { NULL, NULL, NULL, NULL, 0 }
1898 static Eldbus_Message *
1899 _image_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1901 AtspiCoordType type;
1902 Eldbus_Message *ret;
1903 const char *obj_path = eldbus_message_path_get(msg);
1905 Eina_Bool screen_coords;
1906 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1907 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1911 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1913 if (!eldbus_message_arguments_get(msg, "u", &type))
1914 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1916 ret = eldbus_message_method_return_new(msg);
1917 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1919 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1920 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, &w, &h));
1921 eldbus_message_arguments_append(ret, "iiii", x, y, w, h);
1926 static Eldbus_Message *
1927 _image_position_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1929 AtspiCoordType type;
1930 Eldbus_Message *ret;
1931 const char *obj_path = eldbus_message_path_get(msg);
1932 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1933 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1935 Eina_Bool screen_coords;
1937 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1939 if (!eldbus_message_arguments_get(msg, "u", &type))
1940 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1942 ret = eldbus_message_method_return_new(msg);
1943 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1945 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1946 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, NULL, NULL));
1947 eldbus_message_arguments_append(ret, "i", x);
1948 eldbus_message_arguments_append(ret, "i", y);
1953 static Eldbus_Message *
1954 _image_size_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1956 Eldbus_Message *ret;
1957 const char *obj_path = eldbus_message_path_get(msg);
1958 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1959 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1962 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1964 ret = eldbus_message_method_return_new(msg);
1965 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1967 eo_do(obj, elm_interface_atspi_image_extents_get(EINA_FALSE, NULL, NULL, &w, &h));
1968 eldbus_message_arguments_append(ret, "i", w);
1969 eldbus_message_arguments_append(ret, "i", h);
1974 static const Eldbus_Method image_methods[] = {
1975 { "GetImageExtents", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"iiii", "extents"}), _image_extents_get, 0 },
1976 { "GetImagePosition", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}), _image_position_get, 0 },
1977 { "GetImageSize", NULL, ELDBUS_ARGS({"i", "width"}, {"i", "height"}), _image_size_get, 0 },
1978 { NULL, NULL, NULL, NULL, 0 }
1981 static Eldbus_Message *
1982 _text_string_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1984 const char *obj_path = eldbus_message_path_get(msg);
1986 Elm_Atspi_Text_Granularity gran;
1988 Eldbus_Message *ret;
1989 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1990 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1992 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
1994 if (!eldbus_message_arguments_get(msg, "iu", &start, &gran))
1995 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
1997 ret = eldbus_message_method_return_new(msg);
1998 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2000 eo_do(obj, str = elm_interface_atspi_text_string_get(gran, &start, &end));
2001 str = str ? str : strdup("");
2003 eldbus_message_arguments_append(ret, "sii", str, start, end);
2009 static Eldbus_Message *
2010 _text_text_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2012 const char *obj_path = eldbus_message_path_get(msg);
2014 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2015 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2018 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2020 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2021 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
2023 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
2024 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2026 eo_do(obj, str = elm_interface_atspi_text_get(start, end));
2027 str = str ? str : strdup("");
2029 eldbus_message_arguments_append(ret, "s", str);
2035 static Eldbus_Message *
2036 _text_caret_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2038 const char *obj_path = eldbus_message_path_get(msg);
2039 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2040 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2042 Eldbus_Message *ret;
2045 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2047 if (!eldbus_message_arguments_get(msg, "i", &offset))
2048 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2050 ret = eldbus_message_method_return_new(msg);
2051 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2053 eo_do(obj, res = elm_interface_atspi_text_caret_offset_set(offset));
2055 eldbus_message_arguments_append(ret, "b", res);
2060 static Eldbus_Message *
2061 _text_character_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2063 const char *obj_path = eldbus_message_path_get(msg);
2064 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2065 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2067 Eldbus_Message *ret;
2070 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2072 if (!eldbus_message_arguments_get(msg, "i", &offset))
2073 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2075 ret = eldbus_message_method_return_new(msg);
2076 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2078 eo_do(obj, res = elm_interface_atspi_text_character_get(offset));
2080 eldbus_message_arguments_append(ret, "i", res);
2085 static Eldbus_Message *
2086 _text_attribute_value_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2088 const char *name, *obj_path = eldbus_message_path_get(msg);
2090 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2091 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2093 Eldbus_Message *ret;
2096 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2098 if (!eldbus_message_arguments_get(msg, "is", &start, &name))
2099 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and attribute name expected.");
2101 ret = eldbus_message_method_return_new(msg);
2102 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2104 eo_do(obj, res = elm_interface_atspi_text_attribute_get(name, &start, &end, &value));
2105 eldbus_message_arguments_append(ret, "siib", value ? value : "", start, end, res);
2107 if (value) free(value);
2111 static Eldbus_Message *
2112 _text_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2114 const char *obj_path = eldbus_message_path_get(msg);
2115 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2116 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2118 Eldbus_Message *ret;
2119 Eldbus_Message_Iter *iter, *iter_array;
2121 Elm_Atspi_Text_Attribute *attr;
2123 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2125 if (!eldbus_message_arguments_get(msg, "i", &start))
2126 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2128 ret = eldbus_message_method_return_new(msg);
2129 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2131 iter = eldbus_message_iter_get(ret);
2132 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2133 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2135 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2137 EINA_LIST_FREE(attrs, attr)
2139 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2140 elm_atspi_text_text_attribute_free(attr);
2143 eldbus_message_iter_container_close(iter, iter_array);
2144 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2149 if (ret) eldbus_message_unref(ret);
2153 static Eldbus_Message *
2154 _text_default_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2156 const char *obj_path = eldbus_message_path_get(msg);
2157 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2158 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2159 int start = -1, end;
2160 Eldbus_Message *ret;
2161 Eldbus_Message_Iter *iter, *iter_array;
2163 Elm_Atspi_Text_Attribute *attr;
2165 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2167 ret = eldbus_message_method_return_new(msg);
2168 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2170 iter = eldbus_message_iter_get(ret);
2171 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2172 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2174 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2176 EINA_LIST_FREE(attrs, attr)
2178 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2179 elm_atspi_text_text_attribute_free(attr);
2182 eldbus_message_iter_container_close(iter, iter_array);
2183 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2188 if (ret) eldbus_message_unref(ret);
2192 static Eldbus_Message *
2193 _text_character_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2195 const char *obj_path = eldbus_message_path_get(msg);
2196 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2197 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2199 Eina_Rectangle rect;
2200 AtspiCoordType type;
2201 Eina_Bool screen_coords, res;
2202 Eldbus_Message *ret;
2204 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2206 if (!eldbus_message_arguments_get(msg, "iu", &offset, &type))
2207 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2209 ret = eldbus_message_method_return_new(msg);
2210 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2212 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2214 eo_do(obj, res = elm_interface_atspi_text_character_extents_get(offset, screen_coords, &rect));
2218 eldbus_message_unref(ret);
2219 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get character extents.");
2221 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2226 static Eldbus_Message *
2227 _text_offset_at_point_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2229 const char *obj_path = eldbus_message_path_get(msg);
2230 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2231 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2233 AtspiCoordType type;
2234 Eina_Bool screen_coords;
2235 Eldbus_Message *ret;
2237 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2239 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &type))
2240 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2242 ret = eldbus_message_method_return_new(msg);
2243 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2246 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2248 eo_do(obj, offset = elm_interface_atspi_text_offset_at_point_get(screen_coords, x, y));
2250 eldbus_message_arguments_append(ret, "i", offset);
2255 static Eldbus_Message *
2256 _text_n_selections_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2258 const char *obj_path = eldbus_message_path_get(msg);
2259 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2260 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2262 Eldbus_Message *ret;
2264 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2266 ret = eldbus_message_method_return_new(msg);
2267 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2269 eo_do(obj, n = elm_interface_atspi_text_selections_count_get());
2271 eldbus_message_arguments_append(ret, "i", n);
2276 static Eldbus_Message *
2277 _text_selection_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2279 const char *obj_path = eldbus_message_path_get(msg);
2280 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2281 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2282 int sel_num, start, end;
2283 Eldbus_Message *ret;
2285 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2287 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2288 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2290 ret = eldbus_message_method_return_new(msg);
2291 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2293 eo_do(obj, elm_interface_atspi_text_selection_get(sel_num, &start, &end));
2295 eldbus_message_arguments_append(ret, "ii", start, end);
2300 static Eldbus_Message *
2301 _text_selection_add(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2303 const char *obj_path = eldbus_message_path_get(msg);
2304 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2305 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2308 Eldbus_Message *ret;
2310 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2312 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2313 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end text offset expected.");
2315 ret = eldbus_message_method_return_new(msg);
2316 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2318 eo_do(obj, res = elm_interface_atspi_text_selection_add(start, end));
2320 eldbus_message_arguments_append(ret, "b", res);
2325 static Eldbus_Message *
2326 _text_selection_remove(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2328 const char *obj_path = eldbus_message_path_get(msg);
2329 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2330 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2333 Eldbus_Message *ret;
2335 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2337 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2338 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2340 ret = eldbus_message_method_return_new(msg);
2341 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2343 eo_do(obj, res = elm_interface_atspi_text_selection_remove(sel_num));
2345 eldbus_message_arguments_append(ret, "b", res);
2350 static Eldbus_Message *
2351 _text_selection_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2353 const char *obj_path = eldbus_message_path_get(msg);
2354 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2355 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2356 int sel_num, start, end;
2358 Eldbus_Message *ret;
2360 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2362 if (!eldbus_message_arguments_get(msg, "iii", &sel_num, &start, &end))
2363 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2365 ret = eldbus_message_method_return_new(msg);
2366 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2368 eo_do(obj, res = elm_interface_atspi_text_selection_set(sel_num, start, end));
2370 eldbus_message_arguments_append(ret, "b", res);
2375 static Eldbus_Message *
2376 _text_range_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2378 const char *obj_path = eldbus_message_path_get(msg);
2379 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2380 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2382 Eina_Rectangle rect;
2383 Eina_Bool screen_coords, res;
2384 AtspiCoordType type;
2385 Eldbus_Message *ret;
2387 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2389 if (!eldbus_message_arguments_get(msg, "iiu", &start, &end, &type))
2390 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2392 ret = eldbus_message_method_return_new(msg);
2393 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2395 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2396 eo_do(obj, res = elm_interface_atspi_text_range_extents_get(screen_coords, start, end, &rect));
2399 eldbus_message_unref(ret);
2400 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Can't get range extents.");
2403 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2408 static Eldbus_Message *
2409 _text_bounded_ranges_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2411 const char *obj_path = eldbus_message_path_get(msg);
2412 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2413 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2414 Eina_Rectangle rect;
2415 Eina_Bool screen_coords;
2416 AtspiCoordType type;
2417 Elm_Atspi_Text_Clip_Type xclip, yclip;
2419 Eldbus_Message *ret;
2420 Elm_Atspi_Text_Range *range;
2421 Eldbus_Message_Iter *iter, *iter_array, *iter_struct, *iter_var;
2423 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2425 if (!eldbus_message_arguments_get(msg, "iiiiuuu", &rect.x, &rect.y, &rect.w, &rect.h, &type, &xclip, &yclip))
2426 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected (x,y,w,h) of bounding box, screen coord type and x, y text clip types.");
2428 ret = eldbus_message_method_return_new(msg);
2429 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2431 iter = eldbus_message_iter_get(ret);
2432 iter_array = eldbus_message_iter_container_new(iter, 'a', "(iisv)");
2433 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2435 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2436 eo_do(obj, ranges = elm_interface_atspi_text_bounded_ranges_get(screen_coords, rect, xclip, yclip));
2438 EINA_LIST_FREE(ranges, range)
2440 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
2443 eldbus_message_iter_basic_append(iter_struct, 'i', range->start_offset);
2444 eldbus_message_iter_basic_append(iter_struct, 'i', range->end_offset);
2445 range->content = range->content ? range->content : strdup("");
2446 eldbus_message_iter_basic_append(iter_struct, 's', range->content);
2447 /* AT-SPI specification requires variant type in return, however
2448 * ATK or other implementations as well as AT Clients don't use it .
2449 * To cover spec a dummy value will be returned */
2450 iter_var = eldbus_message_iter_container_new(iter_struct, 'v', "i");
2453 eldbus_message_iter_basic_append(iter_var, 'i', 0);
2454 eldbus_message_iter_container_close(iter_struct, iter_var);
2456 eldbus_message_iter_container_close(iter_array, iter_struct);
2458 if (range->content) free(range->content);
2462 eldbus_message_iter_container_close(iter, iter_array);
2467 if (ret) eldbus_message_unref(ret);
2471 static Eldbus_Message *
2472 _text_run_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2474 const char *obj_path = eldbus_message_path_get(msg);
2475 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2476 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2478 Eldbus_Message *ret;
2479 Eldbus_Message_Iter *iter, *iter_array;
2480 Eina_List *attrs, *defaults;
2481 Elm_Atspi_Text_Attribute *attr;
2484 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2486 if (!eldbus_message_arguments_get(msg, "ib", &start, &incl_def))
2487 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and include defaults flag expected.");
2489 ret = eldbus_message_method_return_new(msg);
2490 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2492 iter = eldbus_message_iter_get(ret);
2493 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2494 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2496 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2500 eo_do(obj, defaults = elm_interface_atspi_text_default_attributes_get());
2501 attrs = eina_list_merge(attrs, defaults);
2504 EINA_LIST_FREE(attrs, attr)
2506 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2507 elm_atspi_text_text_attribute_free(attr);
2510 eldbus_message_iter_container_close(iter, iter_array);
2511 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2516 if (ret) eldbus_message_unref(ret);
2520 static const Eldbus_Method text_methods[] = {
2521 { "GetTextAtOffset", ELDBUS_ARGS({"i", "offset"}, {"u", "granularity"}), ELDBUS_ARGS({"s", "string"}, {"i", "startOffset"}, {"i", "endOffset"}), _text_string_at_offset_get, 0 },
2522 { "GetText", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"s", "string"}), _text_text_get, 0 },
2523 { "SetCaretOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"b", NULL}), _text_caret_offset_set, 0 },
2524 { "GetCharacterAtOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"i", NULL}), _text_character_at_offset_get, 0 },
2525 { "GetAttributeValue", ELDBUS_ARGS({"i", "offset"}, {"s", "attributeName"}), ELDBUS_ARGS({"s", NULL}, {"i", "startOffset"}, {"i", "endOffset"}, {"b", "defined"}), _text_attribute_value_get, 0 },
2526 { "GetAttributes", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_attributes_get, 0 },
2527 { "GetDefaultAttributes", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2528 { "GetCharacterExtents", ELDBUS_ARGS({"i", "offset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_character_extents_get, 0 },
2529 { "GetOffsetAtPoint", ELDBUS_ARGS({"i", "x"}, {"i","y"}, {"u", "coordType"}), ELDBUS_ARGS({"i", NULL}), _text_offset_at_point_get, 0 },
2530 { "GetNSelections", NULL, ELDBUS_ARGS({"i", NULL}), _text_n_selections_get, 0 },
2531 { "GetSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), _text_selection_get, 0 },
2532 { "AddSelection", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_add, 0 },
2533 { "RemoveSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"b", NULL}), _text_selection_remove, 0 },
2534 { "SetSelection", ELDBUS_ARGS({"i", "selectionNum"}, {"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_set, 0 },
2535 { "GetRangeExtents", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_range_extents_get, 0 },
2536 { "GetBoundedRanges", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "w"}, {"i", "h"}, {"u", "coordType"}, {"u", "xClipType"}, {"u", "yClipType"}), ELDBUS_ARGS({"a(issv)", NULL}), _text_bounded_ranges_get, 0 },
2537 { "GetAttributeRun", ELDBUS_ARGS({"i", "offset"}, {"b", "includeDefaults"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_run_attributes_get, 0 },
2538 { "GetDefaultAttributeSet", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2539 { NULL, NULL, NULL, NULL, 0 }
2542 static Eldbus_Message *
2543 _editable_text_text_content_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2545 const char *obj_path = eldbus_message_path_get(msg);
2546 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2547 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2548 const char *content;
2549 Eldbus_Message *ret;
2552 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2554 if (!eldbus_message_arguments_get(msg, "s", &content))
2555 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "String expected.");
2557 ret = eldbus_message_method_return_new(msg);
2558 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2560 eo_do(obj, res = elm_interface_atspi_editable_text_content_set(content));
2562 eldbus_message_arguments_append(ret, "b", res);
2567 static Eldbus_Message *
2568 _editable_text_text_insert(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2570 const char *obj_path = eldbus_message_path_get(msg);
2571 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2572 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2574 Eldbus_Message *ret;
2578 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2580 if (!eldbus_message_arguments_get(msg, "isi", &pos, &text, &len))
2581 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Postion, string, length expected.");
2583 ret = eldbus_message_method_return_new(msg);
2584 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2586 eo_do(obj, res = elm_interface_atspi_editable_text_insert(text, pos));
2588 eldbus_message_arguments_append(ret, "b", res);
2593 static Eldbus_Message *
2594 _editable_text_text_copy(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2596 const char *obj_path = eldbus_message_path_get(msg);
2597 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2598 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2599 Eldbus_Message *ret;
2603 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2605 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2606 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2608 ret = eldbus_message_method_return_new(msg);
2609 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2611 eo_do(obj, res = elm_interface_atspi_editable_text_copy(start, end));
2613 eldbus_message_arguments_append(ret, "b", res);
2618 static Eldbus_Message *
2619 _editable_text_text_cut(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2621 const char *obj_path = eldbus_message_path_get(msg);
2622 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2623 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2624 Eldbus_Message *ret;
2628 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2630 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2631 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2633 ret = eldbus_message_method_return_new(msg);
2634 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2636 eo_do(obj, res = elm_interface_atspi_editable_text_cut(start, end));
2638 eldbus_message_arguments_append(ret, "b", res);
2643 static Eldbus_Message *
2644 _editable_text_text_delete(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2646 const char *obj_path = eldbus_message_path_get(msg);
2647 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2648 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2649 Eldbus_Message *ret;
2653 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2655 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2656 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2658 ret = eldbus_message_method_return_new(msg);
2659 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2661 eo_do(obj, res = elm_interface_atspi_editable_text_delete(start, end));
2663 eldbus_message_arguments_append(ret, "b", res);
2668 static Eldbus_Message *
2669 _editable_text_text_paste(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2671 const char *obj_path = eldbus_message_path_get(msg);
2672 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2673 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2674 Eldbus_Message *ret;
2678 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2680 if (!eldbus_message_arguments_get(msg, "i", &pos))
2681 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2683 ret = eldbus_message_method_return_new(msg);
2684 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2686 eo_do(obj, res = elm_interface_atspi_editable_text_paste(pos));
2688 eldbus_message_arguments_append(ret, "b", res);
2694 _elm_atspi_bridge_plug_id_split(const char *plug_id, char **bus, char **path)
2696 if (!plug_id || !strcmp(plug_id, "")) return EINA_FALSE;
2697 unsigned int tokens = 0;
2698 char **split = eina_str_split_full(plug_id, ":", 0, &tokens);
2699 Eina_Bool ret = EINA_FALSE;
2702 if (!split[0] || !split[1])
2706 if (bus) *bus = strdup(split[0]);
2707 if (path) *path = strdup(split[1]);
2711 else if (tokens == 3)
2713 if (!split[0] || !split[1] || !split[2])
2718 snprintf(buf, sizeof(buf), "%s:%s",split[0], split[1]);
2719 if (bus) *bus = strdup(buf);
2720 if (path) *path = strdup(split[2]);
2730 static Eldbus_Message *
2731 _socket_embedded(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
2734 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2735 const char *obj_path = eldbus_message_path_get(msg);
2737 const char *bus, *path;
2738 Eo *bridge = _elm_atspi_bridge_get();
2739 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2740 eo_do(obj, proxy = elm_interface_atspi_accessible_parent_get());
2742 if (!eo_isa(proxy, ELM_ATSPI_PROXY_CLASS))
2743 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to embed object.");
2745 if (!eldbus_message_arguments_get(msg, "s", &path))
2746 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Plug id expected.");
2748 bus = eldbus_message_sender_get(msg);
2750 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
2752 _bridge_cache_build(bridge, proxy);
2754 return eldbus_message_method_return_new(msg);
2757 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2758 static Eldbus_Message *
2759 _socket_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2763 Eo *obj = eldbus_service_object_data_get(iface, "_atspi_obj");
2764 eo_do(obj, parent = eo_parent_get());
2765 Evas_Object *top = elm_object_top_widget_get(parent);
2767 if (!eldbus_message_arguments_get(msg, "ii", &x, &y))
2768 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
2770 eo_do(top, elm_interface_atspi_component_socket_offset_set(x, y));
2772 return eldbus_message_method_return_new(msg);
2776 static const Eldbus_Method editable_text_methods[] = {
2777 { "SetTextContents", ELDBUS_ARGS({"s", "newcontents"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_content_set, 0 },
2778 { "InsertText", ELDBUS_ARGS({"i", "position"}, {"s", "text"}, {"i", "length"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_insert, 0 },
2779 { "CopyText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), NULL, _editable_text_text_copy, 0 },
2780 { "CutText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_cut, 0 },
2781 { "DeleteText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_delete, 0 },
2782 { "PasteText", ELDBUS_ARGS({"i", "position"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_paste, 0 },
2783 { NULL, NULL, NULL, NULL, 0 }
2786 static const Eldbus_Method socket_methods[] = {
2787 { "Embedded", ELDBUS_ARGS({"s", "id"}), ELDBUS_ARGS({NULL, NULL}), _socket_embedded, 0 },
2788 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2789 { "SetOffset", ELDBUS_ARGS({"i", "x"}, {"i", "y"}), ELDBUS_ARGS({NULL, NULL}), _socket_offset_set, 0 },
2791 { NULL, NULL, NULL, NULL, 0 }
2794 static const Eldbus_Service_Interface_Desc socket_iface_desc = {
2795 ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL
2799 _bridge_object_from_path(Eo *bridge, const char *path)
2801 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2802 unsigned long long eo_ptr = 0;
2804 const char *tmp = path;
2807 int len = strlen(ELM_ACCESS_OBJECT_PATH_PREFIX);
2808 if (strncmp(path, ELM_ACCESS_OBJECT_PATH_PREFIX, len))
2811 tmp = path + len; /* Skip over the prefix */
2812 if (!strcmp(ELM_ACCESS_OBJECT_PATH_ROOT, tmp))
2813 return elm_atspi_bridge_root_get(bridge);
2815 sscanf(tmp, "%llu", &eo_ptr);
2816 eo = (Eo *) (uintptr_t) eo_ptr;
2818 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
2819 if (!eina_hash_find(pd->cache, &eo))
2821 WRN("Request for non-registered object: %s", path);
2825 ret = eo_isa(eo, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN) ? eo : NULL;
2831 _bridge_path_from_object(Eo *bridge, const Eo *eo)
2833 static char path[64];
2836 return ATSPI_DBUS_PATH_NULL;
2838 if (eo == elm_atspi_bridge_root_get(bridge))
2839 snprintf(path, sizeof(path), "%s%s", ELM_ACCESS_OBJECT_PATH_PREFIX, ELM_ACCESS_OBJECT_PATH_ROOT);
2841 snprintf(path, sizeof(path), ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE, (unsigned long long)(uintptr_t)eo);
2846 _accessible_property_get(const Eldbus_Service_Interface *interface, const char *property,
2847 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2848 Eldbus_Message **error)
2850 const char *ret = NULL, *obj_path = eldbus_message_path_get(request_msg);
2851 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2852 Eo *ret_obj = NULL, *obj = _bridge_object_from_path(bridge, obj_path);
2854 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, request_msg, error);
2856 if (!strcmp(property, "Name"))
2858 eo_do(obj, ret = elm_interface_atspi_accessible_name_get());
2861 eldbus_message_iter_basic_append(iter, 's', ret);
2864 else if (!strcmp(property, "Description"))
2866 eo_do(obj, ret = elm_interface_atspi_accessible_description_get());
2869 eldbus_message_iter_basic_append(iter, 's', ret);
2872 else if (!strcmp(property, "Parent"))
2874 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
2875 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
2876 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
2877 if ((!ret_obj) && (ELM_ATSPI_ROLE_APPLICATION == role))
2878 _object_desktop_reference_append(iter);
2880 _bridge_iter_object_reference_append(bridge, iter, ret_obj);
2883 else if (!strcmp(property, "ChildCount"))
2885 Eina_List *l = NULL;
2886 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
2887 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
2895 _selection_property_get(const Eldbus_Service_Interface *interface, const char *property,
2896 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2897 Eldbus_Message **error)
2900 const char *obj_path = eldbus_message_path_get(request_msg);
2901 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2902 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2904 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, request_msg, error);
2906 if (!strcmp(property, "NSelectedChildren"))
2908 eo_do(obj, n = elm_interface_atspi_selection_selected_children_count_get());
2909 eldbus_message_iter_basic_append(iter, 'i', n);
2916 _action_property_get(const Eldbus_Service_Interface *interface, const char *property,
2917 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2918 Eldbus_Message **error)
2921 const char *obj_path = eldbus_message_path_get(request_msg);
2922 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2923 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2925 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, request_msg, error);
2927 if (!strcmp(property, "NActions"))
2929 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
2930 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(actions));
2931 eina_list_free(actions);
2937 static Eldbus_Message*
2938 _value_properties_set(const Eldbus_Service_Interface *interface, const char *property,
2939 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg)
2943 const char *obj_path = eldbus_message_path_get(request_msg);
2944 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2945 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2947 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg);
2949 if (!eldbus_message_iter_arguments_get(iter, "d", &value))
2951 return eldbus_message_error_new(request_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: double.");
2954 if (!strcmp(property, "CurrentValue"))
2956 eo_do(obj, ret = elm_interface_atspi_value_and_text_set(value, NULL));
2957 Eldbus_Message *answer = eldbus_message_method_return_new(request_msg);
2958 eldbus_message_arguments_append(answer, "b", ret);
2966 _value_properties_get(const Eldbus_Service_Interface *interface, const char *property,
2967 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2968 Eldbus_Message **error)
2971 const char *obj_path = eldbus_message_path_get(request_msg);
2972 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2973 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2975 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg, error);
2977 if (!strcmp(property, "CurrentValue"))
2979 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
2980 eldbus_message_iter_basic_append(iter, 'd', value);
2983 if (!strcmp(property, "MinimumValue"))
2985 eo_do(obj, elm_interface_atspi_value_range_get(&value, NULL, NULL));
2986 eldbus_message_iter_basic_append(iter, 'd', value);
2989 if (!strcmp(property, "MaximumValue"))
2991 eo_do(obj, elm_interface_atspi_value_range_get(NULL, &value, NULL));
2992 eldbus_message_iter_basic_append(iter, 'd', value);
2995 if (!strcmp(property, "MinimumIncrement"))
2997 eo_do(obj, value = elm_interface_atspi_value_increment_get());
2998 eldbus_message_iter_basic_append(iter, 'd', value);
3005 _image_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3006 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3007 Eldbus_Message **error)
3010 const char *obj_path = eldbus_message_path_get(request_msg);
3011 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3012 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3014 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, request_msg, error);
3016 if (!strcmp(property, "ImageDescription"))
3018 eo_do(obj, value = elm_interface_atspi_image_description_get());
3019 value = value ? value : "";
3020 eldbus_message_iter_basic_append(iter, 's', value);
3023 if (!strcmp(property, "ImageLocale"))
3025 eo_do(obj, value = elm_interface_atspi_image_locale_get());
3026 value = value ? value : "";
3027 eldbus_message_iter_basic_append(iter, 's', value);
3034 _text_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3035 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3036 Eldbus_Message **error)
3038 const char *obj_path = eldbus_message_path_get(request_msg);
3039 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3040 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3043 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, request_msg, error);
3045 if (!strcmp(property, "CharacterCount"))
3047 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
3048 eldbus_message_iter_basic_append(iter, 'i', val);
3051 if (!strcmp(property, "CaretOffset"))
3053 eo_do(obj, val = elm_interface_atspi_text_caret_offset_get());
3054 eldbus_message_iter_basic_append(iter, 'i', val);
3060 static Eldbus_Message*
3061 _application_properties_set(const Eldbus_Service_Interface *iface, const char *property, Eldbus_Message_Iter *iter, const Eldbus_Message *input_msg)
3063 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3064 const char *obj_path = eldbus_message_path_get(input_msg);
3065 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3068 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
3069 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, input_msg);
3071 if (!eldbus_message_iter_arguments_get(iter, "i", &value))
3073 return eldbus_message_error_new(input_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: int.");
3076 if (!strcmp(property, "Id"))
3079 Eldbus_Message *answer = eldbus_message_method_return_new(input_msg);
3080 eldbus_message_arguments_append(answer, "b", EINA_TRUE);
3088 _application_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3089 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3090 Eldbus_Message **error)
3092 const char *obj_path = eldbus_message_path_get(request_msg);
3093 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3094 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3096 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
3097 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, request_msg, error);
3099 if (!strcmp(property, "ToolkitName"))
3101 eldbus_message_iter_basic_append(iter, 's', "elementary");
3104 if (!strcmp(property, "Version"))
3107 snprintf(buf, sizeof(buf), "%d.%d", ELM_VERSION_MAJOR, ELM_VERSION_MINOR);
3108 eldbus_message_iter_basic_append(iter, 's', buf);
3111 if (!strcmp(property, "Id"))
3113 eldbus_message_iter_basic_append(iter, 'i', pd->id);
3119 static const Eldbus_Property accessible_properties[] = {
3120 { "Name", "s", NULL, NULL, 0 },
3121 { "Description", "s", NULL, NULL, 0 },
3122 { "Parent", "(so)", NULL, NULL, 0 },
3123 { "ChildCount", "i", NULL, NULL, 0 },
3124 { NULL, NULL, NULL, NULL, 0 }
3127 static const Eldbus_Property action_properties[] = {
3128 { "NActions", "i", _action_property_get, NULL, 0 },
3129 { NULL, NULL, NULL, NULL, 0 }
3132 static const Eldbus_Property value_properties[] = {
3133 { "MinimumValue", "d", NULL, NULL, 0 },
3134 { "MaximumValue", "d", NULL, NULL, 0 },
3135 { "MinimumIncrement", "d", NULL, NULL, 0 },
3136 { "CurrentValue", "d", NULL, NULL, 0 },
3137 { NULL, NULL, NULL, NULL, 0 }
3140 static const Eldbus_Property image_properties[] = {
3141 { "ImageDescription", "s", NULL, NULL, 0 },
3142 { "ImageLocale", "s", NULL, NULL, 0 },
3143 { NULL, NULL, NULL, NULL, 0 }
3146 static const Eldbus_Property selection_properties[] = {
3147 { "NSelectedChildren", "i", _selection_property_get, NULL, 0 },
3148 { NULL, NULL, NULL, NULL, 0 }
3151 static const Eldbus_Property text_properties[] = {
3152 { "CharacterCount", "i", NULL, NULL, 0 },
3153 { "CaretOffset", "i", NULL, NULL, 0 },
3154 { NULL, NULL, NULL, NULL, 0 }
3157 static const Eldbus_Property application_properties[] = {
3158 { "ToolkitName", "s", NULL, NULL, 0 },
3159 { "Version", "s", NULL, NULL, 0 },
3160 { "Id", "i", NULL, NULL, 0 },
3161 { NULL, NULL, NULL, NULL, 0 }
3164 static const Eldbus_Service_Interface_Desc accessible_iface_desc = {
3165 ATSPI_DBUS_INTERFACE_ACCESSIBLE, accessible_methods, NULL, accessible_properties, _accessible_property_get, NULL
3168 static const Eldbus_Service_Interface_Desc action_iface_desc = {
3169 ATSPI_DBUS_INTERFACE_ACTION, action_methods, NULL, action_properties, NULL, NULL
3172 static const Eldbus_Service_Interface_Desc value_iface_desc = {
3173 ATSPI_DBUS_INTERFACE_VALUE, NULL, NULL, value_properties, _value_properties_get, _value_properties_set
3176 static const Eldbus_Service_Interface_Desc image_iface_desc = {
3177 ATSPI_DBUS_INTERFACE_IMAGE, image_methods, NULL, image_properties, _image_properties_get, NULL
3180 static const Eldbus_Service_Interface_Desc selection_iface_desc = {
3181 ATSPI_DBUS_INTERFACE_SELECTION, selection_methods, NULL, selection_properties, NULL, NULL
3184 static const Eldbus_Service_Interface_Desc text_iface_desc = {
3185 ATSPI_DBUS_INTERFACE_TEXT, text_methods, NULL, text_properties, _text_properties_get, NULL
3188 static const Eldbus_Service_Interface_Desc editable_text_iface_desc = {
3189 ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, editable_text_methods, NULL, NULL, NULL, NULL
3192 static const Eldbus_Service_Interface_Desc application_iface_desc = {
3193 ATSPI_DBUS_INTERFACE_APPLICATION, NULL, NULL, application_properties, _application_properties_get, _application_properties_set
3197 _collection_match_rule_free(struct collection_match_rule *rule)
3199 Elm_Atspi_Attribute *attr;
3200 eina_list_free(rule->ifaces);
3201 EINA_LIST_FREE(rule->attributes, attr)
3203 eina_stringshare_del(attr->key);
3204 eina_stringshare_del(attr->value);
3209 _collection_roles_convert(uint64_t roles[2])
3211 // Currently elm roles and atspi roles are binary compatible.
3212 // Implement this function when it will be needed.
3217 _collection_iter_match_rule_get(Eldbus_Message_Iter *iter, struct collection_match_rule *rule)
3219 Eldbus_Message_Iter *states_iter, *attrib_iter, *iter_arg, *role_iter, *ifc_iter;
3220 unsigned int *array;
3221 int array_count, state_match, attrib_match, role_match, ifc_match, reverse;
3222 const char *ifc_name;
3224 if (!eldbus_message_iter_arguments_get(iter, "aiia{ss}iaiiasib", &states_iter, &state_match, &attrib_iter, &attrib_match, &role_iter, &role_match, &ifc_iter, &ifc_match, &reverse))
3226 ERR("Unable to get message arguments");
3230 memset(rule, 0x0, sizeof(struct collection_match_rule));
3231 rule->statematchtype = state_match;
3232 rule->attributematchtype = attrib_match;
3233 rule->rolematchtype = role_match;
3234 rule->interfacematchtype = ifc_match;
3235 rule->reverse = reverse;
3237 if (!eldbus_message_iter_fixed_array_get(states_iter, 'i', &array, &array_count))
3240 //Roles according to libatspi impementation are transferred in 2-int element fixed bit array
3241 if (array_count != 2)
3243 ERR("Unexpected states array size");
3246 uint64_t states = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3247 rule->states = _atspi_state_set_to_elm_atspi_state_set(states);
3249 //Roles according to libatspi impementation are transferred in 4-int element fixed bit array
3250 if (!eldbus_message_iter_fixed_array_get(role_iter, 'i', &array, &array_count))
3253 if (array_count != 4)
3255 ERR("Unexpected roles array size");
3259 //convert atspi roles to elm_roles
3260 rule->roles[0] = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3261 rule->roles[1] = ((uint64_t)array[2] | ((uint64_t)array[3] << 32));
3263 _collection_roles_convert(rule->roles);
3265 //Get matching properties
3266 while (eldbus_message_iter_get_and_next(attrib_iter, '{', &iter_arg))
3268 const char *key, *value;
3269 if (eldbus_message_iter_arguments_get(iter_arg, "ss", &key, &value))
3271 Elm_Atspi_Attribute *attrib = calloc(sizeof(Elm_Atspi_Attribute), 1);
3272 attrib->key = eina_stringshare_add(key);
3273 attrib->value = eina_stringshare_add(value);
3274 rule->attributes = eina_list_append(rule->attributes, attrib);
3278 //Get interfaces to match
3279 while (eldbus_message_iter_get_and_next(ifc_iter, 's', &ifc_name))
3281 const Eo_Class *class = NULL;
3282 if (!strcmp(ifc_name, "action"))
3283 class = ELM_INTERFACE_ATSPI_ACTION_MIXIN;
3284 else if (!strcmp(ifc_name, "component"))
3285 class = ELM_INTERFACE_ATSPI_COMPONENT_MIXIN;
3286 else if (!strcmp(ifc_name, "editabletext"))
3287 class = ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE;
3288 else if (!strcmp(ifc_name, "text"))
3289 class = ELM_INTERFACE_ATSPI_TEXT_INTERFACE;
3290 else if (!strcmp(ifc_name, "image"))
3291 class = ELM_INTERFACE_ATSPI_SELECTION_INTERFACE;
3292 else if (!strcmp(ifc_name, "value"))
3293 class = ELM_INTERFACE_ATSPI_VALUE_INTERFACE;
3296 rule->ifaces = eina_list_append(rule->ifaces, class);
3299 _collection_match_rule_free(rule);
3308 _collection_match_interfaces_helper(Eo *obj, Eina_List *ifcs, Eina_Bool condition, Eina_Bool ret_if_true, Eina_Bool ret_if_false)
3313 EINA_LIST_FOREACH(ifcs, l, class)
3315 if (eo_isa(obj, class) == condition)
3318 return ret_if_false;
3322 _collection_match_interfaces_lookup(Eo *obj, struct collection_match_rule *rule)
3324 Eina_Bool ret = EINA_FALSE;
3326 switch (rule->interfacematchtype)
3328 case ATSPI_Collection_MATCH_INVALID:
3331 case ATSPI_Collection_MATCH_ALL:
3332 ret = _collection_match_interfaces_helper(
3333 obj, rule->ifaces, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3335 case ATSPI_Collection_MATCH_ANY:
3336 ret = _collection_match_interfaces_helper(
3337 obj, rule->ifaces, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3339 case ATSPI_Collection_MATCH_NONE:
3340 ret = _collection_match_interfaces_helper(
3341 obj, rule->ifaces, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3350 _collection_match_states_lookup(Eo *obj, struct collection_match_rule *rule)
3352 Eina_Bool ret = EINA_FALSE;
3353 Elm_Atspi_State_Set ss;
3355 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
3357 switch (rule->statematchtype)
3359 case ATSPI_Collection_MATCH_INVALID:
3362 case ATSPI_Collection_MATCH_ALL:
3363 ret = (ss & rule->states) == rule->states;
3365 case ATSPI_Collection_MATCH_ANY:
3366 ret = (ss & rule->states) > 0;
3368 case ATSPI_Collection_MATCH_NONE:
3369 ret = (ss & rule->states) == 0;
3379 _collection_match_roles_lookup(Eo *obj, struct collection_match_rule *rule)
3381 Eina_Bool ret = EINA_FALSE;
3382 Elm_Atspi_Role role;
3385 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
3390 role_set = rule->roles[1];
3393 role_set = rule->roles[0];
3397 ERR("Elm_Atspi_Role enum value exceeds 127. Unable to compare with roles bit field.");
3401 switch (rule->rolematchtype)
3403 case ATSPI_Collection_MATCH_INVALID:
3406 case ATSPI_Collection_MATCH_ALL:
3407 case ATSPI_Collection_MATCH_ANY:
3408 ret = (role_set & (1ULL << role)) > 0;
3410 case ATSPI_Collection_MATCH_NONE:
3411 ret = (role_set & (1ULL << role)) == 0;
3421 _collection_match_attributes_helper(Eina_List *obj_attribs, Eina_List *attribs, Eina_Bool compare, Eina_Bool ret_if_compare, Eina_Bool ret_default)
3424 Elm_Atspi_Attribute *attr, *attr2;
3426 EINA_LIST_FOREACH(attribs, l, attr)
3428 EINA_LIST_FOREACH(obj_attribs, l2, attr2)
3430 if ((attr->key && attr2->key &&
3431 attr->value && attr2->value &&
3432 !strcmp(attr->key, attr2->key) &&
3433 !strcmp(attr->value, attr2->value)) == compare)
3435 return ret_if_compare;
3444 _collection_match_attributes_lookup(Eo *obj, struct collection_match_rule *rule)
3446 Eina_Bool ret = EINA_FALSE;
3447 Eina_List *obj_attribs;
3449 eo_do(obj, obj_attribs = elm_interface_atspi_accessible_attributes_get());
3451 switch (rule->attributematchtype)
3453 case ATSPI_Collection_MATCH_INVALID:
3456 case ATSPI_Collection_MATCH_ALL:
3457 ret = _collection_match_attributes_helper(
3458 obj_attribs, rule->attributes, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3460 case ATSPI_Collection_MATCH_ANY:
3461 ret = _collection_match_attributes_helper(
3462 obj_attribs, rule->attributes, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3464 case ATSPI_Collection_MATCH_NONE:
3465 ret = _collection_match_attributes_helper(
3466 obj_attribs, rule->attributes, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3472 elm_atspi_attributes_list_free(obj_attribs);
3478 _collection_sort_order_canonical(struct collection_match_rule *rule, Eina_List **ls,
3480 Eo *obj, long index, Eina_Bool flag,
3481 Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3484 Eina_List *children;
3485 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
3486 long acount = eina_list_count(children);
3487 Eina_Bool prev = pobj ? EINA_TRUE : EINA_FALSE;
3489 for (; i < acount && (max == 0 || count < max); i++)
3491 Eo *child = eina_list_nth(children, i);
3493 if (prev && child == pobj)
3495 eina_list_free(children);
3499 if (flag && _collection_match_interfaces_lookup(child, rule)
3500 && _collection_match_states_lookup(child, rule)
3501 && _collection_match_roles_lookup(child, rule)
3502 && _collection_match_attributes_lookup(child, rule))
3504 *ls = eina_list_append(*ls, child);
3511 if (recurse && traverse)
3512 count = _collection_sort_order_canonical(rule, ls, count,
3513 max, child, 0, EINA_TRUE,
3514 pobj, recurse, traverse);
3516 eina_list_free(children);
3521 _collection_sort_order_reverse_canonical(struct collection_match_rule *rule, Eina_List **ls,
3522 int count, int max, Eo *obj, Eina_Bool flag, Eo *pobj)
3524 Eo *nextobj, *parent;
3526 Eina_List *children;
3528 /* This breaks us out of the recursion. */
3529 if (!obj || obj == pobj)
3534 /* Add to the list if it matches */
3535 if (flag && _collection_match_interfaces_lookup(obj, rule)
3536 && _collection_match_states_lookup(obj, rule)
3537 && _collection_match_roles_lookup(obj, rule)
3538 && _collection_match_attributes_lookup(obj, rule)
3539 && (max == 0 || count < max))
3541 *ls = eina_list_append(*ls, obj);
3548 /* Get the current nodes index in it's parent and the parent object. */
3550 indexinparent = elm_interface_atspi_accessible_index_in_parent_get(),
3551 parent = elm_interface_atspi_accessible_parent_get());
3553 if ((indexinparent > 0) && ((max == 0) || (count < max)))
3555 /* there are still some siblings to visit so get the previous sibling
3556 and get it's last descendant.
3557 First, get the previous sibling */
3558 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
3559 nextobj = eina_list_nth(children, indexinparent - 1);
3560 eina_list_free(children);
3562 /* Now, drill down the right side to the last descendant */
3564 eo_do(nextobj, children = elm_interface_atspi_accessible_children_get());
3565 if (children) nextobj = eina_list_last_data_get(children);
3566 eina_list_free(children);
3569 /* recurse with the last descendant */
3570 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3571 nextobj, EINA_TRUE, pobj);
3573 else if (max == 0 || count < max)
3575 /* no more siblings so next node must be the parent */
3576 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3577 parent, EINA_TRUE, pobj);
3584 _collection_inbackorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3587 *list = eina_list_append(*list, obj);
3589 _collection_sort_order_reverse_canonical(rule, list, 0, max, obj, EINA_TRUE, collection);
3591 *list = eina_list_remove_list(*list, *list);
3597 _collection_inorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3598 int count, int max, Eo *obj, Eina_Bool traverse)
3602 count = _collection_sort_order_canonical(rule, list, count, max, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3604 while ((max == 0 || count < max) && obj && obj != collection)
3608 parent = elm_interface_atspi_accessible_parent_get(),
3609 idx = elm_interface_atspi_accessible_index_in_parent_get());
3610 count = _collection_sort_order_canonical(rule, list, count, max, parent,
3611 idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3615 if (max == 0 || count < max)
3616 count = _collection_sort_order_canonical(rule, list, count, max,
3617 obj, idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3623 _collection_query(struct collection_match_rule *rule, AtspiCollectionSortOrder sortby,
3624 Eina_List **list, int count, int max, Eo *obj, long index,
3625 Eina_Bool flag, Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3629 case ATSPI_Collection_SORT_ORDER_CANONICAL:
3630 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3631 pobj, recurse, traverse);
3633 case ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL:
3634 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3635 pobj, recurse, traverse);
3636 *list = eina_list_reverse(*list);
3640 WRN("Unhandled sort method");
3646 static Eldbus_Message*
3647 _collection_return_msg_from_list(Elm_Atspi_Bridge *bridge, const Eldbus_Message *msg, const Eina_List *objs)
3649 Eldbus_Message *ret;
3651 Eldbus_Message_Iter *iter, *array_iter;
3654 ret = eldbus_message_method_return_new(msg);
3655 if (!ret) return NULL;
3657 iter = eldbus_message_iter_get(ret);
3658 array_iter = eldbus_message_iter_container_new(iter, 'a', "(so)");
3660 EINA_LIST_FOREACH(objs, l, obj)
3662 _bridge_object_register(bridge, obj);
3663 _bridge_iter_object_reference_append(bridge, array_iter, obj);
3666 eldbus_message_iter_container_close(iter, array_iter);
3671 _collection_get_matches_from_handle(Eo *collection, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, int max, Eina_Bool traverse)
3673 Eina_List *result = NULL;
3679 case ATSPI_Collection_TREE_INORDER:
3680 _collection_inorder(collection, rule, &result, 0, max, current, traverse);
3681 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3682 result = eina_list_reverse(result);
3684 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3686 idx = elm_interface_atspi_accessible_index_in_parent_get(),
3687 parent = elm_interface_atspi_accessible_parent_get());
3688 _collection_query(rule, sortby, &result, 0, max, parent, idx, EINA_FALSE, NULL, EINA_TRUE, traverse);
3690 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3691 _collection_query(rule, sortby, &result, 0, max, current, 0, EINA_FALSE, NULL, EINA_TRUE, traverse);
3694 ERR("Tree parameter value not handled");
3700 static Eldbus_Message*
3701 _collection_get_matches_from(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3703 const char *obj_path = eldbus_message_path_get(msg);
3704 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3705 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3706 Eldbus_Message *ret;
3707 Eldbus_Message_Iter *iter, *rule_iter;
3708 struct collection_match_rule rule;
3710 AtspiCollectionTreeTraversalType tree;
3712 AtspiCollectionSortOrder sortby;
3713 Eina_List *result = NULL;
3715 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3717 iter = eldbus_message_iter_get(msg);
3718 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3720 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uuib", &obj_path, &rule_iter, &sortby, &tree, &count, &traverse))
3722 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3725 current = _bridge_object_from_path(bridge, obj_path);
3727 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3729 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3730 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3732 result = _collection_get_matches_from_handle(obj, current, &rule, sortby, tree, count, traverse);
3733 ret = _collection_return_msg_from_list(bridge, msg, result);
3735 eina_list_free(result);
3736 _collection_match_rule_free(&rule);
3742 _collection_get_matches_to_handle(Eo *obj, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, Eina_Bool limit, int max, Eina_Bool traverse)
3744 Eina_List *result = NULL;
3745 Eo *collection = obj;
3748 eo_do(obj, collection = elm_interface_atspi_accessible_parent_get());
3752 case ATSPI_Collection_TREE_INORDER:
3753 _collection_inbackorder(obj, rule, &result, max, current);
3754 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3755 result = eina_list_reverse(result);
3757 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3758 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3760 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3761 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3764 ERR("Tree parameter value not handled");
3771 static Eldbus_Message*
3772 _collection_get_matches_to(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3774 const char *obj_path = eldbus_message_path_get(msg);
3775 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3776 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3777 Eldbus_Message *ret;
3778 Eldbus_Message_Iter *iter, *rule_iter;
3779 struct collection_match_rule rule;
3781 AtspiCollectionTreeTraversalType tree;
3783 AtspiCollectionSortOrder sortby;
3784 Eina_List *result = NULL;
3787 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3789 iter = eldbus_message_iter_get(msg);
3790 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3792 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uubib", &obj_path, &rule_iter, &sortby, &tree, &limit, &count, &traverse))
3794 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, tree, limit count or traverse values.");
3797 current = _bridge_object_from_path(bridge, obj_path);
3799 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3801 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3802 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3804 result = _collection_get_matches_to_handle(obj, current, &rule, sortby, tree, limit, count, traverse);
3805 ret = _collection_return_msg_from_list(bridge, msg, result);
3807 eina_list_free(result);
3808 _collection_match_rule_free(&rule);
3813 static Eldbus_Message*
3814 _collection_get_matches(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
3816 const char *obj_path = eldbus_message_path_get(msg);
3817 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3818 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3819 Eldbus_Message *ret;
3820 Eldbus_Message_Iter *iter, *rule_iter;
3821 struct collection_match_rule rule;
3824 AtspiCollectionSortOrder sortby;
3825 Eina_List *result = NULL;
3827 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3829 iter = eldbus_message_iter_get(msg);
3830 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3832 if (!eldbus_message_iter_arguments_get(iter, "(aiia{ss}iaiiasib)uib", &rule_iter, &sortby, &count, &traverse))
3834 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3837 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3838 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3840 _collection_query(&rule, sortby, &result, 0, count, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3842 ret = _collection_return_msg_from_list(bridge, msg, result);
3844 eina_list_free(result);
3845 _collection_match_rule_free(&rule);
3850 static const Eldbus_Method collection_methods[] = {
3852 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3853 {"u", "sortby"}, {"u", "tree"}, {"i", "count"}, {"b", "traverse"}),
3854 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_from, 0 },
3856 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3857 {"u", "sortby"}, {"u", "tree"}, {"b", "limit_scope"},
3858 {"i", "count"}, {"b", "traverse"}),
3859 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_to, 0 },
3861 ELDBUS_ARGS({"(aiia{ss}iaiiasib)", "match_rule"},
3862 {"u", "sortby"}, {"i", "count"}, {"b", "traverse"}),
3863 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches, 0 },
3864 { NULL, NULL, NULL, NULL, 0 }
3867 static const Eldbus_Service_Interface_Desc collection_iface_desc = {
3868 ATSPI_DBUS_INTERFACE_COLLECTION, collection_methods, NULL, NULL, NULL, NULL
3872 _object_get_bus_name_and_path(Eo *bridge, const Eo *obj, const char **bus_name, const char **path)
3874 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
3876 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
3877 if (eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
3879 const char *pbus = "", *ppath = ATSPI_DBUS_PATH_NULL;
3880 eo_do(obj, elm_obj_atspi_proxy_address_get(&pbus, &ppath));
3883 if (bus_name) *bus_name = pbus;
3884 if (path) *path = ppath;
3887 DBG("Invalid proxy address! Address not set before connecting/listening. Or after proxy is removed.");
3889 if (bus_name) *bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
3890 if (path) *path = _bridge_path_from_object(bridge, obj);
3895 _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj)
3897 EINA_SAFETY_ON_NULL_RETURN(iter);
3899 const char *pbus = NULL, *ppath = NULL;
3900 _object_get_bus_name_and_path(bridge, obj, &pbus, &ppath);
3901 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3902 eldbus_message_iter_basic_append(iter_struct, 's', pbus);
3903 eldbus_message_iter_basic_append(iter_struct, 'o', ppath);
3904 eldbus_message_iter_container_close(iter, iter_struct);
3908 _object_desktop_reference_append(Eldbus_Message_Iter *iter)
3910 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3911 EINA_SAFETY_ON_NULL_RETURN(iter);
3913 eldbus_message_iter_basic_append(iter_struct, 's', ATSPI_DBUS_NAME_REGISTRY);
3914 eldbus_message_iter_basic_append(iter_struct, 'o', ATSPI_DBUS_PATH_ROOT);
3915 eldbus_message_iter_container_close(iter, iter_struct);
3919 _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj)
3921 Eldbus_Message_Iter *iter_array;
3922 iter_array = eldbus_message_iter_container_new(iter, 'a', "s");
3923 if (!iter_array) return;
3925 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
3927 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE);
3928 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COLLECTION);
3930 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN))
3931 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACTION);
3932 if (eo_isa(obj, ELM_ATSPI_APP_OBJECT_CLASS))
3933 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_APPLICATION);
3934 if (eo_isa(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN))
3935 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COMPONENT);
3936 if (eo_isa(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE))
3937 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_EDITABLE_TEXT);
3938 if (eo_isa(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN))
3939 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_IMAGE);
3940 if (eo_isa(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
3941 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_SELECTION);
3942 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
3943 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_TEXT);
3944 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
3945 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_VALUE);
3947 eldbus_message_iter_container_close(iter, iter_array);
3951 _cache_item_reference_append_cb(Eo *bridge, Eo *data, Eldbus_Message_Iter *iter_array)
3953 if (!eo_ref_get(data) || eo_destructed_is(data))
3956 Eldbus_Message_Iter *iter_struct, *iter_sub_array;
3957 Elm_Atspi_State_Set states;
3958 Elm_Atspi_Role role;
3959 Eo *root = elm_atspi_bridge_root_get(bridge);
3961 eo_do(data, role = elm_interface_atspi_accessible_role_get());
3963 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
3964 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_struct, EINA_TRUE);
3966 /* Marshall object path */
3967 _bridge_iter_object_reference_append(bridge, iter_struct, data);
3969 /* Marshall application */
3970 _bridge_iter_object_reference_append(bridge, iter_struct, root);
3973 eo_do(data, parent = elm_interface_atspi_accessible_parent_get());
3974 /* Marshall parent */
3975 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
3976 _object_desktop_reference_append(iter_struct);
3978 _bridge_iter_object_reference_append(bridge, iter_struct, parent);
3980 /* Marshall children */
3981 Eina_List *children_list = NULL, *l;
3984 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3985 Elm_Atspi_State_Set ss;
3986 eo_do(data, ss = elm_interface_atspi_accessible_state_set_get());
3988 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
3989 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
3991 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3992 if (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
3994 eo_do(data, children_list = elm_interface_atspi_accessible_children_get());
3996 EINA_LIST_FOREACH(children_list, l, child)
3997 _bridge_iter_object_reference_append(bridge, iter_sub_array, child);
3999 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
4000 eina_list_free(children_list);
4004 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4006 /* Marshall interfaces */
4007 _iter_interfaces_append(iter_struct, data);
4010 const char *name = NULL;
4011 eo_do(data, name = elm_interface_atspi_accessible_name_get());
4015 eldbus_message_iter_basic_append(iter_struct, 's', name);
4018 eldbus_message_iter_basic_append(iter_struct, 'u', role);
4020 /* Marshall description */
4021 const char* descritpion = NULL;
4022 eo_do(data, descritpion = elm_interface_atspi_accessible_description_get());
4025 eldbus_message_iter_basic_append(iter_struct, 's', descritpion);
4027 /* Marshall state set */
4028 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "u");
4029 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
4031 eo_do(data, states = elm_interface_atspi_accessible_state_set_get());
4033 unsigned int s1 = states & 0xFFFFFFFF;
4034 unsigned int s2 = (states >> 32) & 0xFFFFFFFF;
4035 eldbus_message_iter_basic_append(iter_sub_array, 'u', s1);
4036 eldbus_message_iter_basic_append(iter_sub_array, 'u', s2);
4038 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4039 eldbus_message_iter_container_close(iter_array, iter_struct);
4044 if (iter_struct) eldbus_message_iter_del(iter_struct);
4048 static Eldbus_Message *
4049 _cache_get_items(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
4051 Eldbus_Message_Iter *iter, *iter_array;
4052 Eldbus_Message *ret;
4053 Eina_List *to_process;
4056 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4057 if (!bridge) return NULL;
4059 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4061 ret = eldbus_message_method_return_new(msg);
4062 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4064 iter = eldbus_message_iter_get(ret);
4065 iter_array = eldbus_message_iter_container_new(iter, 'a', CACHE_ITEM_SIGNATURE);
4066 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
4068 eo_do(bridge, root = elm_obj_atspi_bridge_root_get());
4069 to_process = eina_list_append(NULL, root);
4073 Eo *obj = eina_list_data_get(to_process);
4074 to_process = eina_list_remove_list(to_process, to_process);
4075 _cache_item_reference_append_cb(bridge, obj, iter_array);
4076 _bridge_object_register(bridge, obj);
4078 Eina_List *children;
4079 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
4080 to_process = eina_list_merge(to_process, children);
4083 eldbus_message_iter_container_close(iter, iter_array);
4087 if (ret) eldbus_message_unref(ret);
4091 static const Eldbus_Method cache_methods[] = {
4092 { "GetItems", NULL, ELDBUS_ARGS({CACHE_ITEM_SIGNATURE, "items"}), _cache_get_items, 0 },
4093 { NULL, NULL, NULL, NULL, 0 }
4096 static const Eldbus_Signal cache_signals[] = {
4097 [ATSPI_OBJECT_CHILD_ADDED] = { "AddAccessible", ELDBUS_ARGS({"((so)(so)a(so)assusau)", "added"}), 0},
4098 [ATSPI_OBJECT_CHILD_REMOVED] = { "RemoveAccessible", ELDBUS_ARGS({ "(so)", "removed" }), 0},
4102 static const Eldbus_Service_Interface_Desc cache_iface_desc = {
4103 ATSPI_DBUS_INTERFACE_CACHE, cache_methods, cache_signals, NULL, NULL, NULL
4106 // Component interface
4107 static Eldbus_Message *
4108 _component_contains(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4110 const char *obj_path = eldbus_message_path_get(msg);
4111 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4112 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4114 Eina_Bool contains = EINA_FALSE;
4115 AtspiCoordType coord_type;
4116 Eldbus_Message *ret;
4118 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4120 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4121 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4123 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4124 eo_do(obj, contains = elm_interface_atspi_component_contains(type, x, y));
4126 ret = eldbus_message_method_return_new(msg);
4127 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4129 eldbus_message_arguments_append(ret, "b", contains);
4134 static Eldbus_Message *
4135 _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4137 const char *obj_path = eldbus_message_path_get(msg);
4138 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4139 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4140 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4142 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4144 Eo *accessible = NULL;
4145 AtspiCoordType coord_type;
4146 Eldbus_Message *ret;
4147 Eldbus_Message_Iter *iter;
4149 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4151 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
4152 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
4153 if (ecore_evas_obscured_get(ee))
4154 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
4157 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4158 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4160 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4161 Evas_Object *top = elm_object_top_widget_get(obj);
4164 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
4170 ret = eldbus_message_method_return_new(msg);
4171 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4173 iter = eldbus_message_iter_get(ret);
4174 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4175 eo_do(obj, accessible = elm_interface_atspi_component_accessible_at_point_get(type, x, y));
4176 _bridge_iter_object_reference_append(bridge, iter, accessible);
4177 _bridge_object_register(bridge, accessible);
4182 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
4184 NEIGHBOR_SEARCH_MODE_NORMAL = 0,
4185 NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT = 1,
4186 NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING = 2,
4187 NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE = 3,
4188 } GetNeighborSearchMode;
4190 typedef struct accessibility_navigation_pointer_table {
4191 AtspiRole (*object_get_role)(struct accessibility_navigation_pointer_table *t, void *ptr);
4192 uint64_t (*object_get_state_set)(struct accessibility_navigation_pointer_table *t, void *ptr);
4193 void *(*get_object_in_relation_by_type)(struct accessibility_navigation_pointer_table *t, void *ptr, AtspiRelationType type);
4194 unsigned char (*object_is_zero_size)(struct accessibility_navigation_pointer_table *t, void *ptr);
4195 void *(*get_parent)(struct accessibility_navigation_pointer_table *t, void *ptr);
4196 unsigned char (*object_is_scrollable)(struct accessibility_navigation_pointer_table *t, void *ptr);
4197 void *(*get_object_at_point)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4198 unsigned char (*object_contains)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4199 unsigned char (*object_is_proxy)(struct accessibility_navigation_pointer_table *t, void *ptr);
4200 } accessibility_navigation_pointer_table;
4202 #define CALL(fncname, ...) table->fncname(table, __VA_ARGS__)
4203 static unsigned char _accept_object_check_role(accessibility_navigation_pointer_table *table EINA_UNUSED, void *obj)
4205 return _elm_widget_atspi_role_acceptable_check(obj);
4208 static unsigned char _state_set_is_set(uint64_t state_set, AtspiStateType state)
4210 return (state_set & ((uint64_t)1 << (unsigned int)state)) != 0;
4213 static unsigned char _object_is_defunct(accessibility_navigation_pointer_table *table, void *ptr)
4215 uint64_t states = CALL(object_get_state_set, ptr);
4216 return _state_set_is_set(states, ATSPI_STATE_DEFUNCT);
4219 static unsigned char _object_role_is_acceptable_when_navigating_next_prev(accessibility_navigation_pointer_table *table, void *obj)
4221 AtspiRole role = CALL(object_get_role, obj);
4222 return role != ATSPI_ROLE_POPUP_MENU && role != ATSPI_ROLE_DIALOG;
4225 static void *_get_object_in_relation_flow(accessibility_navigation_pointer_table *table, void *source, unsigned char forward)
4227 return CALL(get_object_in_relation_by_type, source, forward ? ATSPI_RELATION_FLOWS_TO : ATSPI_RELATION_FLOWS_FROM);
4230 static unsigned char _object_is_item(accessibility_navigation_pointer_table *table, void *obj)
4232 AtspiRole role = CALL(object_get_role, obj);
4233 return role == ATSPI_ROLE_LIST_ITEM || role == ATSPI_ROLE_MENU_ITEM;
4236 static unsigned char _object_is_highlightable(accessibility_navigation_pointer_table *table, void *obj)
4238 uint64_t state_set = CALL(object_get_state_set, obj);
4239 return _state_set_is_set(state_set, ATSPI_STATE_HIGHLIGHTABLE);
4242 static unsigned char _object_is_visible(accessibility_navigation_pointer_table *table, void *obj)
4244 uint64_t state_set = CALL(object_get_state_set, obj);
4245 return _state_set_is_set(state_set, ATSPI_STATE_VISIBLE);
4248 static unsigned char _object_is_showing(accessibility_navigation_pointer_table *table, void *obj)
4250 uint64_t state_set = CALL(object_get_state_set, obj);
4251 return _state_set_is_set(state_set, ATSPI_STATE_SHOWING);
4254 static unsigned char _object_is_collapsed(accessibility_navigation_pointer_table *table, void *obj)
4256 uint64_t state_set = CALL(object_get_state_set, obj);
4258 _state_set_is_set(state_set, ATSPI_STATE_EXPANDABLE) &&
4259 !_state_set_is_set(state_set, ATSPI_STATE_EXPANDED);
4262 static unsigned char _object_has_modal_state(accessibility_navigation_pointer_table *table, void *obj)
4264 uint64_t state_set = CALL(object_get_state_set, obj);
4265 return _state_set_is_set(state_set, ATSPI_STATE_MODAL);
4268 static unsigned char _object_is_zero_size(accessibility_navigation_pointer_table *table, void *obj)
4270 return CALL(object_is_zero_size, obj);
4273 static void *_get_scrollable_parent(accessibility_navigation_pointer_table *table, void *obj)
4277 obj = CALL(get_parent, obj);
4278 if (obj && CALL(object_is_scrollable, obj)) return obj;
4282 static unsigned char _accept_object(accessibility_navigation_pointer_table *table, void *obj)
4285 if (!_object_is_visible(table, obj)) return 0;
4286 if (!_accept_object_check_role(table, obj)) return 0;
4287 if (CALL(get_object_in_relation_by_type, obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0;
4288 if (!_object_is_highlightable(table, obj)) return 0;
4290 if (_get_scrollable_parent(table, obj) != NULL)
4292 void *parent = CALL(get_parent, obj);
4296 return !_object_is_item(table, obj) || !_object_is_collapsed(table, parent);
4301 if (_object_is_zero_size(table, obj)) return 0;
4302 if (!_object_is_showing(table, obj)) return 0;
4307 /* The target cannot be a parent of root */
4308 static Eina_Bool _target_validation_check(Eo *target, Eo *root)
4311 eo_do(root, parent = elm_interface_atspi_accessible_parent_get());
4315 if (parent == target) return EINA_FALSE;
4316 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4322 static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigation_pointer_table *table,
4323 void *root, int x, int y, unsigned char coordinates_are_screen_based)
4325 if (!root) return NULL;
4326 void *prev_root = root;
4328 void *return_value = NULL;
4331 void *target = CALL(get_object_at_point, root, x, y, coordinates_are_screen_based);
4333 if (target == root || target == prev_root) break;
4334 if (!_target_validation_check(target, root)) break;
4336 // always return proxy, so atspi lib can call on it again
4337 if (CALL(object_is_proxy, target)) return target;
4340 void *relation_obj = CALL(get_object_in_relation_by_type, root, ATSPI_RELATION_CONTROLLED_BY);
4341 unsigned char contains = 0;
4344 contains = CALL(object_contains, relation_obj, x, y, coordinates_are_screen_based);
4345 if (contains) root = relation_obj;
4348 if (_accept_object(table, root))
4350 return_value = root;
4351 if (contains) break;
4355 if (return_value && _object_has_modal_state(table, return_value)) return_value = NULL;
4356 return return_value;
4359 static void *_find_non_defunct_child(accessibility_navigation_pointer_table *table,
4360 Eina_List *children, unsigned int current_index, unsigned char forward)
4362 unsigned int children_count = eina_list_count(children);
4363 for(; current_index < children_count; forward ? ++current_index : --current_index)
4365 void *n = eina_list_nth(children, current_index);
4366 if (n && !_object_is_defunct(table, n)) return n;
4371 static void *_directional_depth_first_search_try_non_defunct_child(accessibility_navigation_pointer_table *table,
4372 void *node, Eina_List *children, unsigned char forward)
4374 unsigned int children_count = eina_list_count(children);
4375 if (children_count > 0)
4377 unsigned char is_showing = _get_scrollable_parent(table, node) == NULL ? _object_is_showing(table, node) : 1;
4380 return _find_non_defunct_child(table, children, forward ? 0 : children_count - 1, forward);
4386 static Eina_List *_scrollable_parent_list_get(Eo *obj)
4388 Eina_List *ret = NULL;
4393 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
4396 if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4398 ret = eina_list_append(ret, parent);
4400 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4407 static void _viewport_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
4409 eo_do(obj, elm_interface_scrollable_content_viewport_geometry_get(x, y, w, h));
4410 /* widget implements scrollable interface but does not use scoller
4411 in this case, use widget geometry */
4412 if (*w == 0 || *h == 0)
4414 INF("%s is zero sized content viewport", eo_class_name_get(eo_class_get(obj)));
4415 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_FALSE, x, y, w, h));
4420 _new_scrollable_parent_viewport_geometry_get(Eo *node, Eo *start,
4421 int *x, int *y, int *w, int *h)
4423 Eina_Bool ret = EINA_FALSE;
4427 n_spl = _scrollable_parent_list_get(node);
4428 s_spl = _scrollable_parent_list_get(start);
4432 EINA_LIST_FOREACH(s_spl, l, sp)
4434 n_spl = eina_list_remove(n_spl, sp);
4437 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4439 unsigned int count = eina_list_count(n_spl);
4442 sp = eina_list_nth(n_spl, count - 1);
4443 _viewport_geometry_get(sp, &sx, &sy, &sw, &sh);
4455 static Eina_List *_valid_children_get(Eina_List *children, Eo *start, Eo *root)
4457 /* condition to find first(last) object regardless of scrollable parent.
4458 looping navigation does not care scrollable parent.
4459 1. currently highlighted object exists
4460 2. both start and root are same */
4461 Eo *current = _elm_object_accessibility_currently_highlighted_get();
4462 if (current && start == root) return children;
4465 child = eina_list_nth(children, 0);
4469 Evas_Coord x = 0, y = 0, w = 0, h = 0;
4470 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4472 if (_new_scrollable_parent_viewport_geometry_get(child, start,
4473 &sx, &sy, &sw, &sh))
4475 Eina_List *l, *l_next;
4476 EINA_LIST_FOREACH_SAFE(children, l, l_next, child)
4479 elm_interface_atspi_component_extents_get(EINA_FALSE,
4481 if (w == 0 || h == 0 ||
4482 !ELM_RECTS_INTERSECT(x, y, w, h, sx, sy, sw, sh))
4483 children = eina_list_remove_list(children, l);
4490 static void *_get_next_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4491 void *obj, void *start, void *root, unsigned char forward)
4493 if (!obj) return NULL;
4494 void *parent = CALL(get_parent, obj);
4495 if (!parent) return NULL;
4497 Eina_List *children;
4498 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
4499 children = _valid_children_get(children, start, root);
4501 unsigned int children_count = eina_list_count(children);
4502 if (children_count == 0)
4504 eina_list_free(children);
4507 unsigned int current = 0;
4508 for(; current < children_count && eina_list_nth(children, current) != obj; ++current) ;
4509 if (current >= children_count)
4511 eina_list_free(children);
4514 forward ? ++current : --current;
4515 void *ret = _find_non_defunct_child(table, children, current, forward);
4516 eina_list_free(children);
4521 _directional_depth_first_search_try_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4522 unsigned char *all_children_visited_ptr,
4523 void *node, void *start, void *root,
4524 unsigned char forward)
4528 void *sibling = _get_next_non_defunct_sibling(table, node, start, root, forward);
4529 if (sibling != NULL)
4532 *all_children_visited_ptr = 0;
4537 node = CALL(get_parent, node);
4538 if (node == NULL || node == root) return NULL;
4540 // in backward traversing stop the walk up on parent
4541 if (!forward) break;
4548 unsigned int current_search_size;
4549 unsigned int counter;
4550 } cycle_detection_data;
4552 void cycle_detection_initialize(cycle_detection_data *data, const void *key)
4556 data->current_search_size = 1;
4560 unsigned char cycle_detection_check_if_in_cycle(cycle_detection_data *data, const void *key)
4562 if (!data) return 1;
4563 if (data->key == key) return 1;
4564 if (--data->counter == 0)
4566 data->current_search_size <<= 1;
4567 if (data->current_search_size == 0) return 1;
4568 data->counter = data->current_search_size;
4577 if (eo_isa(obj, ELM_ACCESS_CLASS))
4579 Elm_Access_Info *info;
4581 info = _elm_access_info_get(obj);
4582 if (info && eo_isa(info->part_object, ELM_LAYOUT_CLASS))
4584 Eina_List *attrs, *l;
4585 Elm_Atspi_Attribute *attr;
4587 eo_do(info->part_object,
4588 attrs = elm_interface_atspi_accessible_attributes_get());
4589 EINA_LIST_FOREACH(attrs, l, attr)
4591 if (!strcmp(attr->key, "___PlugID"))
4593 elm_atspi_attributes_list_free(attrs);
4597 elm_atspi_attributes_list_free(attrs);
4604 _proxy_in_parent_get(Eo *obj)
4608 Eina_List *children_list = NULL;
4609 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4612 EINA_LIST_FOREACH(children_list, l, child)
4614 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4620 eina_list_free(children_list);
4626 _deputy_of_proxy_in_parent_get(Eo *obj)
4630 Eina_List *children_list = NULL;
4631 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4633 unsigned int index = 0;
4635 EINA_LIST_FOREACH(children_list, l, child)
4637 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4641 WRN("Proxy does not have deputy object");
4645 deputy = eina_list_nth(children_list, index - 1);
4650 eina_list_free(children_list);
4655 static void *_calculate_neighbor_impl(accessibility_navigation_pointer_table *table, void *root, void *start, unsigned char forward, GetNeighborSearchMode search_mode)
4657 if (root && _object_is_defunct(table, root)) return NULL;
4658 if (start && _object_is_defunct(table, start))
4664 if (search_mode == NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE)
4666 /* This only works if we navigate backward, and it is not possible to
4667 find in embedded process. In this case the deputy should be used */
4668 return _deputy_of_proxy_in_parent_get(start);
4671 void *node = start ? start : root;
4672 if (!node) return NULL;
4674 // initialization of all-children-visited flag for start node - we assume
4675 // that when we begin at start node and we navigate backward, then all children
4676 // are visited, so navigation will ignore start's children and go to
4677 // previous sibling available.
4678 /* Regarding condtion (start != root):
4679 The last object can be found only if all_children_visited is false.
4680 The start is same with root, when looking for the last object. */
4681 unsigned char all_children_visited = (start != root) && (search_mode != NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT && !forward);
4683 // true, if starting element should be ignored. this is only used in rare case of
4684 // recursive search failing to find an object.
4685 // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
4686 // element A algorithm has to descend into BUS_B and search element B and its children. this is done
4687 // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
4688 // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
4689 // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
4690 // this flag means, that object A was already checked previously and we should skip it and its children.
4691 unsigned char force_next = (search_mode == NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING);
4693 cycle_detection_data cycle_detection;
4694 cycle_detection_initialize(&cycle_detection, node);
4697 if (_object_is_defunct(table, node)) return NULL;
4699 // always accept proxy object from different world
4700 if (!force_next && CALL(object_is_proxy, node)) return node;
4702 Eina_List *children;
4703 eo_do(node, children = elm_interface_atspi_accessible_children_get());
4704 children = _valid_children_get(children, start, root);
4707 // 1. not start node
4708 // 2. parent after all children in backward traversing
4709 // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
4710 // Objects with those roles shouldnt be reachable, when navigating next / prev.
4711 unsigned char all_children_visited_or_moving_forward = (eina_list_count(children) == 0 || forward || all_children_visited);
4712 if (!force_next && node != start && all_children_visited_or_moving_forward && _accept_object(table, node))
4714 if (start == NULL || _object_role_is_acceptable_when_navigating_next_prev(table, node))
4716 eina_list_free(children);
4721 void *next_related_in_direction = !force_next ? _get_object_in_relation_flow(table, node, forward) : NULL;
4723 /* force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
4724 in this case the node is elm_layout which is parent of proxy object.
4725 There is an access object working for the proxy object, and the access
4726 object could have relation information. This relation information should
4727 be checked first before using the elm_layout as a node. */
4728 if (force_next && forward)
4731 deputy = _deputy_of_proxy_in_parent_get(node);
4732 next_related_in_direction =
4733 _get_object_in_relation_flow(table, deputy, forward);
4736 if (next_related_in_direction && _object_is_defunct(table, next_related_in_direction))
4737 next_related_in_direction = NULL;
4738 unsigned char want_cycle_detection = 0;
4739 if (next_related_in_direction)
4741 /* Check next_related_in_direction is deputy object */
4745 /* If the prev object is deputy, then go to inside of its proxy first */
4746 if (_deputy_is(next_related_in_direction))
4748 parent = elm_widget_parent_get(next_related_in_direction);
4749 next_related_in_direction =
4750 _proxy_in_parent_get(parent);
4755 /* If current object is deputy, and it has relation next object,
4756 then do not use the relation next object, and use proxy first */
4757 if (_deputy_is(node))
4759 parent = elm_widget_parent_get(node);
4760 next_related_in_direction =
4761 _proxy_in_parent_get(parent);
4765 node = next_related_in_direction;
4766 want_cycle_detection = 1;
4769 void *child = !force_next && !all_children_visited ?
4770 _directional_depth_first_search_try_non_defunct_child(table, node, children, forward) : NULL;
4771 if (child != NULL) want_cycle_detection = 1;
4774 if (!force_next && node == root)
4776 eina_list_free(children);
4779 all_children_visited = 1;
4780 child = _directional_depth_first_search_try_non_defunct_sibling(table, &all_children_visited, node, start, root, forward);
4786 if (want_cycle_detection && cycle_detection_check_if_in_cycle(&cycle_detection, node))
4788 eina_list_free(children);
4791 eina_list_free(children);
4796 typedef struct accessibility_navigation_pointer_table_impl {
4797 accessibility_navigation_pointer_table ptrs;
4799 } accessibility_navigation_pointer_table_impl;
4801 static AtspiRole _object_get_role_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4803 Elm_Atspi_Role role;
4805 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
4806 return _elm_role_to_atspi_role(role);
4809 static uint64_t _object_get_state_set_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4811 Elm_Atspi_State_Set states;
4813 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
4814 return _elm_atspi_state_set_to_atspi_state_set(states);
4817 static void *_get_object_in_relation_by_type_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr, AtspiRelationType type)
4821 const Eo *source = ptr;
4822 Elm_Atspi_Relation_Set relations;
4823 Elm_Atspi_Relation_Type expected_relation_type = _atspi_relation_to_elm_relation(type);
4824 eo_do(source, relations = elm_interface_atspi_accessible_relation_set_get());
4825 Elm_Atspi_Relation *rel;
4827 EINA_LIST_FOREACH(relations, l, rel)
4829 if (rel->type == expected_relation_type)
4831 Eina_List *last = eina_list_last(rel->objects);
4832 return eina_list_data_get(last);
4839 static unsigned char _object_is_zero_size_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4843 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_TRUE, &x, &y, &w, &h));
4844 return w == 0 || h == 0;
4847 unsigned char _object_is_scrollable_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4850 return eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
4853 void *_get_parent_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4855 Eo *obj = (Eo*)ptr, *ret_obj;
4856 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
4860 void *_get_object_at_point_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr, int x, int y, unsigned char coordinates_are_screen_based)
4862 Eo *obj = (Eo*)ptr, *target;
4863 eo_do(obj, target = elm_interface_atspi_component_accessible_at_point_get(coordinates_are_screen_based, x, y));
4867 unsigned char _object_contains_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr, int x, int y, unsigned char coordinates_are_screen_based)
4870 Eina_Bool return_value;
4871 eo_do(obj, return_value = elm_interface_atspi_component_contains(coordinates_are_screen_based, x, y));
4872 return return_value ? 1 : 0;
4875 unsigned char _object_is_proxy_impl(struct accessibility_navigation_pointer_table *table_, void *obj)
4877 accessibility_navigation_pointer_table_impl *table = (accessibility_navigation_pointer_table_impl*)table_;
4878 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(table->bridge, pd, 0);
4879 const char *our_bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
4880 const char *obj_bus_name;
4881 _object_get_bus_name_and_path(table->bridge, (Eo*)obj, &obj_bus_name, NULL);
4882 return our_bus_name && obj_bus_name && strcmp(our_bus_name, obj_bus_name) != 0;
4885 accessibility_navigation_pointer_table_impl construct_accessibility_navigation_pointer_table(Eo *bridge)
4887 accessibility_navigation_pointer_table_impl table;
4888 #define INIT(n) table.ptrs.n = _## n ## _impl
4889 INIT(object_get_role);
4890 INIT(object_get_state_set);
4891 INIT(get_object_in_relation_by_type);
4892 INIT(object_is_zero_size);
4894 INIT(object_is_scrollable);
4895 INIT(get_object_at_point);
4896 INIT(object_contains);
4897 INIT(object_is_proxy);
4899 table.bridge = bridge;
4904 static Eo *_calculate_navigable_accessible_at_point(Eo *bridge, Eo *root, Eina_Bool coord_type, int x, int y)
4906 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4907 Eo *result = (Eo*)_calculate_navigable_accessible_at_point_impl(&table.ptrs, root, x, y, coord_type ? 1 : 0);
4911 static Eo *_calculate_neighbor(Eo *bridge, Eo *root, Eo *start, Eina_Bool forward, int search_mode)
4913 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4914 Eo *result = (Eo*)_calculate_neighbor_impl(&table.ptrs, root, start, forward ? 1 : 0, (GetNeighborSearchMode)search_mode);
4920 static Eldbus_Message *
4921 _component_get_extents(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4923 const char *obj_path = eldbus_message_path_get(msg);
4924 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4925 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4927 AtspiCoordType coord_type;
4928 Eldbus_Message *ret;
4929 Eldbus_Message_Iter *iter, *iter_struct;
4931 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4933 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4934 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4936 ret = eldbus_message_method_return_new(msg);
4937 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4939 iter = eldbus_message_iter_get(ret);
4941 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4942 eo_do(obj, elm_interface_atspi_component_extents_get(type, &x, &y, &w, &h));
4943 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
4944 EINA_SAFETY_ON_NULL_GOTO(iter_struct, fail);
4946 eldbus_message_iter_basic_append(iter_struct, 'i', x);
4947 eldbus_message_iter_basic_append(iter_struct, 'i', y);
4948 eldbus_message_iter_basic_append(iter_struct, 'i', w);
4949 eldbus_message_iter_basic_append(iter_struct, 'i', h);
4951 eldbus_message_iter_container_close(iter, iter_struct);
4955 if (ret) eldbus_message_unref(ret);
4959 static Eldbus_Message *
4960 _component_get_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4962 const char *obj_path = eldbus_message_path_get(msg);
4963 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4964 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4966 AtspiCoordType coord_type;
4967 Eldbus_Message *ret;
4969 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4971 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4972 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4974 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4975 eo_do(obj, elm_interface_atspi_component_position_get(type, &x, &y));
4977 ret = eldbus_message_method_return_new(msg);
4978 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4980 eldbus_message_arguments_append(ret, "i", x);
4981 eldbus_message_arguments_append(ret, "i", y);
4986 static Eldbus_Message *
4987 _component_get_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4989 const char *obj_path = eldbus_message_path_get(msg);
4990 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4991 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4993 Eldbus_Message *ret;
4995 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4997 eo_do(obj, elm_interface_atspi_component_size_get(&x, &y));
4999 ret = eldbus_message_method_return_new(msg);
5000 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5002 eldbus_message_arguments_append(ret, "i", x);
5003 eldbus_message_arguments_append(ret, "i", y);
5008 static AtspiComponentLayer
5009 _elm_layer_2_atspi_layer(int layer)
5011 if (layer <= ELM_OBJECT_LAYER_BACKGROUND) return ATSPI_LAYER_CANVAS;
5012 if (layer < ELM_OBJECT_LAYER_FOCUS) return ATSPI_LAYER_WIDGET;
5013 if (layer <= ELM_OBJECT_LAYER_TOOLTIP) return ATSPI_LAYER_POPUP;
5015 return ATSPI_LAYER_OVERLAY;
5018 static Eldbus_Message *
5019 _component_get_layer(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5021 const char *obj_path = eldbus_message_path_get(msg);
5022 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5023 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5025 Eldbus_Message *ret;
5026 AtspiComponentLayer atspi_layer;
5028 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5030 eo_do(obj, layer = elm_interface_atspi_component_layer_get());
5032 ret = eldbus_message_method_return_new(msg);
5033 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5035 atspi_layer = _elm_layer_2_atspi_layer(layer);
5036 eldbus_message_arguments_append(ret, "u", atspi_layer);
5041 static Eldbus_Message *
5042 _component_grab_focus(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5044 const char *obj_path = eldbus_message_path_get(msg);
5045 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5046 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5047 Eldbus_Message *ret;
5048 Eina_Bool focus = EINA_FALSE;
5051 return _dbus_invalid_ref_error_new(msg);
5053 eo_do(obj, focus = elm_interface_atspi_component_focus_grab());
5055 ret = eldbus_message_method_return_new(msg);
5056 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5058 eldbus_message_arguments_append(ret, "b", focus);
5063 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5064 static Eldbus_Message *
5065 _component_grab_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5067 const char *obj_path = eldbus_message_path_get(msg);
5068 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5069 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5070 Eldbus_Message *ret;
5071 Eina_Bool highlight = EINA_FALSE;
5073 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5075 eo_do(obj, highlight = elm_interface_atspi_component_highlight_grab());
5077 ret = eldbus_message_method_return_new(msg);
5078 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5080 eldbus_message_arguments_append(ret, "b", highlight);
5085 static Eldbus_Message *
5086 _component_clear_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5088 const char *obj_path = eldbus_message_path_get(msg);
5089 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5090 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5091 Eldbus_Message *ret;
5092 Eina_Bool highlight = EINA_FALSE;
5094 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5096 eo_do(obj, highlight = elm_interface_atspi_component_highlight_clear());
5098 ret = eldbus_message_method_return_new(msg);
5099 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5101 eldbus_message_arguments_append(ret, "b", highlight);
5107 static Eldbus_Message *
5108 _component_get_alpha(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5110 const char *obj_path = eldbus_message_path_get(msg);
5111 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5112 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5113 Eldbus_Message *ret;
5117 return _dbus_invalid_ref_error_new(msg);
5119 eo_do(obj, alpha = elm_interface_atspi_component_alpha_get());
5121 ret = eldbus_message_method_return_new(msg);
5122 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5124 eldbus_message_arguments_append(ret, "d", alpha);
5129 static Eldbus_Message *
5130 _component_set_extends(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5132 const char *obj_path = eldbus_message_path_get(msg);
5133 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5134 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5136 AtspiCoordType coord_type;
5137 Eldbus_Message *ret;
5138 Eina_Bool result = EINA_FALSE;
5140 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5142 if (!eldbus_message_arguments_get(msg, "iiiiu", &x, &y, &w, &h, &coord_type))
5143 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5145 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5146 eo_do(obj, result = elm_interface_atspi_component_extents_set(type, x, y, w, h));
5148 ret = eldbus_message_method_return_new(msg);
5149 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5151 eldbus_message_arguments_append(ret, "b", result);
5156 static Eldbus_Message *
5157 _component_set_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5159 const char *obj_path = eldbus_message_path_get(msg);
5160 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5161 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5163 Eina_Bool result = EINA_FALSE;
5164 AtspiCoordType coord_type;
5165 Eldbus_Message *ret;
5167 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5169 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
5170 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5172 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5173 eo_do(obj, result = elm_interface_atspi_component_position_set(type, x, y));
5175 ret = eldbus_message_method_return_new(msg);
5176 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5178 eldbus_message_arguments_append(ret, "b", result);
5183 static Eldbus_Message *
5184 _component_set_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5186 const char *obj_path = eldbus_message_path_get(msg);
5187 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5188 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5191 Eldbus_Message *ret;
5193 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5195 if (!eldbus_message_arguments_get(msg, "ii", &w, &h))
5196 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5198 eo_do(obj, result = elm_interface_atspi_component_size_set(w, h));
5200 ret = eldbus_message_method_return_new(msg);
5201 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5203 eldbus_message_arguments_append(ret, "b", result);
5208 static const Eldbus_Method component_methods[] = {
5209 { "Contains", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "contains"}), _component_contains, 0 },
5210 { "GetAccessibleAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)", "accessible"}), _component_get_accessible_at_point, 0 },
5211 { "GetExtents", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"(iiii)", "extents"}), _component_get_extents, 0 },
5212 { "GetPosition", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"i", "x"}, {"i","y"}), _component_get_position, 0 },
5213 { "GetSize", NULL, ELDBUS_ARGS({"i", "w"}, {"i", "h"}), _component_get_size, 0 },
5214 { "GetLayer", NULL, ELDBUS_ARGS({"u", "layer"}), _component_get_layer, 0 },
5215 // { "GetMDIZOrder", NULL, ELDBUS_ARGS({"n", "MDIZOrder"}), _component_get_mdizorder, 0 },
5216 { "GrabFocus", NULL, ELDBUS_ARGS({"b", "focus"}), _component_grab_focus, 0 },
5217 { "GetAlpha", NULL, ELDBUS_ARGS({"d", "alpha"}), _component_get_alpha, 0 },
5218 { "SetExtents", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "width"}, {"i", "height"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_extends, 0 },
5219 { "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
5220 { "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
5222 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5223 { "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
5224 { "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
5226 { NULL, NULL, NULL, NULL, 0 }
5229 static const Eldbus_Service_Interface_Desc component_iface_desc = {
5230 ATSPI_DBUS_INTERFACE_COMPONENT, component_methods, NULL, NULL, NULL, NULL
5234 _on_elm_atspi_bridge_app_register(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
5236 const char *errname, *errmsg;
5238 if (eldbus_message_error_get(msg, &errname, &errmsg))
5240 ERR("%s %s", errname, errmsg);
5243 DBG("Application successfuly registered at ATSPI2 bus.");
5247 _elm_atspi_bridge_app_register(Eo *bridge)
5249 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5251 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5252 ATSPI_DBUS_PATH_ROOT,
5253 ATSPI_DBUS_INTERFACE_SOCKET,
5255 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5257 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
5258 eldbus_connection_send(pd->a11y_bus, message, _on_elm_atspi_bridge_app_register, NULL, -1);
5264 _elm_atspi_bridge_app_unregister(Eo *bridge)
5267 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5269 root = elm_atspi_bridge_root_get(bridge);
5271 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5272 ATSPI_DBUS_PATH_ROOT,
5273 ATSPI_DBUS_INTERFACE_SOCKET,
5275 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5277 _bridge_iter_object_reference_append(bridge, iter, root);
5278 eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1);
5284 _cache_register(Eo *obj)
5286 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
5287 pd->cache_interface = eldbus_service_interface_register(pd->a11y_bus, CACHE_INTERFACE_PATH, &cache_iface_desc);
5288 eldbus_service_object_data_set(pd->cache_interface, ELM_ATSPI_BRIDGE_CLASS_NAME, obj);
5292 _set_broadcast_flag(const char *event, Eo *bridge)
5295 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5297 tokens = eina_str_split(event, ":", 3);
5299 if (!tokens) return;
5301 if (!strcmp(tokens[0], "Object"))
5303 if (!tokens[1] || *tokens[1] == '\0') return; // do not handle "Object:*"
5304 else if (!strcmp(tokens[1], "StateChanged"))
5306 if (!tokens[2] || *tokens[2] == '\0')
5307 pd->object_state_broadcast_mask = -1; // broadcast all
5308 eina_str_tolower(&tokens[2]);
5309 struct atspi_state_desc *sd = eina_hash_find(pd->state_hash, tokens[2]);
5311 STATE_TYPE_SET(pd->object_state_broadcast_mask, sd->elm_state);
5313 else if (!strcmp(tokens[1], "PropertyChange"))
5315 if (!tokens[2] || *tokens[2] == '\0')
5316 pd->object_property_broadcast_mask = -1; //broadcast all
5317 else if (!strcmp(tokens[2], "AccessibleValue"))
5318 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_VALUE);
5319 else if (!strcmp(tokens[2], "AccessibleName"))
5320 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_NAME);
5321 else if (!strcmp(tokens[2], "AccessibleDescription"))
5322 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_DESCRIPTION);
5323 else if (!strcmp(tokens[2], "AccessibleParent"))
5324 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_PARENT);
5325 else if (!strcmp(tokens[2], "AccessibleRole"))
5326 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_ROLE);
5328 else if (!strcmp(tokens[1], "ChildrenChanged"))
5330 if (!tokens[2] || *tokens[2] == '\0')
5331 pd->object_children_broadcast_mask = -1; // broadcast all
5332 else if (!strcmp(tokens[2], "add"))
5333 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_ADDED);
5334 else if (!strcmp(tokens[2], "remove"))
5335 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_REMOVED);
5337 else if (!strcmp(tokens[1], "TextChanged"))
5338 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED);
5339 else if (!strcmp(tokens[1], "TextCaretMoved"))
5340 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED);
5341 else if (!strcmp(tokens[1], "TextBoundsChanged"))
5342 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED);
5343 else if (!strcmp(tokens[1], "TextSelectionChanged"))
5344 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED);
5345 else if (!strcmp(tokens[1], "TextAttributesChanged"))
5346 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED);
5347 else if (!strcmp(tokens[1], "VisibleDataChanged"))
5348 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED);
5349 else if (!strcmp(tokens[1], "ActiveDescendantChanged"))
5350 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED);
5351 else if (!strcmp(tokens[1], "BoundsChanged"))
5352 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_BOUNDS_CHANGED);
5353 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5354 else if (!strcmp(tokens[1], "MoveOuted"))
5355 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED);
5358 else if (!strcmp(tokens[0], "Window"))
5360 if (!tokens[1] || *tokens[1] == '\0')
5361 pd->window_signal_broadcast_mask = -1; // broadcast all
5362 else if (!strcmp(tokens[1], "Create"))
5363 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_CREATE);
5364 else if (!strcmp(tokens[1], "Destroy"))
5365 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DESTROY);
5366 else if (!strcmp(tokens[1], "Activate"))
5367 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_ACTIVATE);
5368 else if (!strcmp(tokens[1], "Deactivate"))
5369 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DEACTIVATE);
5370 else if (!strcmp(tokens[1], "Maximize"))
5371 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MAXIMIZE);
5372 else if (!strcmp(tokens[1], "Minimize"))
5373 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MINIMIZE);
5374 else if (!strcmp(tokens[1], "Resize"))
5375 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESIZE);
5376 else if (!strcmp(tokens[1], "Restore"))
5377 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESTORE);
5385 _registered_listeners_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
5387 const char *event, *bus;
5389 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
5390 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
5392 DBG("Updating registered ATSPI signals list.");
5393 pd->object_broadcast_mask = 0;
5394 pd->object_children_broadcast_mask = 0;
5395 pd->object_property_broadcast_mask = 0;
5396 pd->object_state_broadcast_mask = 0;
5397 pd->window_signal_broadcast_mask = 0;
5399 if (eldbus_message_error_get(msg, &event, &bus))
5401 WRN("%s %s", event, bus);
5404 Eldbus_Message_Iter *iter, *siter;
5405 if (!eldbus_message_arguments_get(msg, "a(ss)", &iter))
5407 ERR("Invalid answer type from GetRegisteredEvents method call!");
5410 while (eldbus_message_iter_get_and_next(iter, 'r', &siter))
5412 if (!eldbus_message_iter_arguments_get(siter, "ss", &bus, &event))
5414 ERR("Unable to get message arguments");
5417 _set_broadcast_flag(event, data);
5422 //TIZEN_ONLY(20170910) atspi: emit signal after atspi bridge is connected
5423 pd->connected = EINA_TRUE;
5424 eo_do(data, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_CONNECTED, NULL));
5425 _elm_win_atspi(EINA_TRUE);
5429 eo_do(data, root = elm_obj_atspi_bridge_root_get());
5430 _bridge_cache_build(data, root);
5432 // initialize pending proxy
5433 EINA_LIST_FREE(pd->socket_queue, pr)
5434 _socket_ifc_create(pd->a11y_bus, pr);
5435 EINA_LIST_FREE(pd->plug_queue, pr)
5436 _plug_connect(pd->a11y_bus, pr);
5438 pd->socket_queue = pd->plug_queue = NULL;
5443 _registered_events_list_update(Eo *bridge)
5445 Eldbus_Message *msg;
5446 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5449 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "GetRegisteredEvents");
5450 p = eldbus_connection_send(pd->a11y_bus, msg, _registered_listeners_get, bridge, -1);
5451 pd->pending_requests = eina_list_append(pd->pending_requests, p);
5455 _handle_listener_change(void *data, const Eldbus_Message *msg EINA_UNUSED)
5457 _registered_events_list_update(data);
5460 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5462 _scroll_gesture_required_is(Eo *obj)
5464 Eina_Bool ret = EINA_FALSE;
5465 Eina_List *l, *attr_list = NULL;
5466 Elm_Atspi_Attribute *attr = NULL;
5468 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5469 EINA_LIST_FOREACH(attr_list, l, attr)
5471 if (!strcmp(attr->key, "gesture_required") && !strcmp(attr->value, "scroll"))
5478 elm_atspi_attributes_list_free(attr_list);
5485 _state_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5487 Elm_Atspi_Event_State_Changed_Data *state_data = event_info;
5488 const char *type_desc;
5489 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5491 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
5492 if ((state_data->type == ELM_ATSPI_STATE_ACTIVE) && eo_isa(obj, ELM_WIN_CLASS))
5494 pd->window_activated = state_data->new_value;
5497 // TIZEN_ONLY(20161209): reduce IPC of object:state-changed:showing
5498 if ((state_data->type == ELM_ATSPI_STATE_SHOWING) ||
5499 (state_data->type == ELM_ATSPI_STATE_VISIBLE))
5501 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5502 Elm_Atspi_State_Set ss;
5504 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5505 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
5506 if (state_data->new_value) /* Showing */
5508 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5509 (role != ELM_ATSPI_ROLE_PAGE_TAB) &&
5510 (role != ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW) &&
5511 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)))
5514 else /* Not Showing */
5516 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5517 (role != ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW) &&
5518 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)) &&
5519 (_elm_object_accessibility_currently_highlighted_get() != (void *)obj))
5525 if (!STATE_TYPE_GET(pd->object_state_broadcast_mask, state_data->type))
5528 if ((state_data->type > ELM_ATSPI_STATE_LAST_DEFINED) ||
5529 (int)state_data->type < 0)
5532 type_desc = elm_states_to_atspi_state[state_data->type].name;
5534 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5535 unsigned int det2 = 0;
5536 if ((state_data->type == ELM_ATSPI_STATE_HIGHLIGHTED) &&
5537 (_scroll_gesture_required_is(obj)))
5540 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5541 &_event_obj_signals[ATSPI_OBJECT_EVENT_STATE_CHANGED], type_desc, state_data->new_value, det2, NULL);
5547 _bounds_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5549 Elm_Atspi_Event_Geometry_Changed_Data *geo_data = event_info;
5551 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5552 &_event_obj_signals[ATSPI_OBJECT_EVENT_BOUNDS_CHANGED], "", 0, 0, "(iiii)",
5553 geo_data->x, geo_data->y, geo_data->width, geo_data->height);
5558 _property_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5560 const char *property = event_info;
5562 enum _Atspi_Object_Property prop = ATSPI_OBJECT_PROPERTY_LAST;
5564 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5566 if (!strcmp(property, "parent"))
5568 prop = ATSPI_OBJECT_PROPERTY_PARENT;
5569 atspi_desc = "accessible-parent";
5571 else if (!strcmp(property, "name"))
5573 prop = ATSPI_OBJECT_PROPERTY_NAME;
5574 atspi_desc = "accessible-name";
5576 else if (!strcmp(property, "description"))
5578 prop = ATSPI_OBJECT_PROPERTY_DESCRIPTION;
5579 atspi_desc = "accessible-description";
5581 else if (!strcmp(property, "role"))
5583 prop = ATSPI_OBJECT_PROPERTY_ROLE;
5584 atspi_desc = "accessible-role";
5586 else if (!strcmp(property, "value"))
5588 prop = ATSPI_OBJECT_PROPERTY_VALUE;
5589 atspi_desc = "accessible-value";
5591 if (prop == ATSPI_OBJECT_PROPERTY_LAST)
5593 ERR("Unrecognized property name!");
5596 if (!STATE_TYPE_GET(pd->object_property_broadcast_mask, prop))
5598 DBG("Masking property %s changed event.", property);
5602 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5603 &_event_obj_signals[ATSPI_OBJECT_EVENT_PROPERTY_CHANGED], atspi_desc, 0, 0, NULL, NULL);
5608 _visible_data_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5610 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5612 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED))
5615 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5616 &_event_obj_signals[ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED], "",
5623 _active_descendant_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5625 Eo *child = event_info;
5628 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5630 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED))
5633 eo_do(child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5635 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5636 &_event_obj_signals[ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED], "",
5637 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), child);
5642 _children_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5644 const char *atspi_desc = NULL;
5645 Elm_Atspi_Event_Children_Changed_Data *ev_data = event_info;
5647 enum _Atspi_Object_Child_Event_Type type;
5649 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5651 type = ev_data->is_added ? ATSPI_OBJECT_CHILD_ADDED : ATSPI_OBJECT_CHILD_REMOVED;
5653 // update cached objects
5654 if (ev_data->is_added)
5655 _bridge_cache_build(data, ev_data->child);
5657 if (!STATE_TYPE_GET(pd->object_children_broadcast_mask, type))
5662 case ATSPI_OBJECT_CHILD_ADDED:
5664 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5666 case ATSPI_OBJECT_CHILD_REMOVED:
5667 atspi_desc = "remove";
5668 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5672 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5673 &_event_obj_signals[ATSPI_OBJECT_EVENT_CHILDREN_CHANGED], atspi_desc,
5674 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), ev_data->child);
5679 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5681 _move_outed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5683 const Elm_Atspi_Move_Outed_Type *type = event_info;
5685 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5687 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED))
5689 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5690 &_event_obj_signals[ATSPI_OBJECT_EVENT_MOVE_OUTED], "", *type, 0, NULL, NULL);
5695 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
5697 _window_activated_detail_value_add(Eo *obj)
5699 unsigned int ret = ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED;
5700 Eina_List *l, *attr_list = NULL;
5701 Elm_Atspi_Attribute *attr = NULL;
5703 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5704 EINA_LIST_FOREACH(attr_list, l, attr)
5706 if (!strcmp(attr->key, "default_label") && !strcmp(attr->value, "disabled"))
5708 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_DISABLED;
5713 elm_atspi_attributes_list_free(attr_list);
5715 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5716 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5717 if (role == ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW)
5718 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_KEYBOARD;
5724 _window_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info EINA_UNUSED)
5726 enum _Atspi_Window_Signals type;
5728 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5730 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED)
5731 type = ATSPI_WINDOW_EVENT_CREATE;
5732 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED)
5733 type = ATSPI_WINDOW_EVENT_DESTROY;
5734 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DEACTIVATED)
5735 type = ATSPI_WINDOW_EVENT_DEACTIVATE;
5736 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5737 type = ATSPI_WINDOW_EVENT_ACTIVATE;
5738 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MAXIMIZED)
5739 type = ATSPI_WINDOW_EVENT_MAXIMIZE;
5740 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MINIMIZED)
5741 type = ATSPI_WINDOW_EVENT_MINIMIZE;
5742 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_RESTORED)
5743 type = ATSPI_WINDOW_EVENT_RESTORE;
5747 if (!STATE_TYPE_GET(pd->window_signal_broadcast_mask, type))
5752 ERR("A11Y connection closed. Unable to send ATSPI event.");
5756 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
5757 unsigned int det1 = 0;
5758 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5759 det1 = _window_activated_detail_value_add(obj);
5762 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_WINDOW,
5763 &_window_obj_signals[type], "", det1, 0, "i", 0);
5768 _selection_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5770 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5772 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_SELECTION_CHANGED))
5775 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5776 &_event_obj_signals[ATSPI_OBJECT_EVENT_SELECTION_CHANGED], "", 0, 0, "i", 0);
5780 static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *infc, const Eldbus_Signal *signal, const char *minor, unsigned int det1, unsigned int det2, const char *variant_sig, ...)
5782 Eldbus_Message *msg;
5783 Eldbus_Message_Iter *iter , *iter_stack[64], *iter_struct;
5789 EINA_SAFETY_ON_NULL_RETURN(infc);
5790 EINA_SAFETY_ON_NULL_RETURN(signal);
5791 EINA_SAFETY_ON_NULL_RETURN(minor);
5792 EINA_SAFETY_ON_NULL_RETURN(obj);
5793 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5795 path = _bridge_path_from_object(bridge, obj);
5797 msg = eldbus_message_signal_new(path, infc, signal->name);
5800 va_start(va, variant_sig);
5802 iter = eldbus_message_iter_get(msg);
5803 eldbus_message_iter_arguments_append(iter, "sii", minor, det1, det2);
5807 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', variant_sig);
5809 const char *tmp = variant_sig;
5815 iter_stack[top + 1] = eldbus_message_iter_container_new(iter_stack[top], 'r', NULL);
5819 eldbus_message_iter_basic_append(iter_stack[top], 's', va_arg(va, char*));
5822 eldbus_message_iter_basic_append(iter_stack[top], 'i', va_arg(va, int));
5825 atspi_obj = va_arg(va, Eo*);
5826 path = _bridge_path_from_object(bridge, atspi_obj);
5827 eldbus_message_iter_basic_append(iter_stack[top], 'o', path);
5830 eldbus_message_iter_container_close(iter_stack[top - 1], iter_stack[top]);
5834 ERR("Not supported d-bus type: %c.", *tmp);
5840 else // AT-SPI implementation forces checks on variant in signature even if not used.
5842 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', "i");
5843 eldbus_message_iter_basic_append(iter_stack[top], 'i', 0);
5848 ERR("Invalid d-bus signature: () do not match.");
5850 eldbus_message_iter_container_close(iter, iter_stack[0]);
5852 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
5853 path = _bridge_path_from_object(bridge, elm_atspi_bridge_root_get(bridge));
5854 eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
5855 eldbus_message_iter_basic_append(iter_struct, 'o', path);
5856 eldbus_message_iter_container_close(iter, iter_struct);
5858 eldbus_connection_send(pd->a11y_bus, msg, NULL, NULL, -1);
5859 DBG("Send %s.%s[%s,%d,%d]", infc, signal->name, minor, det1, det2);
5863 _text_caret_moved_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5867 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5869 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED))
5872 eo_do(obj, cursor_pos = elm_interface_atspi_text_caret_offset_get());
5874 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5875 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED], "", cursor_pos, 0, NULL, NULL);
5881 _text_text_inserted_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5883 Elm_Atspi_Text_Change_Info *info = event_info;
5885 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5887 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5892 WRN("Try to send signal with NULL value");
5896 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5897 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "insert", info->pos, info->len, "s", info->content);
5903 _text_text_removed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5905 Elm_Atspi_Text_Change_Info *info = event_info;
5907 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5909 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5914 WRN("Try to send signal with NULL value");
5918 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5919 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "delete", info->pos, info->len, "s", info->content);
5925 _text_selection_changed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5927 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5929 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED))
5932 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5933 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED], "", 0, 0, NULL, NULL);
5938 //TIZEN_ONLY(20160527) - Add direct reading feature
5940 _on_reading_state_changed(void *data EINA_UNUSED, const Eldbus_Message *msg)
5943 const char *say_signal_name = "";
5944 Elm_Atspi_Say_Info *say_info;
5946 if (eldbus_message_arguments_get(msg, "is", &i, &say_signal_name))
5947 { if (read_command_id)
5949 say_info = eina_hash_find(read_command_id, &i);
5952 if (say_info->func && say_signal_name)
5953 say_info->func(say_info->data, say_signal_name);
5954 eina_hash_del(read_command_id, &i, NULL);
5963 _event_handlers_register(Eo *bridge)
5965 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5967 _registered_events_list_update(bridge);
5969 // register signal handlers in order to update list of registered listeners of ATSPI-Clients
5970 pd->register_hdl = eldbus_signal_handler_add(pd->a11y_bus, ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "EventListenerRegistered", _handle_listener_change, bridge);
5971 pd->unregister_hdl = eldbus_signal_handler_add(pd->a11y_bus, ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "EventListenerDeregistered", _handle_listener_change, bridge);
5972 //TIZEN_ONLY(20160527) - Add direct reading feature
5973 pd->reading_state_changed_hdl = eldbus_signal_handler_add(pd->a11y_bus, ELM_ATSPI_DIRECT_READ_BUS, ELM_ATSPI_DIRECT_READ_PATH, ELM_ATSPI_DIRECT_READ_INTERFACE, "ReadingStateChanged", _on_reading_state_changed, bridge);
5975 pd->key_flr = ecore_event_filter_add(NULL, _elm_atspi_bridge_key_filter, NULL, bridge);
5979 _bridge_object_unregister(Eo *bridge, Eo *obj)
5981 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5983 eina_hash_del(pd->cache, &obj, obj);
5987 _on_object_add(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
5989 Eldbus_Message *sig;
5990 Eldbus_Message_Iter *iter;
5992 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5994 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_ADDED);
5995 iter = eldbus_message_iter_get(sig);
5996 _cache_item_reference_append_cb(data, obj, iter);
5998 eldbus_service_signal_send(pd->cache_interface, sig);
6004 _on_object_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6006 Eldbus_Message *sig;
6008 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6010 _bridge_object_unregister(data, obj);
6012 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_REMOVED);
6013 Eldbus_Message_Iter *iter = eldbus_message_iter_get(sig);
6014 _bridge_iter_object_reference_append(data, iter, obj);
6015 eldbus_service_signal_send(pd->cache_interface, sig);
6021 _bridge_cache_build(Eo *bridge, void *obj)
6023 Eina_List *children;
6024 Elm_Atspi_State_Set ss;
6027 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6029 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6032 if (!eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
6033 _bridge_object_register(bridge, obj);
6035 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
6036 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
6038 if (eo_isa(obj, ELM_INTERFACE_ATSPI_WINDOW_INTERFACE))
6040 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_ACTIVE))
6042 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6043 pd->window_activated = EINA_TRUE;
6048 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6049 pd->window_activated = EINA_FALSE;
6053 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
6054 EINA_LIST_FREE(children, child)
6055 _bridge_cache_build(bridge, child);
6059 _interfaces_unregister(Eo *bridge)
6061 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6063 #define INTERFACE_SAFE_FREE(ifc) \
6065 eldbus_service_interface_unregister(ifc); \
6068 INTERFACE_SAFE_FREE(pd->interfaces.accessible);
6069 INTERFACE_SAFE_FREE(pd->interfaces.application);
6070 INTERFACE_SAFE_FREE(pd->interfaces.action);
6071 INTERFACE_SAFE_FREE(pd->interfaces.component);
6072 INTERFACE_SAFE_FREE(pd->interfaces.collection);
6073 INTERFACE_SAFE_FREE(pd->interfaces.editable_text);
6074 INTERFACE_SAFE_FREE(pd->interfaces.image);
6075 INTERFACE_SAFE_FREE(pd->interfaces.selection);
6076 INTERFACE_SAFE_FREE(pd->interfaces.text);
6077 INTERFACE_SAFE_FREE(pd->interfaces.value);
6081 _a11y_connection_shutdown(Eo *bridge)
6083 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6084 Eldbus_Pending *pending;
6087 _elm_atspi_bridge_app_unregister(bridge);
6090 eina_hash_free(pd->cache);
6093 if (pd->cache_interface)
6094 eldbus_service_object_unregister(pd->cache_interface);
6095 pd->cache_interface = NULL;
6097 _interfaces_unregister(bridge);
6099 if (pd->key_flr) ecore_event_filter_del(pd->key_flr);
6102 if (pd->register_hdl) eldbus_signal_handler_del(pd->register_hdl);
6103 pd->register_hdl = NULL;
6105 if (pd->unregister_hdl) eldbus_signal_handler_del(pd->unregister_hdl);
6106 pd->unregister_hdl = NULL;
6108 //TIZEN_ONLY(20160527) - Add direct reading feature
6109 if (pd->reading_state_changed_hdl) eldbus_signal_handler_del(pd->reading_state_changed_hdl);
6110 pd->reading_state_changed_hdl = NULL;
6113 EINA_LIST_FREE(pd->pending_requests, pending)
6114 eldbus_pending_cancel(pending);
6115 pd->pending_requests = NULL;
6117 if (pd->a11y_bus) eldbus_connection_unref(pd->a11y_bus);
6118 pd->a11y_bus = NULL;
6120 if (pd->state_hash) eina_hash_free(pd->state_hash);
6121 pd->state_hash = NULL;
6123 if (pd->event_hash) eina_hash_free(pd->event_hash);
6124 pd->event_hash = NULL;
6126 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, elm_interface_atspi_accessible_event_handler_del(pd->event_hdlr));
6127 pd->event_hdlr = NULL;
6129 eo_do(bridge, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, NULL));
6130 pd->connected = EINA_FALSE;
6133 static void _disconnect_cb(void *data, Eldbus_Connection *conn EINA_UNUSED, void *event_info EINA_UNUSED)
6135 _a11y_connection_shutdown(data);
6139 _interfaces_register(Eo *bridge)
6141 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6143 pd->interfaces.accessible =
6144 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &accessible_iface_desc);
6145 eldbus_service_object_data_set(pd->interfaces.accessible, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6147 pd->interfaces.application =
6148 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &application_iface_desc);
6149 eldbus_service_object_data_set(pd->interfaces.application, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6151 pd->interfaces.action =
6152 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &action_iface_desc);
6153 eldbus_service_object_data_set(pd->interfaces.action, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6155 pd->interfaces.component =
6156 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &component_iface_desc);
6157 eldbus_service_object_data_set(pd->interfaces.component, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6159 pd->interfaces.collection =
6160 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &collection_iface_desc);
6161 eldbus_service_object_data_set(pd->interfaces.collection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6163 pd->interfaces.editable_text =
6164 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &editable_text_iface_desc);
6165 eldbus_service_object_data_set(pd->interfaces.editable_text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6167 pd->interfaces.image =
6168 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &image_iface_desc);
6169 eldbus_service_object_data_set(pd->interfaces.image, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6171 pd->interfaces.selection =
6172 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &selection_iface_desc);
6173 eldbus_service_object_data_set(pd->interfaces.selection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6175 pd->interfaces.text =
6176 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &text_iface_desc);
6177 eldbus_service_object_data_set(pd->interfaces.text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6179 pd->interfaces.value =
6180 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &value_iface_desc);
6181 eldbus_service_object_data_set(pd->interfaces.value, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6185 _bridge_accessible_event_dispatch(void *data, Eo *accessible, const Eo_Event_Description *desc, void *event_info)
6187 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6189 _bridge_object_register(data, accessible);
6191 Eo_Event_Cb cb = eina_hash_find(pd->event_hash, &desc);
6192 return cb ? cb(data, accessible, desc, event_info) : EINA_TRUE;
6196 _a11y_bus_initialize(Eo *obj, const char *socket_addr)
6198 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
6199 pd->a11y_bus = eldbus_private_address_connection_get(socket_addr);
6203 eldbus_connection_event_callback_add(pd->a11y_bus, ELDBUS_CONNECTION_EVENT_DISCONNECTED, _disconnect_cb, obj);
6205 // init data structures
6206 pd->cache = eina_hash_pointer_new(NULL);
6207 pd->state_hash = _elm_atspi_state_hash_build();
6208 pd->event_hash = _elm_atspi_event_hash_build();
6211 _cache_register(obj);
6212 _interfaces_register(obj);
6213 _event_handlers_register(obj);
6214 if (!getenv("ELM_ATSPI_NO_EMBED"))
6215 _elm_atspi_bridge_app_register(obj);
6217 // register accesible object event listener
6218 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, pd->event_hdlr = elm_interface_atspi_accessible_event_handler_add(_bridge_accessible_event_dispatch, obj));
6223 _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6225 const char *errname, *errmsg, *sock_addr = NULL;
6226 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6228 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6230 if (eldbus_message_error_get(msg, &errname, &errmsg))
6232 ERR("%s %s", errname, errmsg);
6236 if (!eldbus_message_arguments_get(msg, "s", &sock_addr) || !sock_addr)
6238 ERR("Could not get A11Y Bus socket address.");
6242 _a11y_socket_address = eina_stringshare_add(sock_addr);
6243 _a11y_bus_initialize((Eo*)data, sock_addr);
6246 static void _a11y_connection_init(Eo *bridge)
6248 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6249 Eina_Bool is_connected;
6251 eo_do(bridge, is_connected = elm_obj_atspi_bridge_connected_get());
6253 if (is_connected) return;
6255 // TIZEN_ONLY(20170512): send window activated event to at_spi2 only once per session
6256 pd->window_activated_broadcast_needed = EINA_TRUE;
6258 Eldbus_Message *m = eldbus_object_method_call_new(pd->bus_obj, A11Y_DBUS_INTERFACE, "GetAddress");
6259 Eldbus_Pending *p = eldbus_object_send(pd->bus_obj, m, _a11y_bus_address_get, bridge, 100);
6262 pd->pending_requests = eina_list_append(pd->pending_requests, p);
6266 _screen_reader_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6268 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6269 const char *errname, *errmsg;
6270 Eina_Bool is_enabled;
6271 Eldbus_Message_Iter *variant;
6273 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6275 if (eldbus_message_error_get(msg, &errname, &errmsg))
6277 WRN("%s %s", errname, errmsg);
6280 if (!eldbus_message_arguments_get(msg, "v", &variant))
6282 ERR("'ScreenReaderEnabled' not packed into variant.");
6285 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6287 ERR("Could not get 'ScreenReaderEnabled' boolean property");
6290 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6291 pd->screen_reader_enabled = !!is_enabled;
6293 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6294 //register/unregister access objects accordingly.
6295 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6296 _elm_win_screen_reader(is_enabled);
6301 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6303 _at_spi_client_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6305 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6306 const char *errname, *errmsg;
6307 Eina_Bool is_enabled;
6308 Eldbus_Message_Iter *variant;
6310 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6312 if (eldbus_message_error_get(msg, &errname, &errmsg))
6314 WRN("%s %s", errname, errmsg);
6317 if (!eldbus_message_arguments_get(msg, "v", &variant))
6319 ERR("'" A11Y_DBUS_ENABLED_PROPERTY "' not packed into variant.");
6322 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6324 ERR("Could not get '" A11Y_DBUS_ENABLED_PROPERTY "' boolean property");
6328 _a11y_connection_init(data);
6331 _elm_win_atspi(EINA_FALSE);
6332 DBG("AT-SPI2 stack not enabled.");
6338 static void _bridge_object_register(Eo *bridge, Eo *obj)
6340 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6342 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6344 WRN("Unable to register class w/o Elm_Interface_Atspi_Accessible!");
6348 if (eina_hash_find(pd->cache, &obj))
6351 eina_hash_add(pd->cache, &obj, obj);
6355 _elm_atspi_bridge_init(void)
6359 _instance = eo_add(ELM_ATSPI_BRIDGE_CLASS, NULL);
6365 _elm_atspi_bridge_get(void)
6371 _elm_atspi_bridge_shutdown(void)
6378 if (_a11y_socket_address)
6379 eina_stringshare_del(_a11y_socket_address);
6380 _a11y_socket_address = NULL;
6383 static Key_Event_Info*
6384 _key_event_info_new(int event_type, const Ecore_Event_Key *data, Eo *bridge)
6386 Key_Event_Info *ret;
6387 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
6389 ret = calloc(sizeof(Key_Event_Info), 1);
6391 ret->type = event_type;
6393 ret->bridge = bridge;
6395 ret->event.keyname = eina_stringshare_add(data->keyname);
6396 ret->event.key = eina_stringshare_add(data->key);
6397 ret->event.string = eina_stringshare_add(data->string);
6398 ret->event.compose = eina_stringshare_add(data->compose);
6400 // not sure why it is here, but explicite keep it NULLed.
6401 ret->event.data = NULL;
6407 _key_event_info_free(Key_Event_Info *data)
6409 EINA_SAFETY_ON_NULL_RETURN(data);
6411 eina_stringshare_del(data->event.keyname);
6412 eina_stringshare_del(data->event.key);
6413 eina_stringshare_del(data->event.string);
6414 eina_stringshare_del(data->event.compose);
6420 _iter_marshall_key_event(Eldbus_Message_Iter *iter, Key_Event_Info *data)
6422 Eldbus_Message_Iter *struct_iter;
6423 EINA_SAFETY_ON_NULL_RETURN(data);
6425 struct_iter = eldbus_message_iter_container_new(iter, 'r', NULL);
6427 const char *str = data->event.keyname ? data->event.keyname : "";
6428 int is_text = data->event.keyname ? 1 : 0;
6430 if (data->type == ECORE_EVENT_KEY_DOWN)
6431 type = ATSPI_KEY_PRESSED_EVENT;
6433 type = ATSPI_KEY_RELEASED_EVENT;
6435 eldbus_message_iter_arguments_append(struct_iter, "uiiiisb", type, 0, data->event.keycode, 0, data->event.timestamp, str, is_text);
6436 eldbus_message_iter_container_close(iter, struct_iter);
6440 _on_event_del(void *user_data, void *func_data EINA_UNUSED)
6442 Key_Event_Info *info = user_data;
6443 _key_event_info_free(info);
6447 _on_listener_answer(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6449 Key_Event_Info *info = data;
6450 const char *errname, *errmsg;
6451 Eina_Bool ret = EINA_TRUE;
6453 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(info->bridge, pd);
6455 if (eldbus_message_error_get(msg, &errname, &errmsg))
6457 ERR("%s %s", errname, errmsg);
6460 if (!eldbus_message_arguments_get(msg, "b", &ret))
6462 ERR("Return message doen not contian return value");
6467 _key_event_info_free(info);
6471 ecore_event_add(info->type, &info->event, _on_event_del, info);
6472 pd->reemited_events = eina_list_append(pd->reemited_events, &info->event);
6476 _elm_atspi_bridge_key_filter(void *data, void *loop EINA_UNUSED, int type, void *event)
6478 Eldbus_Message *msg;
6479 Eldbus_Message_Iter *iter;
6480 Ecore_Event_Key *key_event = event;
6484 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_TRUE);
6486 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6487 if (!pd->window_activated) return EINA_TRUE;
6490 if ((type != ECORE_EVENT_KEY_DOWN) && (type != ECORE_EVENT_KEY_UP)) return EINA_TRUE;
6492 // check if reemited
6493 if (eina_list_data_find(pd->reemited_events, event))
6495 pd->reemited_events = eina_list_remove(pd->reemited_events, event);
6499 // TIZEN_ONLY(20170118): Not handle events if keyboard is on
6502 Eina_List *children, *l;
6504 eo_do(pd->root, children = elm_interface_atspi_accessible_children_get());
6506 EINA_LIST_FOREACH(children, l, child)
6508 if (elm_widget_focus_get(child)) break;
6510 eina_list_free(children);
6512 Elm_Win_Keyboard_Mode mode;
6513 mode = elm_win_keyboard_mode_get(child);
6514 if (mode == ELM_WIN_KEYBOARD_ON) return EINA_TRUE;
6518 ke = _key_event_info_new(type, key_event, bridge);
6519 if (!ke) return EINA_TRUE;
6521 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_DEC,
6522 ATSPI_DBUS_INTERFACE_DEC, "NotifyListenersSync");
6523 iter = eldbus_message_iter_get(msg);
6524 _iter_marshall_key_event(iter, ke);
6526 // timeout should be kept reasonaby low to avoid delays
6527 if (!eldbus_connection_send(pd->a11y_bus, msg, _on_listener_answer, ke, 100))
6534 _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6536 return pd->connected;
6540 _elm_atspi_bridge_root_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6544 pd->root = eo_add(ELM_ATSPI_APP_OBJECT_CLASS, NULL);
6545 elm_interface_atspi_accessible_added(pd->root);
6552 _properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
6554 Eldbus_Proxy_Event_Property_Changed *ev = event;
6557 const char *ifc = eldbus_proxy_interface_get(ev->proxy);
6558 if (ev->name && !strcmp(ev->name, "ScreenReaderEnabled" ) &&
6559 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6561 if (!eina_value_get(ev->value, &val))
6563 ERR("Unable to get ScreenReaderEnabled property value");
6566 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6567 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6568 pd->screen_reader_enabled = !!val;
6570 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6571 //register/unregister access objects accordingly.
6572 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6573 _elm_win_screen_reader(val);
6577 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6578 if (ev->name && !strcmp(ev->name, A11Y_DBUS_ENABLED_PROPERTY) &&
6579 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6581 if (!eina_value_get(ev->value, &val))
6583 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6584 ERR("Unable to get " A11Y_DBUS_ENABLED_PROPERTY " property value");
6590 _a11y_connection_init(bridge);
6593 _elm_win_atspi(EINA_FALSE);
6594 _a11y_connection_shutdown(bridge);
6601 _elm_atspi_bridge_eo_base_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6603 Eldbus_Proxy *proxy;
6604 Eldbus_Pending *req;
6606 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_constructor());
6610 if (!(pd->session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION)))
6612 ERR("Unable to connect to Session Bus");
6615 if (!(pd->bus_obj = eldbus_object_get(pd->session_bus, A11Y_DBUS_NAME, A11Y_DBUS_PATH)))
6617 ERR("Could not get /org/a11y/bus object");
6620 if (!(proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE)))
6622 ERR("Could not get proxy object for %s interface", A11Y_DBUS_STATUS_INTERFACE);
6625 if (!(req = eldbus_proxy_property_get(proxy, "ScreenReaderEnabled", _screen_reader_enabled_get, obj)))
6627 ERR("Could not send PropertyGet request");
6630 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6632 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6633 if (!(req = eldbus_proxy_property_get(proxy, A11Y_DBUS_ENABLED_PROPERTY, _at_spi_client_enabled_get, obj)))
6635 ERR("Could not send PropertyGet request");
6639 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6642 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
6643 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
6644 _properties_changed_cb, obj);
6649 eldbus_object_unref(pd->bus_obj);
6652 eldbus_connection_unref(pd->session_bus);
6653 pd->session_bus = NULL;
6658 _elm_atspi_bridge_eo_base_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6660 _a11y_connection_shutdown(obj);
6662 if (pd->bus_obj) eldbus_object_unref(pd->bus_obj);
6663 if (pd->session_bus) eldbus_connection_unref(pd->session_bus);
6664 if (pd->root) eo_del(pd->root);
6666 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_destructor());
6670 elm_atspi_bridge_object_address_get(Eo *obj, char **bus, char **path)
6672 Eo *bridge = _elm_atspi_bridge_get();
6675 ERR("Connection with accessibility bus not established.");
6678 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
6679 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6681 ERR("Connection with accessibility bus not established.");
6684 if (bus) *bus = strdup(eldbus_connection_unique_name_get(pd->a11y_bus));
6685 if (path) *path = strdup(_bridge_path_from_object(bridge, obj));
6691 _proxy_property_get(const Eldbus_Service_Interface *interface, const char *property,
6692 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED,
6693 Eldbus_Message **error EINA_UNUSED)
6696 Eo *obj = eldbus_service_object_data_get(interface, "_atspi_obj");
6697 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6699 if (!strcmp(property, "Object"))
6702 eo_do(obj, parent = eo_parent_get());
6703 if (!elm_atspi_bridge_object_address_get(parent, &bus, &path))
6706 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
6709 eldbus_message_iter_basic_append(iter_struct, 's', bus);
6710 eldbus_message_iter_basic_append(iter_struct, 'o', path);
6711 eldbus_message_iter_container_close(iter, iter_struct);
6720 static const Eldbus_Property proxy_properties[] = {
6721 { "Object", "(so)", _proxy_property_get, NULL, 0 },
6722 { NULL, NULL, NULL, NULL, 0 }
6725 static const Eldbus_Service_Interface_Desc _proxy_iface_desc = {
6726 ELM_ATSPI_DBUS_INTERFACE_PROXY, socket_methods, NULL, proxy_properties, NULL, NULL
6729 static void _embedded_reply_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6731 Eo *parent, *proxy = data;
6732 const char *err, *txt;
6734 if (eldbus_message_error_get(msg, &err, &txt))
6736 ERR("AT-SPI: Embedded method call failed: %s %s", err, txt);
6737 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6740 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_CONNECTED, NULL));
6742 eo_do(proxy, parent = eo_parent_get());
6744 elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, proxy);
6748 _plug_embedded_send(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6750 char *obj_path = NULL;
6752 Eldbus_Message *msg = NULL;
6754 eo_do(proxy, parent = eo_parent_get());
6755 if (!parent) goto fail;
6757 msg = eldbus_message_method_call_new(bus, path, ATSPI_DBUS_INTERFACE_SOCKET, "Embedded");
6758 if (!msg) goto fail;
6760 if (!elm_atspi_bridge_object_address_get(parent, NULL, &obj_path))
6763 if (!eldbus_message_arguments_append(msg, "s", obj_path))
6766 if (!eldbus_connection_send(conn, msg, _embedded_reply_cb, proxy, 100))
6769 ELM_SAFE_FREE(obj_path, free);
6773 ERR("AT-SPI: Unable to send Embedded request.");
6774 if (msg) eldbus_message_unref(msg);
6775 ELM_SAFE_FREE(obj_path, free);
6776 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6779 static void _socket_addr_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6782 const char *bus, *path, *err, *txt;
6783 Eldbus_Message_Iter *iter, *iter_variant, *iter_struct;
6785 Eo *bridge = _elm_atspi_bridge_get();
6788 ERR("AT-SPI: Atspi bridge is not enabled.");
6791 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6793 if (eldbus_message_error_get(msg, &err, &txt))
6795 ERR("Unable to connect to socket: %s %s", err, txt);
6799 iter = eldbus_message_iter_get(msg);
6800 if (!eldbus_message_iter_arguments_get(iter, "v", &iter_variant))
6802 ERR("Unable to get variant parameter");
6806 if (!eldbus_message_iter_arguments_get(iter_variant, "(so)", &iter_struct))
6808 ERR("Unable to get so parameters");
6812 if (!eldbus_message_iter_arguments_get(iter_struct, "so", &bus, &path))
6814 ERR("Unable to get so parameters");
6818 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
6820 _plug_embedded_send(pd->a11y_bus, proxy, bus, path);
6825 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6829 eo_do(proxy, elm_obj_atspi_proxy_address_get_retry_timer_add());
6833 _plug_address_discover(Eldbus_Connection *conn, Eo *proxy, const char *svc_bus, const char *svc_path)
6835 Eldbus_Object *dobj;
6836 dobj = eldbus_object_get(conn, svc_bus, svc_path);
6839 ERR("Unable to get eldbus object from: %s %s", svc_bus, svc_path);
6843 Eldbus_Message *msg = eldbus_object_method_call_new(dobj, ELDBUS_FDO_INTERFACE_PROPERTIES, "Get");
6844 eldbus_message_arguments_append(msg, "ss", ELM_ATSPI_DBUS_INTERFACE_PROXY, "Object");
6845 eldbus_object_send(dobj, msg, _socket_addr_get_cb, proxy, 100);
6848 static void _plug_connect(Eldbus_Connection *conn, Eo *proxy)
6850 const char *bus, *path;
6852 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
6853 eo_do(proxy, path = eo_key_data_get("__svc_path"));
6857 _plug_address_discover(conn, proxy, bus, path);
6862 eo_do(proxy, elm_obj_atspi_proxy_address_get(&bus, &path));
6865 ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set. Unable to connect");
6866 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6869 _plug_embedded_send(conn, proxy, bus, path);
6874 static Eina_Bool _from_list_remove(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6876 Eina_List **list = data;
6877 *list = eina_list_remove(*list, obj);
6881 EAPI void elm_atspi_bridge_utils_proxy_connect(Eo *proxy)
6883 Eo *bridge = _elm_atspi_bridge_get();
6887 ERR("AT-SPI: Atspi bridge is not enabled.");
6888 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6891 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6895 if (!eina_list_data_find(pd->plug_queue, proxy))
6897 pd->plug_queue = eina_list_append(pd->plug_queue, proxy);
6898 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->plug_queue));
6902 _plug_connect(pd->a11y_bus, proxy);
6906 * @brief Service name sanitizer according to specs:
6907 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
6908 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
6910 char *_sanitize_service_name(const char *name)
6912 char ret[256] = "\0";
6914 if (!name) return NULL;
6916 const char *tmp = name;
6919 // name element should not begin with digit. Swallow non-charater prefix
6920 while ((*tmp != '\0') && !isalpha(*tmp)) tmp++;
6922 // append rest of character valid charactes [A-Z][a-z][0-9]_
6923 while ((*tmp != '\0') && (dst < &ret[sizeof(ret) - 1]))
6925 if (isalpha(*tmp) || isdigit(*tmp) || (*tmp == '_'))
6934 Eo* _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type)
6937 char bus[256], path[256], *name;
6940 name = _sanitize_service_name(svcname);
6941 if (!name) return NULL;
6943 res = snprintf(bus, sizeof(bus), "elm.atspi.proxy.socket.%s-%d", name, svcnum);
6944 if (res < 0 || (res >= (int)sizeof(bus)))
6950 res = snprintf(path, sizeof(path), "/elm/atspi/proxy/socket/%s/%d", name, svcnum);
6951 if (res < 0 || (res >= (int)sizeof(path)))
6959 ret = eo_add(ELM_ATSPI_PROXY_CLASS, parent, elm_obj_atspi_proxy_constructor(type));
6960 if (!ret) return NULL;
6962 eo_do(ret, eo_key_data_set("__svc_bus", eina_stringshare_add(bus)));
6963 eo_do(ret, eo_key_data_set("__svc_path", eina_stringshare_add(path)));
6969 _on_socket_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6971 Eldbus_Service_Interface *ifc = data;
6973 Eldbus_Connection *conn = eldbus_service_connection_get(ifc);
6974 eo_do(obj, bus = eo_key_data_get("__svc_bus"));
6975 eldbus_name_release(conn, bus, NULL, NULL);
6976 eldbus_service_interface_unregister(ifc);
6981 _proxy_interface_register(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6983 Eldbus_Service_Interface *proxy_infc;
6984 Eo *bridge = _elm_atspi_bridge_get();
6987 ERR("AT-SPI: Atspi bridge is not enabled.");
6990 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6992 eldbus_name_request(conn, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, NULL, NULL);
6993 proxy_infc = eldbus_service_interface_register(pd->a11y_bus, path, &_proxy_iface_desc);
6995 ERR("AT-SPI: Proxy interface registration failed");
6996 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _on_socket_del, proxy_infc));
6997 eldbus_service_object_data_set(proxy_infc, "_atspi_obj", proxy);
7000 static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy)
7002 const char *bus, *path;
7003 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7004 Eo *bridge = _elm_atspi_bridge_get();
7005 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7008 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7009 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7012 _proxy_interface_register(conn, proxy, bus, path);
7014 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7015 pd->interfaces.socket =
7016 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &socket_iface_desc);
7020 EAPI void elm_atspi_bridge_utils_proxy_listen(Eo *proxy)
7022 Eo *bridge = _elm_atspi_bridge_get();
7025 ERR("AT-SPI: Atspi bridge is not enabled.");
7028 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7031 if (!eina_list_data_find(pd->socket_queue, proxy))
7033 pd->socket_queue = eina_list_append(pd->socket_queue, proxy);
7034 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->socket_queue));
7038 _socket_ifc_create(pd->a11y_bus, proxy);
7041 //TIZEN_ONLY(20160527) - Add direct reading feature
7043 _on_read_command_call(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7045 const char *errname, *errmsg;
7049 Elm_Atspi_Say_Info *say_info = data;
7051 if (eldbus_message_error_get(msg, &errname, &errmsg))
7053 ERR("%s %s", errname, errmsg);
7059 // get read command id and map it to obj
7060 if (eldbus_message_arguments_get(msg, "sbi", &s, &b, &i))
7062 if (!read_command_id)
7063 read_command_id = eina_hash_int32_new(NULL);
7065 if (!read_command_id) {
7066 ERR("eina_hash_int32_new() failed to create new map to store callbacks for direct reading commands");
7070 eina_hash_add(read_command_id, &i, say_info);
7076 elm_atspi_bridge_utils_say(const char* text,
7077 Eina_Bool discardable,
7078 const Elm_Atspi_Say_Signal_Cb func,
7081 Eldbus_Message *msg;
7082 Eldbus_Message_Iter *iter;
7083 Elm_Atspi_Say_Info *say_info = NULL;
7084 Eo *bridge = _elm_atspi_bridge_get();
7087 ERR("AT-SPI: Atspi bridge is not enabled.");
7090 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7093 ERR("AT-SPI: a11y bus is not set.");
7097 msg = eldbus_message_method_call_new(ELM_ATSPI_DIRECT_READ_BUS,
7098 ELM_ATSPI_DIRECT_READ_PATH,
7099 ELM_ATSPI_DIRECT_READ_INTERFACE,
7101 iter = eldbus_message_iter_get(msg);
7102 eldbus_message_iter_arguments_append(iter, "sb", text, discardable);
7104 say_info = calloc(1, sizeof(Elm_Atspi_Say_Info));
7106 say_info->func = func;
7107 say_info->data = (void *)data;
7110 eldbus_connection_send(pd->a11y_bus, msg, _on_read_command_call, say_info, -1);
7114 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7116 _offset_set_reply_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7118 const char *err, *txt;
7120 if (eldbus_message_error_get(msg, &err, &txt))
7122 ERR("AT-SPI: SetOffset method call failed: %s %s", err, txt);
7127 void elm_atspi_bridge_utils_proxy_offset_set(Eo *proxy, int x, int y)
7129 const char *bus, *path;
7130 Eo *bridge = _elm_atspi_bridge_get();
7131 if (!bridge) return;
7133 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7135 if (!pd->a11y_bus) return;
7137 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7138 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7140 Eldbus_Message *msg = NULL;
7142 msg = eldbus_message_method_call_new(bus, path, ELM_ATSPI_DBUS_INTERFACE_PROXY, "SetOffset");
7143 if (!msg) goto fail;
7145 if (!eldbus_message_arguments_append(msg, "i", x))
7148 if (!eldbus_message_arguments_append(msg, "i", y))
7151 if (!eldbus_connection_send(pd->a11y_bus, msg, _offset_set_reply_cb, NULL, 100))
7157 ERR("AT-SPI: Unable to send SetOffset request.");
7158 if (msg) eldbus_message_unref(msg);
7161 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
7162 EAPI Eina_Bool elm_atspi_bridge_utils_is_screen_reader_enabled(void)
7164 Eo *bridge = _elm_atspi_bridge_get();
7167 ERR("AT-SPI: Atspi bridge is not enabled.");
7170 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
7171 return pd->screen_reader_enabled;
7174 #include "elm_atspi_bridge.eo.c"