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 enum _Atspi_Object_Child_Event_Type
223 ATSPI_OBJECT_CHILD_ADDED = 0,
224 ATSPI_OBJECT_CHILD_REMOVED
227 enum _Atspi_Object_Property
229 ATSPI_OBJECT_PROPERTY_NAME = 0,
230 ATSPI_OBJECT_PROPERTY_DESCRIPTION,
231 ATSPI_OBJECT_PROPERTY_VALUE,
232 ATSPI_OBJECT_PROPERTY_ROLE,
233 ATSPI_OBJECT_PROPERTY_PARENT,
234 ATSPI_OBJECT_PROPERTY_LAST
237 enum _Atspi_Object_Signals {
238 ATSPI_OBJECT_EVENT_PROPERTY_CHANGED = 0,
239 ATSPI_OBJECT_EVENT_BOUNDS_CHANGED,
240 ATSPI_OBJECT_EVENT_LINK_SELECTED,
241 ATSPI_OBJECT_EVENT_STATE_CHANGED,
242 ATSPI_OBJECT_EVENT_CHILDREN_CHANGED,
243 ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED,
244 ATSPI_OBJECT_EVENT_SELECTION_CHANGED,
245 ATSPI_OBJECT_EVENT_MODEL_CHANGED,
246 ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED,
247 ATSPI_OBJECT_EVENT_ROW_INSERTED,
248 ATSPI_OBJECT_EVENT_ROW_REORDERED,
249 ATSPI_OBJECT_EVENT_ROW_DELETED,
250 ATSPI_OBJECT_EVENT_COLUMN_INSERTED,
251 ATSPI_OBJECT_EVENT_COLUMN_REORDERED,
252 ATSPI_OBJECT_EVENT_COLUMN_DELETED,
253 ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED,
254 ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED,
255 ATSPI_OBJECT_EVENT_TEXT_CHANGED,
256 ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED,
257 ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED,
258 ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED,
259 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
260 ATSPI_OBJECT_EVENT_MOVE_OUTED
264 enum _Atspi_Window_Signals
266 ATSPI_WINDOW_EVENT_PROPERTY_CHANGE = 0,
267 ATSPI_WINDOW_EVENT_MINIMIZE,
268 ATSPI_WINDOW_EVENT_MAXIMIZE,
269 ATSPI_WINDOW_EVENT_RESTORE,
270 ATSPI_WINDOW_EVENT_CLOSE,
271 ATSPI_WINDOW_EVENT_CREATE,
272 ATSPI_WINDOW_EVENT_REPARENT,
273 ATSPI_WINDOW_EVENT_DESKTOPCREATE,
274 ATSPI_WINDOW_EVENT_DESKTOPDESTROY,
275 ATSPI_WINDOW_EVENT_DESTROY,
276 ATSPI_WINDOW_EVENT_ACTIVATE,
277 ATSPI_WINDOW_EVENT_DEACTIVATE,
278 ATSPI_WINDOW_EVENT_RAISE,
279 ATSPI_WINDOW_EVENT_LOWER,
280 ATSPI_WINDOW_EVENT_MOVE,
281 ATSPI_WINDOW_EVENT_RESIZE,
282 ATSPI_WINDOW_EVENT_SHADE,
283 ATSPI_WINDOW_EVENT_UUSHADE,
284 ATSPI_WINDOW_EVENT_RESTYLE,
287 static const Eldbus_Signal _event_obj_signals[] = {
288 [ATSPI_OBJECT_EVENT_PROPERTY_CHANGED] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
289 [ATSPI_OBJECT_EVENT_BOUNDS_CHANGED] = {"BoundsChanged", ELDBUS_ARGS({"siiv(iiii)", NULL}), 0},
290 [ATSPI_OBJECT_EVENT_LINK_SELECTED] = {"LinkSelected", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
291 [ATSPI_OBJECT_EVENT_STATE_CHANGED] = {"StateChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
292 [ATSPI_OBJECT_EVENT_CHILDREN_CHANGED] = {"ChildrenChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
293 [ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED] = {"VisibleDataChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
294 [ATSPI_OBJECT_EVENT_SELECTION_CHANGED] = {"SelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
295 [ATSPI_OBJECT_EVENT_MODEL_CHANGED] = {"ModelChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
296 [ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED] = {"ActiveDescendantChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
297 [ATSPI_OBJECT_EVENT_ROW_INSERTED] = {"RowInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
298 [ATSPI_OBJECT_EVENT_ROW_REORDERED] = {"RowReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
299 [ATSPI_OBJECT_EVENT_ROW_DELETED] = {"RowDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
300 [ATSPI_OBJECT_EVENT_COLUMN_INSERTED] = {"ColumnInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
301 [ATSPI_OBJECT_EVENT_COLUMN_REORDERED] = {"ColumnReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
302 [ATSPI_OBJECT_EVENT_COLUMN_DELETED] = {"ColumnDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
303 [ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED] = {"TextBoundsChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
304 [ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED] = {"TextSelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
305 [ATSPI_OBJECT_EVENT_TEXT_CHANGED] = {"TextChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
306 [ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED] = {"TextAttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
307 [ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED] = {"TextCaretMoved", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
308 [ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED] = {"AttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
309 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
310 [ATSPI_OBJECT_EVENT_MOVE_OUTED] = {"MoveOuted", ELDBUS_ARGS({"siiv(i)", NULL}), 0},
312 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
315 static const Eldbus_Signal _window_obj_signals[] = {
316 [ATSPI_WINDOW_EVENT_PROPERTY_CHANGE] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
317 [ATSPI_WINDOW_EVENT_MINIMIZE] = {"Minimize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
318 [ATSPI_WINDOW_EVENT_MAXIMIZE] = {"Maximize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
319 [ATSPI_WINDOW_EVENT_RESTORE] = {"Restore", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
320 [ATSPI_WINDOW_EVENT_CLOSE] = {"Close", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
321 [ATSPI_WINDOW_EVENT_CREATE] = {"Create", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
322 [ATSPI_WINDOW_EVENT_REPARENT] = {"Reparent", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
323 [ATSPI_WINDOW_EVENT_DESKTOPCREATE] = {"DesktopCreate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
324 [ATSPI_WINDOW_EVENT_DESKTOPDESTROY] = {"DesktopDestroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
325 [ATSPI_WINDOW_EVENT_DESTROY] = {"Destroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
326 [ATSPI_WINDOW_EVENT_ACTIVATE] = {"Activate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
327 [ATSPI_WINDOW_EVENT_DEACTIVATE] = {"Deactivate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
328 [ATSPI_WINDOW_EVENT_RAISE] = {"Raise", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
329 [ATSPI_WINDOW_EVENT_LOWER] = {"Lower", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
330 [ATSPI_WINDOW_EVENT_MOVE] = {"Move", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
331 [ATSPI_WINDOW_EVENT_RESIZE] = {"Resize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
332 [ATSPI_WINDOW_EVENT_SHADE] = {"Shade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
333 [ATSPI_WINDOW_EVENT_UUSHADE] = {"uUshade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
334 [ATSPI_WINDOW_EVENT_RESTYLE] = {"Restyle", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
335 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
338 const int elm_roles_to_atspi_roles[][2] = {
339 { ELM_ATSPI_ROLE_INVALID, ATSPI_ROLE_INVALID },
340 { ELM_ATSPI_ROLE_ACCELERATOR_LABEL, ATSPI_ROLE_ACCELERATOR_LABEL },
341 { ELM_ATSPI_ROLE_ALERT, ATSPI_ROLE_ALERT },
342 { ELM_ATSPI_ROLE_ANIMATION, ATSPI_ROLE_ANIMATION },
343 { ELM_ATSPI_ROLE_ARROW, ATSPI_ROLE_ARROW },
344 { ELM_ATSPI_ROLE_CALENDAR, ATSPI_ROLE_CALENDAR },
345 { ELM_ATSPI_ROLE_CANVAS, ATSPI_ROLE_CANVAS },
346 { ELM_ATSPI_ROLE_CHECK_BOX, ATSPI_ROLE_CHECK_BOX },
347 { ELM_ATSPI_ROLE_CHECK_MENU_ITEM, ATSPI_ROLE_CHECK_MENU_ITEM },
348 { ELM_ATSPI_ROLE_COLOR_CHOOSER, ATSPI_ROLE_COLOR_CHOOSER },
349 { ELM_ATSPI_ROLE_COLUMN_HEADER, ATSPI_ROLE_COLUMN_HEADER },
350 { ELM_ATSPI_ROLE_COMBO_BOX, ATSPI_ROLE_COMBO_BOX },
351 { ELM_ATSPI_ROLE_DATE_EDITOR, ATSPI_ROLE_DATE_EDITOR },
352 { ELM_ATSPI_ROLE_DESKTOP_ICON, ATSPI_ROLE_DESKTOP_ICON },
353 { ELM_ATSPI_ROLE_DESKTOP_FRAME, ATSPI_ROLE_DESKTOP_FRAME },
354 { ELM_ATSPI_ROLE_DIAL, ATSPI_ROLE_DIAL },
355 { ELM_ATSPI_ROLE_DIALOG, ATSPI_ROLE_DIALOG },
356 { ELM_ATSPI_ROLE_DIRECTORY_PANE, ATSPI_ROLE_DIRECTORY_PANE },
357 { ELM_ATSPI_ROLE_DRAWING_AREA, ATSPI_ROLE_DRAWING_AREA },
358 { ELM_ATSPI_ROLE_FILE_CHOOSER, ATSPI_ROLE_FILE_CHOOSER },
359 { ELM_ATSPI_ROLE_FILLER, ATSPI_ROLE_FILLER },
360 { ELM_ATSPI_ROLE_FOCUS_TRAVERSABLE, ATSPI_ROLE_FOCUS_TRAVERSABLE },
361 { ELM_ATSPI_ROLE_FONT_CHOOSER, ATSPI_ROLE_FONT_CHOOSER },
362 { ELM_ATSPI_ROLE_FRAME, ATSPI_ROLE_FRAME },
363 { ELM_ATSPI_ROLE_GLASS_PANE, ATSPI_ROLE_GLASS_PANE },
364 { ELM_ATSPI_ROLE_HTML_CONTAINER, ATSPI_ROLE_HTML_CONTAINER },
365 { ELM_ATSPI_ROLE_ICON, ATSPI_ROLE_ICON },
366 { ELM_ATSPI_ROLE_IMAGE, ATSPI_ROLE_IMAGE },
367 { ELM_ATSPI_ROLE_INTERNAL_FRAME, ATSPI_ROLE_INTERNAL_FRAME },
368 { ELM_ATSPI_ROLE_LABEL, ATSPI_ROLE_LABEL },
369 { ELM_ATSPI_ROLE_LAYERED_PANE, ATSPI_ROLE_LAYERED_PANE },
370 { ELM_ATSPI_ROLE_LIST, ATSPI_ROLE_LIST },
371 { ELM_ATSPI_ROLE_LIST_ITEM, ATSPI_ROLE_LIST_ITEM },
372 { ELM_ATSPI_ROLE_MENU, ATSPI_ROLE_MENU },
373 { ELM_ATSPI_ROLE_MENU_BAR, ATSPI_ROLE_MENU_BAR },
374 { ELM_ATSPI_ROLE_MENU_ITEM, ATSPI_ROLE_MENU_ITEM },
375 { ELM_ATSPI_ROLE_OPTION_PANE, ATSPI_ROLE_OPTION_PANE },
376 { ELM_ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_PAGE_TAB },
377 { ELM_ATSPI_ROLE_PAGE_TAB_LIST, ATSPI_ROLE_PAGE_TAB_LIST },
378 { ELM_ATSPI_ROLE_PANEL, ATSPI_ROLE_PANEL },
379 { ELM_ATSPI_ROLE_PASSWORD_TEXT, ATSPI_ROLE_PASSWORD_TEXT },
380 { ELM_ATSPI_ROLE_POPUP_MENU, ATSPI_ROLE_POPUP_MENU },
381 { ELM_ATSPI_ROLE_PROGRESS_BAR, ATSPI_ROLE_PROGRESS_BAR },
382 { ELM_ATSPI_ROLE_PUSH_BUTTON, ATSPI_ROLE_PUSH_BUTTON },
383 { ELM_ATSPI_ROLE_RADIO_BUTTON, ATSPI_ROLE_RADIO_BUTTON },
384 { ELM_ATSPI_ROLE_RADIO_MENU_ITEM, ATSPI_ROLE_RADIO_MENU_ITEM },
385 { ELM_ATSPI_ROLE_ROOT_PANE, ATSPI_ROLE_ROOT_PANE },
386 { ELM_ATSPI_ROLE_ROW_HEADER, ATSPI_ROLE_ROW_HEADER },
387 { ELM_ATSPI_ROLE_SCROLL_BAR, ATSPI_ROLE_SCROLL_BAR },
388 { ELM_ATSPI_ROLE_SCROLL_PANE, ATSPI_ROLE_SCROLL_PANE },
389 { ELM_ATSPI_ROLE_SEPARATOR, ATSPI_ROLE_SEPARATOR },
390 { ELM_ATSPI_ROLE_SLIDER, ATSPI_ROLE_SLIDER },
391 { ELM_ATSPI_ROLE_SPIN_BUTTON, ATSPI_ROLE_SPIN_BUTTON },
392 { ELM_ATSPI_ROLE_SPLIT_PANE, ATSPI_ROLE_SPLIT_PANE },
393 { ELM_ATSPI_ROLE_STATUS_BAR, ATSPI_ROLE_STATUS_BAR },
394 { ELM_ATSPI_ROLE_TABLE, ATSPI_ROLE_TABLE },
395 { ELM_ATSPI_ROLE_TABLE_CELL, ATSPI_ROLE_TABLE_CELL },
396 { ELM_ATSPI_ROLE_TABLE_COLUMN_HEADER, ATSPI_ROLE_TABLE_COLUMN_HEADER },
397 { ELM_ATSPI_ROLE_TABLE_ROW_HEADER, ATSPI_ROLE_TABLE_ROW_HEADER },
398 { ELM_ATSPI_ROLE_TEAROFF_MENU_ITEM, ATSPI_ROLE_TEAROFF_MENU_ITEM },
399 { ELM_ATSPI_ROLE_TERMINAL, ATSPI_ROLE_TERMINAL },
400 { ELM_ATSPI_ROLE_TEXT, ATSPI_ROLE_TEXT },
401 { ELM_ATSPI_ROLE_TOGGLE_BUTTON, ATSPI_ROLE_TOGGLE_BUTTON },
402 { ELM_ATSPI_ROLE_TOOL_BAR, ATSPI_ROLE_TOOL_BAR },
403 { ELM_ATSPI_ROLE_TOOL_TIP, ATSPI_ROLE_TOOL_TIP },
404 { ELM_ATSPI_ROLE_TREE, ATSPI_ROLE_TREE },
405 { ELM_ATSPI_ROLE_TREE_TABLE, ATSPI_ROLE_TREE_TABLE },
406 { ELM_ATSPI_ROLE_UNKNOWN, ATSPI_ROLE_UNKNOWN },
407 { ELM_ATSPI_ROLE_VIEWPORT, ATSPI_ROLE_VIEWPORT },
408 { ELM_ATSPI_ROLE_WINDOW, ATSPI_ROLE_WINDOW },
409 { ELM_ATSPI_ROLE_EXTENDED, ATSPI_ROLE_EXTENDED },
410 { ELM_ATSPI_ROLE_HEADER, ATSPI_ROLE_HEADER },
411 { ELM_ATSPI_ROLE_FOOTER, ATSPI_ROLE_FOOTER },
412 { ELM_ATSPI_ROLE_PARAGRAPH, ATSPI_ROLE_PARAGRAPH },
413 { ELM_ATSPI_ROLE_RULER, ATSPI_ROLE_RULER },
414 { ELM_ATSPI_ROLE_APPLICATION, ATSPI_ROLE_APPLICATION },
415 { ELM_ATSPI_ROLE_AUTOCOMPLETE, ATSPI_ROLE_AUTOCOMPLETE },
416 { ELM_ATSPI_ROLE_EDITBAR, ATSPI_ROLE_EDITBAR },
417 { ELM_ATSPI_ROLE_EMBEDDED, ATSPI_ROLE_EMBEDDED },
418 { ELM_ATSPI_ROLE_ENTRY, ATSPI_ROLE_ENTRY },
419 { ELM_ATSPI_ROLE_CHART, ATSPI_ROLE_CHART },
420 { ELM_ATSPI_ROLE_CAPTION, ATSPI_ROLE_CAPTION },
421 { ELM_ATSPI_ROLE_DOCUMENT_FRAME, ATSPI_ROLE_DOCUMENT_FRAME },
422 { ELM_ATSPI_ROLE_HEADING, ATSPI_ROLE_HEADING },
423 { ELM_ATSPI_ROLE_PAGE, ATSPI_ROLE_PAGE },
424 { ELM_ATSPI_ROLE_SECTION, ATSPI_ROLE_SECTION },
425 { ELM_ATSPI_ROLE_REDUNDANT_OBJECT, ATSPI_ROLE_REDUNDANT_OBJECT },
426 { ELM_ATSPI_ROLE_FORM, ATSPI_ROLE_FORM },
427 { ELM_ATSPI_ROLE_LINK, ATSPI_ROLE_LINK },
428 { ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW, ATSPI_ROLE_INPUT_METHOD_WINDOW },
429 { ELM_ATSPI_ROLE_TABLE_ROW, ATSPI_ROLE_TABLE_ROW },
430 { ELM_ATSPI_ROLE_TREE_ITEM, ATSPI_ROLE_TREE_ITEM },
431 { ELM_ATSPI_ROLE_DOCUMENT_SPREADSHEET, ATSPI_ROLE_DOCUMENT_SPREADSHEET },
432 { ELM_ATSPI_ROLE_DOCUMENT_PRESENTATION, ATSPI_ROLE_DOCUMENT_PRESENTATION },
433 { ELM_ATSPI_ROLE_DOCUMENT_TEXT, ATSPI_ROLE_DOCUMENT_TEXT },
434 { ELM_ATSPI_ROLE_DOCUMENT_WEB, ATSPI_ROLE_DOCUMENT_WEB },
435 { ELM_ATSPI_ROLE_DOCUMENT_EMAIL, ATSPI_ROLE_DOCUMENT_EMAIL },
436 { ELM_ATSPI_ROLE_COMMENT, ATSPI_ROLE_COMMENT },
437 { ELM_ATSPI_ROLE_LIST_BOX, ATSPI_ROLE_LIST_BOX },
438 { ELM_ATSPI_ROLE_GROUPING, ATSPI_ROLE_GROUPING },
439 { ELM_ATSPI_ROLE_IMAGE_MAP, ATSPI_ROLE_IMAGE_MAP },
440 { ELM_ATSPI_ROLE_NOTIFICATION, ATSPI_ROLE_NOTIFICATION },
441 { ELM_ATSPI_ROLE_INFO_BAR, ATSPI_ROLE_INFO_BAR },
442 { ELM_ATSPI_ROLE_LAST_DEFINED, ATSPI_ROLE_LAST_DEFINED },
445 struct atspi_state_desc
447 Elm_Atspi_State_Type elm_state;
448 AtspiStateType atspi_state;
452 const struct atspi_state_desc elm_states_to_atspi_state[] = {
453 { ELM_ATSPI_STATE_INVALID, ATSPI_STATE_INVALID, "invalid" },
454 { ELM_ATSPI_STATE_ACTIVE, ATSPI_STATE_ACTIVE, "active" },
455 { ELM_ATSPI_STATE_ARMED, ATSPI_STATE_ARMED, "armed" },
456 { ELM_ATSPI_STATE_BUSY, ATSPI_STATE_BUSY, "busy" },
457 { ELM_ATSPI_STATE_CHECKED, ATSPI_STATE_CHECKED, "checked" },
458 { ELM_ATSPI_STATE_COLLAPSED, ATSPI_STATE_COLLAPSED, "collapsed" },
459 { ELM_ATSPI_STATE_DEFUNCT, ATSPI_STATE_DEFUNCT, "defunct" },
460 { ELM_ATSPI_STATE_EDITABLE, ATSPI_STATE_EDITABLE, "editable" },
461 { ELM_ATSPI_STATE_ENABLED, ATSPI_STATE_ENABLED, "enabled" },
462 { ELM_ATSPI_STATE_EXPANDABLE, ATSPI_STATE_EXPANDABLE, "expandable" },
463 { ELM_ATSPI_STATE_EXPANDED, ATSPI_STATE_EXPANDED, "expanded" },
464 { ELM_ATSPI_STATE_FOCUSABLE, ATSPI_STATE_FOCUSABLE, "focusable" },
465 { ELM_ATSPI_STATE_FOCUSED, ATSPI_STATE_FOCUSED, "focused" },
466 { ELM_ATSPI_STATE_HAS_TOOLTIP, ATSPI_STATE_HAS_TOOLTIP, "has-tooltip" },
467 { ELM_ATSPI_STATE_HORIZONTAL, ATSPI_STATE_HORIZONTAL, "horizontal" },
468 { ELM_ATSPI_STATE_ICONIFIED, ATSPI_STATE_ICONIFIED, "iconified" },
469 { ELM_ATSPI_STATE_MODAL, ATSPI_STATE_MODAL, "modal" },
470 { ELM_ATSPI_STATE_MULTI_LINE, ATSPI_STATE_MULTI_LINE, "multi-line" },
471 { ELM_ATSPI_STATE_MULTISELECTABLE, ATSPI_STATE_MULTISELECTABLE, "multiselectable" },
472 { ELM_ATSPI_STATE_OPAQUE, ATSPI_STATE_OPAQUE, "opaque" },
473 { ELM_ATSPI_STATE_PRESSED, ATSPI_STATE_PRESSED, "pressed" },
474 { ELM_ATSPI_STATE_RESIZABLE, ATSPI_STATE_RESIZABLE, "resizable" },
475 { ELM_ATSPI_STATE_SELECTABLE, ATSPI_STATE_SELECTABLE, "selectable" },
476 { ELM_ATSPI_STATE_SELECTED, ATSPI_STATE_SELECTED, "selected" },
477 { ELM_ATSPI_STATE_SENSITIVE, ATSPI_STATE_SENSITIVE, "sensitive" },
478 { ELM_ATSPI_STATE_SHOWING, ATSPI_STATE_SHOWING, "showing" },
479 { ELM_ATSPI_STATE_SINGLE_LINE, ATSPI_STATE_SINGLE_LINE, "single-line" },
480 { ELM_ATSPI_STATE_STALE, ATSPI_STATE_STALE, "stale" },
481 { ELM_ATSPI_STATE_TRANSIENT, ATSPI_STATE_TRANSIENT, "transient" },
482 { ELM_ATSPI_STATE_VERTICAL, ATSPI_STATE_VERTICAL, "vertical" },
483 { ELM_ATSPI_STATE_VISIBLE, ATSPI_STATE_VISIBLE, "visible" },
484 { ELM_ATSPI_STATE_MANAGES_DESCENDANTS, ATSPI_STATE_MANAGES_DESCENDANTS, "manages-descendants" },
485 { ELM_ATSPI_STATE_INDETERMINATE, ATSPI_STATE_INDETERMINATE, "indeterminate" },
486 { ELM_ATSPI_STATE_REQUIRED, ATSPI_STATE_REQUIRED, "required" },
487 { ELM_ATSPI_STATE_TRUNCATED, ATSPI_STATE_TRUNCATED, "truncated" },
488 { ELM_ATSPI_STATE_ANIMATED, ATSPI_STATE_ANIMATED, "animated" },
489 { ELM_ATSPI_STATE_INVALID_ENTRY, ATSPI_STATE_INVALID_ENTRY, "invalid-entry" },
490 { ELM_ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, "supports-autocompletion" },
491 { ELM_ATSPI_STATE_SELECTABLE_TEXT, ATSPI_STATE_SELECTABLE_TEXT, "selectable-text" },
492 { ELM_ATSPI_STATE_IS_DEFAULT, ATSPI_STATE_IS_DEFAULT, "is-default" },
493 { ELM_ATSPI_STATE_VISITED, ATSPI_STATE_VISITED, "visited" },
494 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
495 { ELM_ATSPI_STATE_CHECKABLE, ATSPI_STATE_CHECKABLE, "checkable" },
496 { ELM_ATSPI_STATE_HAS_POPUP, ATSPI_STATE_HAS_POPUP, "has-popup" },
497 { ELM_ATSPI_STATE_READ_ONLY, ATSPI_STATE_READ_ONLY, "read-only" },
498 { ELM_ATSPI_STATE_HIGHLIGHTED, ATSPI_STATE_HIGHLIGHTED, "highlighted" },
499 { ELM_ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_HIGHLIGHTABLE, "highlightable" },
501 { ELM_ATSPI_STATE_LAST_DEFINED, ATSPI_STATE_LAST_DEFINED, "last-defined" }
504 const int elm_relation_to_atspi_relation_mapping[] = {
505 [ELM_ATSPI_RELATION_NULL] = ATSPI_RELATION_NULL,
506 [ELM_ATSPI_RELATION_LABEL_FOR] = ATSPI_RELATION_LABEL_FOR,
507 [ELM_ATSPI_RELATION_LABELLED_BY] = ATSPI_RELATION_LABELLED_BY,
508 [ELM_ATSPI_RELATION_CONTROLLER_FOR] = ATSPI_RELATION_CONTROLLER_FOR,
509 [ELM_ATSPI_RELATION_CONTROLLED_BY] = ATSPI_RELATION_CONTROLLED_BY,
510 [ELM_ATSPI_RELATION_MEMBER_OF] = ATSPI_RELATION_MEMBER_OF,
511 [ELM_ATSPI_RELATION_TOOLTIP_FOR] = ATSPI_RELATION_TOOLTIP_FOR,
512 [ELM_ATSPI_RELATION_NODE_CHILD_OF] = ATSPI_RELATION_NODE_CHILD_OF,
513 [ELM_ATSPI_RELATION_NODE_PARENT_OF] = ATSPI_RELATION_NODE_PARENT_OF,
514 [ELM_ATSPI_RELATION_EXTENDED] = ATSPI_RELATION_EXTENDED,
515 [ELM_ATSPI_RELATION_FLOWS_TO] = ATSPI_RELATION_FLOWS_TO,
516 [ELM_ATSPI_RELATION_FLOWS_FROM] = ATSPI_RELATION_FLOWS_FROM,
517 [ELM_ATSPI_RELATION_SUBWINDOW_OF] = ATSPI_RELATION_SUBWINDOW_OF,
518 [ELM_ATSPI_RELATION_EMBEDS] = ATSPI_RELATION_EMBEDS,
519 [ELM_ATSPI_RELATION_EMBEDDED_BY] = ATSPI_RELATION_EMBEDDED_BY,
520 [ELM_ATSPI_RELATION_POPUP_FOR] = ATSPI_RELATION_POPUP_FOR,
521 [ELM_ATSPI_RELATION_PARENT_WINDOW_OF] = ATSPI_RELATION_PARENT_WINDOW_OF,
522 [ELM_ATSPI_RELATION_DESCRIPTION_FOR] = ATSPI_RELATION_DESCRIPTION_FOR,
523 [ELM_ATSPI_RELATION_DESCRIBED_BY] = ATSPI_RELATION_DESCRIBED_BY,
524 [ELM_ATSPI_RELATION_LAST_DEFINED] = ATSPI_RELATION_LAST_DEFINED,
527 static inline Eldbus_Message *_dbus_invalid_ref_error_new(const Eldbus_Message *msg)
529 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.UnknownObject", "Path is not valid accessible object reference.");
532 static AtspiRelationType _elm_relation_to_atspi_relation(Elm_Atspi_Relation_Type type)
534 if ((type < ELM_ATSPI_RELATION_LAST_DEFINED) && (type > ELM_ATSPI_RELATION_NULL))
535 return elm_relation_to_atspi_relation_mapping[type];
536 return ATSPI_RELATION_NULL;
539 static Elm_Atspi_Relation_Type _atspi_relation_to_elm_relation(AtspiRelationType type)
542 for(i = 0; i < sizeof(elm_relation_to_atspi_relation_mapping) / sizeof(elm_relation_to_atspi_relation_mapping[0]); ++i)
544 if (elm_relation_to_atspi_relation_mapping[i] == (int)type) return (Elm_Atspi_Relation_Type)i;
546 return ELM_ATSPI_RELATION_NULL;
549 static AtspiRole _elm_role_to_atspi_role(Elm_Atspi_Role role)
551 return role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
554 static Eldbus_Message *
555 _accessible_get_role(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
557 const char *obj_path = eldbus_message_path_get(msg);
558 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
559 Eo *obj = _bridge_object_from_path(bridge, obj_path);
562 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
564 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
566 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
567 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
569 AtspiRole atspi_role = _elm_role_to_atspi_role(role);
570 eldbus_message_arguments_append(ret, "u", atspi_role);
574 static Eldbus_Message *
575 _accessible_get_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
577 const char *role_name = NULL, *obj_path = eldbus_message_path_get(msg);
578 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
579 Eo *obj = _bridge_object_from_path(bridge, obj_path);
581 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
583 eo_do(obj, role_name = elm_interface_atspi_accessible_role_name_get());
585 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
586 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
587 eldbus_message_arguments_append(ret, "s", role_name);
592 static Eldbus_Message *
593 _accessible_get_localized_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
595 const char *l_role_name = NULL, *obj_path = eldbus_message_path_get(msg);
596 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
597 Eo *obj = _bridge_object_from_path(bridge, obj_path);
599 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
601 eo_do(obj, l_role_name = elm_interface_atspi_accessible_localized_role_name_get());
602 EINA_SAFETY_ON_NULL_RETURN_VAL(l_role_name, NULL);
604 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
605 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
606 eldbus_message_arguments_append(ret, "s", l_role_name);
611 static Eldbus_Message *
612 _accessible_get_children(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
614 const char *obj_path = eldbus_message_path_get(msg);
615 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
616 Eo *obj = _bridge_object_from_path(bridge, obj_path);
617 Eina_List *children_list = NULL, *l;
619 Eldbus_Message_Iter *iter, *iter_array;
622 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
624 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
626 ret = eldbus_message_method_return_new(msg);
627 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
629 iter = eldbus_message_iter_get(ret);
630 iter_array = eldbus_message_iter_container_new(iter, 'a', "(so)");
631 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
633 EINA_LIST_FOREACH(children_list, l, children)
635 _bridge_iter_object_reference_append(bridge, iter_array, children);
636 _bridge_object_register(bridge, children);
639 eldbus_message_iter_container_close(iter, iter_array);
640 eina_list_free(children_list);
645 if (ret) eldbus_message_unref(ret);
649 static Eldbus_Message *
650 _accessible_get_application(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
653 const char *obj_path = eldbus_message_path_get(msg);
654 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
655 Eo *obj = _bridge_object_from_path(bridge, obj_path);
657 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
659 ret = eldbus_message_method_return_new(msg);
660 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
662 Eldbus_Message_Iter *iter = eldbus_message_iter_get(ret);
663 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
668 static Eldbus_Message *
669 _accessible_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
671 Eina_List *attrs, *l;
672 Elm_Atspi_Attribute *attr;
673 Eldbus_Message_Iter *iter, *iter_dict, *iter_entry;
676 const char *obj_path = eldbus_message_path_get(msg);
677 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
678 Eo *obj = _bridge_object_from_path(bridge, obj_path);
680 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
682 ret = eldbus_message_method_return_new(msg);
683 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
685 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
687 iter = eldbus_message_iter_get(ret);
688 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
689 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
691 EINA_LIST_FOREACH(attrs, l, attr)
693 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
694 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
695 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
696 eldbus_message_iter_container_close(iter_dict, iter_entry);
699 eldbus_message_iter_container_close(iter, iter_dict);
700 elm_atspi_attributes_list_free(attrs);
705 static Eldbus_Message *
706 _accessible_interfaces_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
709 Eldbus_Message_Iter *iter;
710 const char *obj_path = eldbus_message_path_get(msg);
711 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
712 Eo *obj = _bridge_object_from_path(bridge, obj_path);
714 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
716 ret = eldbus_message_method_return_new(msg);
717 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
719 iter = eldbus_message_iter_get(ret);
720 _iter_interfaces_append(iter, obj);
726 _elm_atspi_state_set_to_atspi_state_set(Elm_Atspi_State_Set states)
731 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
733 if (STATE_TYPE_GET(states, elm_states_to_atspi_state[i].elm_state))
734 STATE_TYPE_SET(ret, elm_states_to_atspi_state[i].atspi_state);
739 static Elm_Atspi_State_Set
740 _atspi_state_set_to_elm_atspi_state_set(uint64_t states)
742 //Currently Elm_Atspi_State and Atspi_State_Set are binary compatible,
743 //implement proper coversion when it will be needed.
744 Elm_Atspi_State_Set ret = states;
749 _elm_atspi_state_hash_build(void)
751 Eina_Hash *ret = eina_hash_string_superfast_new(NULL);
754 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
755 eina_hash_add(ret, elm_states_to_atspi_state[i].name, &elm_states_to_atspi_state[i]);
761 _elm_atspi_event_hash_build(void)
763 Eina_Hash *ret = eina_hash_pointer_new(NULL);
766 for (i = 0; i < SIZE(event_handlers); i++)
767 eina_hash_add(ret, &(event_handlers[i].desc), event_handlers[i].callback);
772 static Eldbus_Message *
773 _accessible_get_state(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
776 Eldbus_Message_Iter *iter, *iter_array;
777 Elm_Atspi_State_Set states;
778 uint64_t atspi_states = 0;
780 const char *obj_path = eldbus_message_path_get(msg);
781 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
782 Eo *obj = _bridge_object_from_path(bridge, obj_path);
784 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
786 ret = eldbus_message_method_return_new(msg);
787 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
789 iter = eldbus_message_iter_get(ret);
790 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
791 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
793 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
795 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
797 unsigned int s1 = atspi_states & 0xFFFFFFFF;
798 unsigned int s2 = (atspi_states >> 32) & 0xFFFFFFFF;
800 eldbus_message_iter_basic_append(iter_array, 'u', s1);
801 eldbus_message_iter_basic_append(iter_array, 'u', s2);
802 eldbus_message_iter_container_close(iter, iter_array);
807 if (ret) eldbus_message_unref(ret);
811 static Eldbus_Message *
812 _accessible_get_index_in_parent(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
814 const char *obj_path = eldbus_message_path_get(msg);
815 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
816 Eo *obj = _bridge_object_from_path(bridge, obj_path);
820 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
822 ret = eldbus_message_method_return_new(msg);
823 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
825 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
827 eldbus_message_arguments_append(ret, "i", idx);
832 static Eldbus_Message *
833 _accessible_child_at_index(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
835 const char *obj_path = eldbus_message_path_get(msg);
836 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
837 Eo *obj = _bridge_object_from_path(bridge, obj_path);
839 Eina_List *children = NULL;
842 Eldbus_Message_Iter *iter;
844 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
846 if (!eldbus_message_arguments_get(msg, "i", &idx))
847 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
849 ret = eldbus_message_method_return_new(msg);
850 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
852 iter = eldbus_message_iter_get(ret);
853 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
855 child = eina_list_nth(children, idx);
856 _bridge_iter_object_reference_append(bridge, iter, child);
857 _bridge_object_register(bridge, child);
858 eina_list_free(children);
863 static Eldbus_Message *
864 _accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
866 const char *obj_path = eldbus_message_path_get(msg);
867 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
868 Eo *rel_obj, *obj = _bridge_object_from_path(bridge, obj_path);
869 Eldbus_Message *ret = NULL;
870 Eldbus_Message_Iter *iter = NULL, *iter_array = NULL, *iter_array2 = NULL, *iter_struct;
871 Elm_Atspi_Relation *rel;
873 Elm_Atspi_Relation_Set rels;
875 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
877 ret = eldbus_message_method_return_new(msg);
878 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
880 iter = eldbus_message_iter_get(ret);
881 iter_array = eldbus_message_iter_container_new(iter, 'a', "(ua(so))");
882 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
884 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
886 EINA_LIST_FOREACH(rels, l, rel)
888 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
889 eldbus_message_iter_basic_append(iter_struct, 'u', _elm_relation_to_atspi_relation(rel->type));
890 iter_array2 = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
891 EINA_SAFETY_ON_NULL_GOTO(iter_array2, fail);
892 EINA_LIST_FOREACH(rel->objects, l2, rel_obj)
894 _bridge_iter_object_reference_append(bridge, iter_array2, rel_obj);
895 _bridge_object_register(bridge, rel_obj);
897 eldbus_message_iter_container_close(iter_struct, iter_array2);
898 eldbus_message_iter_container_close(iter_array, iter_struct);
900 elm_atspi_relation_set_free(&rels);
901 eldbus_message_iter_container_close(iter, iter_array);
906 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get relation set.");
909 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
910 static Eldbus_Message *
911 _accessible_gesture_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
913 const char *obj_path = eldbus_message_path_get(msg);
914 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
915 Eo *obj = _bridge_object_from_path(bridge, obj_path);
916 int type, x_beg, y_beg, x_end, y_end, state;
917 unsigned int event_time;
919 Eina_Bool result = EINA_FALSE;
921 if (!eldbus_message_arguments_get(msg, "iiiiiiu", &type, &x_beg, &y_beg,
922 &x_end, &y_end, &state, &event_time))
923 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
925 ret = eldbus_message_method_return_new(msg);
926 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
928 Elm_Atspi_Gesture_Info gesture_info;
929 gesture_info.type = (Elm_Atspi_Gesture_Type)type;
930 gesture_info.x_beg = x_beg;
931 gesture_info.y_beg = y_beg;
932 gesture_info.x_end = x_end;
933 gesture_info.y_end = y_end;
934 gesture_info.state = (Elm_Atspi_Gesture_State)state;
935 gesture_info.event_time = event_time;
936 eo_do(obj, result = elm_interface_atspi_accessible_gesture_do(gesture_info));
937 eldbus_message_arguments_append(ret, "b", result);
942 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
943 static Eldbus_Message *
944 _accessible_get_neighbor(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
946 const char *start_path = eldbus_message_path_get(msg);
947 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
948 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
949 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
951 Eo *start = _bridge_object_from_path(bridge, start_path);
953 Eldbus_Message_Iter *iter;
954 int direction, search_mode;
956 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(start, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
958 char *root_path = "";
959 if (!eldbus_message_arguments_get(msg, "sii", &root_path, &direction, &search_mode))
960 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
962 Eo *root = _bridge_object_from_path(bridge, root_path);
964 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
967 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(root));
968 if (ecore_evas_obscured_get(ee))
969 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
973 ret = eldbus_message_method_return_new(msg);
974 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
976 iter = eldbus_message_iter_get(ret);
978 Eo *accessible = _calculate_neighbor(bridge, root, start, direction == 1, search_mode);
979 _bridge_iter_object_reference_append(bridge, iter, accessible);
980 _bridge_object_register(bridge, accessible);
982 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
983 _object_get_bus_name_and_path(bridge, start, &obj_bus_name, NULL);
984 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
986 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
987 eldbus_message_iter_basic_append(iter, 'y', recurse);
991 static Eldbus_Message *
992 _accessible_get_navigable_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
994 const char *obj_path = eldbus_message_path_get(msg);
995 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
996 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
997 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
999 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1001 Eldbus_Message *ret;
1002 AtspiCoordType coord_type;
1003 Eldbus_Message_Iter *iter;
1005 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1007 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
1008 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
1009 if (ecore_evas_obscured_get(ee))
1010 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
1013 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
1014 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1016 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
1017 Evas_Object *top = elm_object_top_widget_get(obj);
1020 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
1025 ret = eldbus_message_method_return_new(msg);
1026 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1028 iter = eldbus_message_iter_get(ret);
1030 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1031 Eo *accessible = _calculate_navigable_accessible_at_point(bridge, obj, type, x, y);
1035 if (accessible && eo_isa(accessible, ELM_ACCESS_CLASS))
1037 Evas_Object *parent = elm_widget_parent_get(accessible);
1039 Elm_Widget_Smart_Data *wd;
1040 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
1044 Evas_Object *widget;
1046 EINA_LIST_FOREACH(wd->subobjs, l, widget)
1050 proxy = evas_object_data_get(widget, "__widget_proxy");
1054 evas_object_geometry_get(widget, &px, &py, &pw, &ph);
1055 if (x >= px && x <= px + pw && y >= py && y <= py +ph)
1057 /* proxy is also selectable */
1058 deputy = accessible;
1067 _bridge_iter_object_reference_append(bridge, iter, accessible);
1068 _bridge_object_register(bridge, accessible);
1070 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
1071 _object_get_bus_name_and_path(bridge, obj, &obj_bus_name, NULL);
1072 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
1073 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
1074 eldbus_message_iter_basic_append(iter, 'y', recurse);
1077 _bridge_iter_object_reference_append(bridge, iter, deputy);
1078 if (deputy) _bridge_object_register(bridge, deputy);
1084 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1086 _list_children_count_check(Eo *obj)
1090 Eina_List *children;
1092 Elm_Atspi_Role role;
1097 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1098 if (role == ELM_ATSPI_ROLE_LIST)
1100 int children_count = 0;
1101 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1102 children_count = eina_list_count(children);
1104 for (i = 0; i < children_count; i++)
1106 child = eina_list_nth(children, i);
1107 eo_do(child, role = elm_interface_atspi_accessible_role_get());
1108 if (role == ELM_ATSPI_ROLE_LIST_ITEM)
1111 eina_list_free(children);
1118 _list_children_count(Eo *obj)
1120 Eina_List *children;
1121 int list_items_count = 0;
1122 int children_count = 0;
1124 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1125 children_count = eina_list_count(children);
1130 list_items_count = _list_children_count_check(obj);
1131 if (list_items_count > 0)
1133 eina_list_free(children);
1134 return list_items_count;
1137 for (i = 0; i < children_count; i++)
1139 child = eina_list_nth(children, i);
1140 list_items_count = _list_children_count(child);
1141 if (list_items_count > 0)
1143 eina_list_free(children);
1144 return list_items_count;
1151 static Eldbus_Message *
1152 _accessible_reading_material_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1154 Eldbus_Message *ret;
1155 Eldbus_Message_Iter *iter, *iter_array, *iter_dict, *iter_entry;
1156 Eina_List *attrs, *l, *children;
1157 const char *name = NULL;
1158 unsigned int s1, s2;
1160 double increment = 0;
1161 double max_value = 0;
1162 double min_value = 0;
1164 int child_count = 0;
1165 int selected_child_count = 0;
1166 uint64_t atspi_states = 0;
1167 Elm_Atspi_Role role;
1168 Elm_Atspi_Attribute *attr;
1169 Elm_Atspi_State_Set states;
1170 Elm_Atspi_Relation_Set rels = NULL;
1171 Elm_Atspi_Relation *rel;
1172 Eo *relation_obj = NULL;
1175 Eina_Bool is_selected = EINA_FALSE;
1176 AtspiRole atspi_role = ATSPI_ROLE_INVALID;
1178 const char *obj_path = eldbus_message_path_get(msg);
1179 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1180 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1182 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1184 ret = eldbus_message_method_return_new(msg);
1185 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1187 iter = eldbus_message_iter_get(ret);
1189 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
1190 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
1191 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
1192 EINA_LIST_FOREACH(attrs, l, attr)
1194 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
1195 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
1196 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
1197 eldbus_message_iter_container_close(iter_dict, iter_entry);
1200 eldbus_message_iter_container_close(iter, iter_dict);
1201 elm_atspi_attributes_list_free(attrs);
1204 eo_do(obj, name = elm_interface_atspi_accessible_name_get());
1207 eldbus_message_iter_basic_append(iter, 's', name);
1209 /* name - LABELED_BY relation */
1210 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
1211 EINA_LIST_FOREACH(rels, l, rel)
1213 if (rel->type == ELM_ATSPI_RELATION_LABELLED_BY)
1215 int last_index = eina_list_count(rel->objects) - 1;
1216 relation_obj = eina_list_nth(rel->objects, last_index);
1220 eo_do(relation_obj, name = elm_interface_atspi_accessible_name_get());
1223 eldbus_message_iter_basic_append(iter, 's', name);
1225 /* name - text interface */
1227 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
1230 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
1231 eo_do(obj, name = elm_interface_atspi_text_get(0, val));
1235 eldbus_message_iter_basic_append(iter, 's', name);
1238 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1239 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1240 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1243 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1244 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1245 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1246 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1247 s1 = atspi_states & 0xFFFFFFFF;
1248 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1249 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1250 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1251 eldbus_message_iter_container_close(iter, iter_array);
1253 /* localized role name */
1254 eo_do(obj, name = elm_interface_atspi_accessible_localized_role_name_get());
1257 eldbus_message_iter_basic_append(iter, 's', name);
1260 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
1261 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1264 /* current value, increment, max, min */
1269 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
1271 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
1272 eo_do(obj, increment = elm_interface_atspi_value_increment_get());
1273 eo_do(obj, elm_interface_atspi_value_range_get(&min_value, &max_value, NULL));
1275 eldbus_message_iter_basic_append(iter, 'd', value);
1276 eldbus_message_iter_basic_append(iter, 'd', increment);
1277 eldbus_message_iter_basic_append(iter, 'd', max_value);
1278 eldbus_message_iter_basic_append(iter, 'd', min_value);
1281 eo_do(obj, name = elm_interface_atspi_accessible_description_get());
1284 eldbus_message_iter_basic_append(iter, 's', name);
1286 /* index in parent */
1287 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
1288 eldbus_message_iter_basic_append(iter, 'i', idx);
1290 /* is selected in parent */
1291 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
1292 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1294 eo_do(parent, is_selected = elm_interface_atspi_selection_is_child_selected(idx));
1296 eldbus_message_arguments_append(ret, "b", is_selected);
1298 /* has checkbox child */
1299 is_selected = EINA_FALSE;
1300 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1301 EINA_LIST_FOREACH(children, l, child)
1303 if (eo_isa(child, ELM_CHECK_CLASS))
1305 is_selected = EINA_TRUE;
1309 eldbus_message_iter_basic_append(iter, 'b', is_selected);
1310 eina_list_free(children);
1312 /* list children count */
1314 if (role == ELM_ATSPI_ROLE_DIALOG)
1316 child_count = _list_children_count(obj);
1318 eldbus_message_iter_basic_append(iter, 'i', child_count);
1320 /* first selected child index */
1322 if (eo_isa(obj, ELM_INDEX_CLASS))
1324 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1325 EINA_LIST_FOREACH(children, l, child)
1327 eo_do(child, states = elm_interface_atspi_accessible_state_set_get());
1328 if (STATE_TYPE_GET(states, ELM_ATSPI_STATE_SELECTED))
1332 eina_list_free(children);
1334 eldbus_message_iter_basic_append(iter, 'i', idx);
1337 role = ELM_ATSPI_ROLE_INVALID;
1338 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1339 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
1340 _object_desktop_reference_append(iter);
1342 _bridge_iter_object_reference_append(bridge, iter, parent);
1344 /* parent - states */
1345 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1346 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1347 eo_do(parent, states = elm_interface_atspi_accessible_state_set_get());
1348 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1349 s1 = atspi_states & 0xFFFFFFFF;
1350 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1351 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1352 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1353 eldbus_message_iter_container_close(iter, iter_array);
1355 /* parent - child count */
1356 eo_do(parent, l = elm_interface_atspi_accessible_children_get());
1357 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1361 eo_do(parent, role = elm_interface_atspi_accessible_role_get());
1362 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1363 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1365 /* parent - child count */
1366 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1368 eo_do(parent, selected_child_count = elm_interface_atspi_selection_selected_children_count_get());
1370 eldbus_message_iter_basic_append(iter, 'i', selected_child_count);
1372 /* relation object - DESCRIBED_BY */
1373 relation_obj = NULL;
1374 EINA_LIST_FOREACH(rels, l, rel)
1376 if (rel->type == ELM_ATSPI_RELATION_DESCRIBED_BY)
1378 int last_index = eina_list_count(rel->objects) - 1;
1379 relation_obj = eina_list_nth(rel->objects, last_index);
1383 _bridge_iter_object_reference_append(bridge, iter, relation_obj);
1384 elm_atspi_relation_set_free(&rels);
1389 if (rels) elm_atspi_relation_set_free(&rels);
1390 if (ret) eldbus_message_unref(ret);
1395 static const Eldbus_Method accessible_methods[] = {
1396 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
1397 { "GetNavigableAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)y", "accessible"}, {"(so)", "deputy"}), _accessible_get_navigable_at_point, 0 },
1398 { "GetNeighbor", ELDBUS_ARGS({"s", "current"}, {"i", "direction"}, {"i", "force_next"}), ELDBUS_ARGS({"(so)y", "accessible"}), _accessible_get_neighbor, 0 },
1400 { "GetChildAtIndex", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"(so)", "Accessible"}), _accessible_child_at_index, 0 },
1401 { "GetChildren", NULL, ELDBUS_ARGS({"a(so)", "children"}), _accessible_get_children, 0 },
1402 { "GetIndexInParent", NULL, ELDBUS_ARGS({"i", "index"}), _accessible_get_index_in_parent, 0 },
1403 { "GetRelationSet", NULL, ELDBUS_ARGS({"a(ua(so))", NULL}), _accessible_get_relation_set, 0 },
1404 { "GetRole", NULL, ELDBUS_ARGS({"u", "Role"}), _accessible_get_role, 0 },
1405 { "GetRoleName", NULL, ELDBUS_ARGS({"s", "Name"}), _accessible_get_role_name, 0 },
1406 { "GetLocalizedRoleName", NULL, ELDBUS_ARGS({"s", "LocalizedName"}), _accessible_get_localized_role_name, 0},
1407 { "GetState", NULL, ELDBUS_ARGS({"au", NULL}), _accessible_get_state, 0},
1408 { "GetApplication", NULL, ELDBUS_ARGS({"(so)", NULL}), _accessible_get_application, 0},
1409 { "GetAttributes", NULL, ELDBUS_ARGS({"a{ss}", NULL}), _accessible_attributes_get, 0},
1410 { "GetInterfaces", NULL, ELDBUS_ARGS({"as", NULL}), _accessible_interfaces_get, 0},
1411 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
1413 ELDBUS_ARGS({"i", "type"}, {"i", "x_beg"}, {"i", "y_beg"},
1414 {"i", "x_end"}, {"i", "y_end"}, {"i", "state"},
1415 {"u", "event_time"}),
1416 ELDBUS_ARGS({"b", "result"}), _accessible_gesture_do, 0},
1418 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1419 { "GetReadingMaterial",
1421 ELDBUS_ARGS({"a{ss}", "attributes"}, {"s", "name"},
1422 {"s", "labledByName"},{"s", "textIfceName"},
1423 {"u", "role"}, {"au", "stateSet"},
1424 {"s", "localizedName"}, {"i", "childCount"},
1425 {"d", "currentValue"},{"d", "minimumIncrement"},
1426 {"d", "maximumValue"},{"d", "minimumValue"},
1427 {"s", "description"}, {"i", "indexInParent"},
1428 {"b", "isSelectedInParent"}, {"b", "hasCheckboxChild"},
1429 {"i", "listChildrenCount"},
1430 {"i", "firstSelectedChildIndex"},
1431 {"(so)", "parent"}, {"au", "parentStateSet"},
1432 {"i", "parentChildCount"}, {"u", "parentRole"},
1433 {"i", "selectedChildCount"},
1434 {"(so)", "describecByObject"}),
1435 _accessible_reading_material_get, 0},
1437 { NULL, NULL, NULL, NULL, 0 }
1441 _is_operation_permitted(Eo *obj)
1443 Elm_Atspi_State_Set states;
1444 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1446 if (!STATE_TYPE_GET(states, ELM_ATSPI_STATE_SHOWING)) return EINA_FALSE;
1451 if (evas_object_freeze_events_get(parent)) return EINA_FALSE;
1452 parent = evas_object_smart_parent_get(parent);
1457 static Eldbus_Message *
1458 _selection_selected_child_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1460 const char *obj_path = eldbus_message_path_get(msg);
1461 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1462 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1466 Eldbus_Message *ret;
1467 Eldbus_Message_Iter *iter;
1469 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1471 if (!eldbus_message_arguments_get(msg, "i", &idx))
1472 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1474 ret = eldbus_message_method_return_new(msg);
1475 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1477 iter = eldbus_message_iter_get(ret);
1478 eo_do(obj, child = elm_interface_atspi_selection_selected_child_get(idx));
1480 _bridge_iter_object_reference_append(bridge, iter, child);
1481 _bridge_object_register(bridge, child);
1486 static Eldbus_Message *
1487 _selection_child_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1489 const char *obj_path = eldbus_message_path_get(msg);
1490 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1491 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1493 Eldbus_Message *ret;
1494 Eina_Bool result = EINA_FALSE;
1496 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1498 if (!eldbus_message_arguments_get(msg, "i", &idx))
1499 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1501 ret = eldbus_message_method_return_new(msg);
1502 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1504 if (_is_operation_permitted(obj))
1505 eo_do(obj, result = elm_interface_atspi_selection_child_select(idx));
1506 eldbus_message_arguments_append(ret, "b", result);
1511 static Eldbus_Message *
1512 _selection_selected_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1514 const char *obj_path = eldbus_message_path_get(msg);
1515 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1516 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1518 Eldbus_Message *ret;
1519 Eina_Bool result = EINA_FALSE;
1521 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1523 if (!eldbus_message_arguments_get(msg, "i", &idx))
1524 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1526 ret = eldbus_message_method_return_new(msg);
1527 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1529 if (_is_operation_permitted(obj))
1530 eo_do(obj, result = elm_interface_atspi_selection_selected_child_deselect(idx));
1531 eldbus_message_arguments_append(ret, "b", result);
1536 static Eldbus_Message *
1537 _selection_is_child_selected(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1539 const char *obj_path = eldbus_message_path_get(msg);
1540 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1541 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1543 Eldbus_Message *ret;
1546 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1548 if (!eldbus_message_arguments_get(msg, "i", &idx))
1549 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1551 ret = eldbus_message_method_return_new(msg);
1552 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1554 eo_do(obj, result = elm_interface_atspi_selection_is_child_selected(idx));
1555 eldbus_message_arguments_append(ret, "b", result);
1560 static Eldbus_Message *
1561 _selection_all_children_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1563 const char *obj_path = eldbus_message_path_get(msg);
1564 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1565 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1566 Eldbus_Message *ret;
1567 Eina_Bool result = EINA_FALSE;
1569 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1571 ret = eldbus_message_method_return_new(msg);
1572 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1574 if (_is_operation_permitted(obj))
1575 eo_do(obj, result = elm_interface_atspi_selection_all_children_select());
1576 eldbus_message_arguments_append(ret, "b", result);
1581 static Eldbus_Message *
1582 _selection_clear(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1584 const char *obj_path = eldbus_message_path_get(msg);
1585 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1586 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1587 Eldbus_Message *ret;
1588 Eina_Bool result = EINA_FALSE;
1590 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1592 ret = eldbus_message_method_return_new(msg);
1593 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1595 if (_is_operation_permitted(obj))
1596 eo_do(obj, result = elm_interface_atspi_selection_clear());
1597 eldbus_message_arguments_append(ret, "b", result);
1602 static Eldbus_Message *
1603 _selection_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1605 const char *obj_path = eldbus_message_path_get(msg);
1606 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1607 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1609 Eldbus_Message *ret;
1610 Eina_Bool result = EINA_FALSE;
1612 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1614 if (!eldbus_message_arguments_get(msg, "i", &idx))
1615 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
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_child_deselect(idx));
1622 eldbus_message_arguments_append(ret, "b", result);
1627 static const Eldbus_Method selection_methods[] = {
1628 { "GetSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"(so)", "Accessible"}), _selection_selected_child_get, 0 },
1629 { "SelectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_select, 0 },
1630 { "DeselectSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_selected_child_deselect, 0 },
1631 { "IsChildSelected", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_is_child_selected, 0 },
1632 { "SelectAll", NULL, ELDBUS_ARGS({"b", "result"}), _selection_all_children_select, 0},
1633 { "ClearSelection", NULL, ELDBUS_ARGS({"b", "result"}), _selection_clear, 0},
1634 { "DeselectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_deselect, 0 },
1635 { NULL, NULL, NULL, NULL, 0 }
1638 static Eldbus_Message *
1639 _action_description_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1641 const char *description, *obj_path = eldbus_message_path_get(msg);
1642 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1643 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1645 Eldbus_Message *ret;
1647 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1649 if (!eldbus_message_arguments_get(msg, "i", &idx))
1650 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1652 ret = eldbus_message_method_return_new(msg);
1653 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1655 eo_do(obj, description = elm_interface_atspi_action_description_get(idx));
1656 description = description ? description : "";
1657 eldbus_message_arguments_append(ret, "s", description);
1662 static Eldbus_Message *
1663 _action_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1665 const char *name, *obj_path = eldbus_message_path_get(msg);
1666 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1667 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1669 Eldbus_Message *ret;
1671 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1673 if (!eldbus_message_arguments_get(msg, "i", &idx))
1674 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1676 ret = eldbus_message_method_return_new(msg);
1677 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1679 eo_do(obj, name = elm_interface_atspi_action_name_get(idx));
1680 name = name ? name : "";
1681 eldbus_message_arguments_append(ret, "s", name);
1686 static Eldbus_Message *
1687 _action_localized_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1689 const char *name, *obj_path = eldbus_message_path_get(msg);
1690 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1691 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1693 Eldbus_Message *ret;
1695 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1697 if (!eldbus_message_arguments_get(msg, "i", &idx))
1698 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1700 ret = eldbus_message_method_return_new(msg);
1701 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1703 eo_do(obj, name = elm_interface_atspi_action_localized_name_get(idx));
1704 name = name ? name : "";
1705 eldbus_message_arguments_append(ret, "s", name);
1710 static Eldbus_Message *
1711 _action_key_binding_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1713 const char *obj_path = eldbus_message_path_get(msg);
1715 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1716 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1718 Eldbus_Message *ret;
1720 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1722 if (!eldbus_message_arguments_get(msg, "i", &idx))
1723 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1725 ret = eldbus_message_method_return_new(msg);
1726 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1728 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(idx));
1729 eldbus_message_arguments_append(ret, "s", key ? key : "");
1735 static Eldbus_Message *
1736 _action_actions_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1738 const char *action, *obj_path = eldbus_message_path_get(msg);
1739 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1740 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1742 Eldbus_Message *ret;
1743 Eldbus_Message_Iter *iter, *iter_array;
1745 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1747 ret = eldbus_message_method_return_new(msg);
1748 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1750 iter = eldbus_message_iter_get(ret);
1751 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
1753 iter_array = eldbus_message_iter_container_new(iter, 'a', "sss");
1754 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_array, NULL);
1756 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1759 EINA_LIST_FREE(actions, action)
1763 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(id));
1764 eo_do(obj, descr = elm_interface_atspi_action_description_get(id));
1765 descr = descr ? descr : "";
1766 eldbus_message_iter_arguments_append(iter_array, "sss", action, descr, key ? key : "");
1771 eldbus_message_iter_container_close(iter, iter_array);
1776 static Eldbus_Message *
1777 _action_action_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1779 const char *obj_path = eldbus_message_path_get(msg);
1780 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1781 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1783 Eldbus_Message *ret;
1784 Eina_Bool result = EINA_FALSE;
1786 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1788 if (!eldbus_message_arguments_get(msg, "i", &idx))
1789 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1791 ret = eldbus_message_method_return_new(msg);
1792 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1794 if (_is_operation_permitted(obj))
1795 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1797 eldbus_message_arguments_append(ret, "b", result);
1802 static Eldbus_Message *
1803 _action_action_name_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1805 const char *obj_path = eldbus_message_path_get(msg);
1806 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1807 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1812 Eldbus_Message *ret;
1813 Eina_Bool result = EINA_FALSE;
1815 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1817 if (!eldbus_message_arguments_get(msg, "s", &action_name))
1818 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1820 ret = eldbus_message_method_return_new(msg);
1821 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1823 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1824 EINA_LIST_FREE(actions, action)
1826 if (!result && action && !strcmp(action, action_name))
1834 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1836 eldbus_message_arguments_append(ret, "b", result);
1841 static const Eldbus_Method action_methods[] = {
1842 { "GetDescription", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "description"}), _action_description_get, 0 },
1843 { "GetName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_name_get, 0 },
1844 { "GetLocalizedName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_localized_name_get, 0 },
1845 { "GetKeyBinding", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "key"}), _action_key_binding_get, 0 },
1846 { "GetActions", NULL, ELDBUS_ARGS({"a(sss)", "actions"}), _action_actions_get, 0 },
1847 { "DoAction", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"b", "result"}), _action_action_do, 0 },
1848 { "DoActionName", ELDBUS_ARGS({"s", "name"}), ELDBUS_ARGS({"b", "result"}), _action_action_name_do, 0 },
1849 { NULL, NULL, NULL, NULL, 0 }
1852 static Eldbus_Message *
1853 _image_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1855 AtspiCoordType type;
1856 Eldbus_Message *ret;
1857 const char *obj_path = eldbus_message_path_get(msg);
1859 Eina_Bool screen_coords;
1860 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1861 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1865 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1867 if (!eldbus_message_arguments_get(msg, "u", &type))
1868 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1870 ret = eldbus_message_method_return_new(msg);
1871 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1873 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1874 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, &w, &h));
1875 eldbus_message_arguments_append(ret, "iiii", x, y, w, h);
1880 static Eldbus_Message *
1881 _image_position_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1883 AtspiCoordType type;
1884 Eldbus_Message *ret;
1885 const char *obj_path = eldbus_message_path_get(msg);
1886 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1887 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1889 Eina_Bool screen_coords;
1891 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1893 if (!eldbus_message_arguments_get(msg, "u", &type))
1894 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1896 ret = eldbus_message_method_return_new(msg);
1897 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1899 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1900 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, NULL, NULL));
1901 eldbus_message_arguments_append(ret, "i", x);
1902 eldbus_message_arguments_append(ret, "i", y);
1907 static Eldbus_Message *
1908 _image_size_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1910 Eldbus_Message *ret;
1911 const char *obj_path = eldbus_message_path_get(msg);
1912 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1913 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1916 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1918 ret = eldbus_message_method_return_new(msg);
1919 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1921 eo_do(obj, elm_interface_atspi_image_extents_get(EINA_FALSE, NULL, NULL, &w, &h));
1922 eldbus_message_arguments_append(ret, "i", w);
1923 eldbus_message_arguments_append(ret, "i", h);
1928 static const Eldbus_Method image_methods[] = {
1929 { "GetImageExtents", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"iiii", "extents"}), _image_extents_get, 0 },
1930 { "GetImagePosition", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}), _image_position_get, 0 },
1931 { "GetImageSize", NULL, ELDBUS_ARGS({"i", "width"}, {"i", "height"}), _image_size_get, 0 },
1932 { NULL, NULL, NULL, NULL, 0 }
1935 static Eldbus_Message *
1936 _text_string_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1938 const char *obj_path = eldbus_message_path_get(msg);
1940 Elm_Atspi_Text_Granularity gran;
1942 Eldbus_Message *ret;
1943 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1944 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1946 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
1948 if (!eldbus_message_arguments_get(msg, "iu", &start, &gran))
1949 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
1951 ret = eldbus_message_method_return_new(msg);
1952 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1954 eo_do(obj, str = elm_interface_atspi_text_string_get(gran, &start, &end));
1955 str = str ? str : strdup("");
1957 eldbus_message_arguments_append(ret, "sii", str, start, end);
1963 static Eldbus_Message *
1964 _text_text_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1966 const char *obj_path = eldbus_message_path_get(msg);
1968 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1969 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1972 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
1974 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
1975 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
1977 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
1978 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1980 eo_do(obj, str = elm_interface_atspi_text_get(start, end));
1981 str = str ? str : strdup("");
1983 eldbus_message_arguments_append(ret, "s", str);
1989 static Eldbus_Message *
1990 _text_caret_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1992 const char *obj_path = eldbus_message_path_get(msg);
1993 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1994 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1996 Eldbus_Message *ret;
1999 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2001 if (!eldbus_message_arguments_get(msg, "i", &offset))
2002 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2004 ret = eldbus_message_method_return_new(msg);
2005 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2007 eo_do(obj, res = elm_interface_atspi_text_caret_offset_set(offset));
2009 eldbus_message_arguments_append(ret, "b", res);
2014 static Eldbus_Message *
2015 _text_character_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2017 const char *obj_path = eldbus_message_path_get(msg);
2018 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2019 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2021 Eldbus_Message *ret;
2024 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2026 if (!eldbus_message_arguments_get(msg, "i", &offset))
2027 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2029 ret = eldbus_message_method_return_new(msg);
2030 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2032 eo_do(obj, res = elm_interface_atspi_text_character_get(offset));
2034 eldbus_message_arguments_append(ret, "i", res);
2039 static Eldbus_Message *
2040 _text_attribute_value_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2042 const char *name, *obj_path = eldbus_message_path_get(msg);
2044 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2045 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2047 Eldbus_Message *ret;
2050 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2052 if (!eldbus_message_arguments_get(msg, "is", &start, &name))
2053 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and attribute name expected.");
2055 ret = eldbus_message_method_return_new(msg);
2056 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2058 eo_do(obj, res = elm_interface_atspi_text_attribute_get(name, &start, &end, &value));
2059 eldbus_message_arguments_append(ret, "siib", value ? value : "", start, end, res);
2061 if (value) free(value);
2065 static Eldbus_Message *
2066 _text_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2068 const char *obj_path = eldbus_message_path_get(msg);
2069 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2070 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2072 Eldbus_Message *ret;
2073 Eldbus_Message_Iter *iter, *iter_array;
2075 Elm_Atspi_Text_Attribute *attr;
2077 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2079 if (!eldbus_message_arguments_get(msg, "i", &start))
2080 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2082 ret = eldbus_message_method_return_new(msg);
2083 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2085 iter = eldbus_message_iter_get(ret);
2086 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2087 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2089 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2091 EINA_LIST_FREE(attrs, attr)
2093 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2094 elm_atspi_text_text_attribute_free(attr);
2097 eldbus_message_iter_container_close(iter, iter_array);
2098 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2103 if (ret) eldbus_message_unref(ret);
2107 static Eldbus_Message *
2108 _text_default_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2110 const char *obj_path = eldbus_message_path_get(msg);
2111 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2112 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2113 int start = -1, end;
2114 Eldbus_Message *ret;
2115 Eldbus_Message_Iter *iter, *iter_array;
2117 Elm_Atspi_Text_Attribute *attr;
2119 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2121 ret = eldbus_message_method_return_new(msg);
2122 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2124 iter = eldbus_message_iter_get(ret);
2125 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2126 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2128 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2130 EINA_LIST_FREE(attrs, attr)
2132 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2133 elm_atspi_text_text_attribute_free(attr);
2136 eldbus_message_iter_container_close(iter, iter_array);
2137 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2142 if (ret) eldbus_message_unref(ret);
2146 static Eldbus_Message *
2147 _text_character_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2149 const char *obj_path = eldbus_message_path_get(msg);
2150 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2151 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2153 Eina_Rectangle rect;
2154 AtspiCoordType type;
2155 Eina_Bool screen_coords, res;
2156 Eldbus_Message *ret;
2158 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2160 if (!eldbus_message_arguments_get(msg, "iu", &offset, &type))
2161 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2163 ret = eldbus_message_method_return_new(msg);
2164 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2166 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2168 eo_do(obj, res = elm_interface_atspi_text_character_extents_get(offset, screen_coords, &rect));
2172 eldbus_message_unref(ret);
2173 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get character extents.");
2175 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2180 static Eldbus_Message *
2181 _text_offset_at_point_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2183 const char *obj_path = eldbus_message_path_get(msg);
2184 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2185 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2187 AtspiCoordType type;
2188 Eina_Bool screen_coords;
2189 Eldbus_Message *ret;
2191 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2193 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &type))
2194 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2196 ret = eldbus_message_method_return_new(msg);
2197 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2200 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2202 eo_do(obj, offset = elm_interface_atspi_text_offset_at_point_get(screen_coords, x, y));
2204 eldbus_message_arguments_append(ret, "i", offset);
2209 static Eldbus_Message *
2210 _text_n_selections_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2212 const char *obj_path = eldbus_message_path_get(msg);
2213 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2214 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2216 Eldbus_Message *ret;
2218 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2220 ret = eldbus_message_method_return_new(msg);
2221 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2223 eo_do(obj, n = elm_interface_atspi_text_selections_count_get());
2225 eldbus_message_arguments_append(ret, "i", n);
2230 static Eldbus_Message *
2231 _text_selection_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2233 const char *obj_path = eldbus_message_path_get(msg);
2234 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2235 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2236 int sel_num, start, end;
2237 Eldbus_Message *ret;
2239 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2241 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2242 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2244 ret = eldbus_message_method_return_new(msg);
2245 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2247 eo_do(obj, elm_interface_atspi_text_selection_get(sel_num, &start, &end));
2249 eldbus_message_arguments_append(ret, "ii", start, end);
2254 static Eldbus_Message *
2255 _text_selection_add(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2257 const char *obj_path = eldbus_message_path_get(msg);
2258 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2259 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 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2267 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end text offset expected.");
2269 ret = eldbus_message_method_return_new(msg);
2270 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2272 eo_do(obj, res = elm_interface_atspi_text_selection_add(start, end));
2274 eldbus_message_arguments_append(ret, "b", res);
2279 static Eldbus_Message *
2280 _text_selection_remove(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2282 const char *obj_path = eldbus_message_path_get(msg);
2283 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2284 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2287 Eldbus_Message *ret;
2289 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2291 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2292 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2294 ret = eldbus_message_method_return_new(msg);
2295 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2297 eo_do(obj, res = elm_interface_atspi_text_selection_remove(sel_num));
2299 eldbus_message_arguments_append(ret, "b", res);
2304 static Eldbus_Message *
2305 _text_selection_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2307 const char *obj_path = eldbus_message_path_get(msg);
2308 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2309 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2310 int sel_num, start, end;
2312 Eldbus_Message *ret;
2314 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2316 if (!eldbus_message_arguments_get(msg, "iii", &sel_num, &start, &end))
2317 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2319 ret = eldbus_message_method_return_new(msg);
2320 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2322 eo_do(obj, res = elm_interface_atspi_text_selection_set(sel_num, start, end));
2324 eldbus_message_arguments_append(ret, "b", res);
2329 static Eldbus_Message *
2330 _text_range_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2332 const char *obj_path = eldbus_message_path_get(msg);
2333 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2334 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2336 Eina_Rectangle rect;
2337 Eina_Bool screen_coords, res;
2338 AtspiCoordType type;
2339 Eldbus_Message *ret;
2341 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2343 if (!eldbus_message_arguments_get(msg, "iiu", &start, &end, &type))
2344 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2346 ret = eldbus_message_method_return_new(msg);
2347 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2349 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2350 eo_do(obj, res = elm_interface_atspi_text_range_extents_get(screen_coords, start, end, &rect));
2353 eldbus_message_unref(ret);
2354 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Can't get range extents.");
2357 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2362 static Eldbus_Message *
2363 _text_bounded_ranges_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2365 const char *obj_path = eldbus_message_path_get(msg);
2366 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2367 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2368 Eina_Rectangle rect;
2369 Eina_Bool screen_coords;
2370 AtspiCoordType type;
2371 Elm_Atspi_Text_Clip_Type xclip, yclip;
2373 Eldbus_Message *ret;
2374 Elm_Atspi_Text_Range *range;
2375 Eldbus_Message_Iter *iter, *iter_array, *iter_struct, *iter_var;
2377 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2379 if (!eldbus_message_arguments_get(msg, "iiiiuuu", &rect.x, &rect.y, &rect.w, &rect.h, &type, &xclip, &yclip))
2380 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.");
2382 ret = eldbus_message_method_return_new(msg);
2383 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2385 iter = eldbus_message_iter_get(ret);
2386 iter_array = eldbus_message_iter_container_new(iter, 'a', "(iisv)");
2387 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2389 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2390 eo_do(obj, ranges = elm_interface_atspi_text_bounded_ranges_get(screen_coords, rect, xclip, yclip));
2392 EINA_LIST_FREE(ranges, range)
2394 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
2397 eldbus_message_iter_basic_append(iter_struct, 'i', range->start_offset);
2398 eldbus_message_iter_basic_append(iter_struct, 'i', range->end_offset);
2399 range->content = range->content ? range->content : strdup("");
2400 eldbus_message_iter_basic_append(iter_struct, 's', range->content);
2401 /* AT-SPI specification requires variant type in return, however
2402 * ATK or other implementations as well as AT Clients don't use it .
2403 * To cover spec a dummy value will be returned */
2404 iter_var = eldbus_message_iter_container_new(iter_struct, 'v', "i");
2407 eldbus_message_iter_basic_append(iter_var, 'i', 0);
2408 eldbus_message_iter_container_close(iter_struct, iter_var);
2410 eldbus_message_iter_container_close(iter_array, iter_struct);
2412 if (range->content) free(range->content);
2416 eldbus_message_iter_container_close(iter, iter_array);
2421 if (ret) eldbus_message_unref(ret);
2425 static Eldbus_Message *
2426 _text_run_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2428 const char *obj_path = eldbus_message_path_get(msg);
2429 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2430 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2432 Eldbus_Message *ret;
2433 Eldbus_Message_Iter *iter, *iter_array;
2434 Eina_List *attrs, *defaults;
2435 Elm_Atspi_Text_Attribute *attr;
2438 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2440 if (!eldbus_message_arguments_get(msg, "ib", &start, &incl_def))
2441 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and include defaults flag expected.");
2443 ret = eldbus_message_method_return_new(msg);
2444 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2446 iter = eldbus_message_iter_get(ret);
2447 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2448 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2450 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2454 eo_do(obj, defaults = elm_interface_atspi_text_default_attributes_get());
2455 attrs = eina_list_merge(attrs, defaults);
2458 EINA_LIST_FREE(attrs, attr)
2460 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2461 elm_atspi_text_text_attribute_free(attr);
2464 eldbus_message_iter_container_close(iter, iter_array);
2465 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2470 if (ret) eldbus_message_unref(ret);
2474 static const Eldbus_Method text_methods[] = {
2475 { "GetTextAtOffset", ELDBUS_ARGS({"i", "offset"}, {"u", "granularity"}), ELDBUS_ARGS({"s", "string"}, {"i", "startOffset"}, {"i", "endOffset"}), _text_string_at_offset_get, 0 },
2476 { "GetText", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"s", "string"}), _text_text_get, 0 },
2477 { "SetCaretOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"b", NULL}), _text_caret_offset_set, 0 },
2478 { "GetCharacterAtOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"i", NULL}), _text_character_at_offset_get, 0 },
2479 { "GetAttributeValue", ELDBUS_ARGS({"i", "offset"}, {"s", "attributeName"}), ELDBUS_ARGS({"s", NULL}, {"i", "startOffset"}, {"i", "endOffset"}, {"b", "defined"}), _text_attribute_value_get, 0 },
2480 { "GetAttributes", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_attributes_get, 0 },
2481 { "GetDefaultAttributes", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2482 { "GetCharacterExtents", ELDBUS_ARGS({"i", "offset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_character_extents_get, 0 },
2483 { "GetOffsetAtPoint", ELDBUS_ARGS({"i", "x"}, {"i","y"}, {"u", "coordType"}), ELDBUS_ARGS({"i", NULL}), _text_offset_at_point_get, 0 },
2484 { "GetNSelections", NULL, ELDBUS_ARGS({"i", NULL}), _text_n_selections_get, 0 },
2485 { "GetSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), _text_selection_get, 0 },
2486 { "AddSelection", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_add, 0 },
2487 { "RemoveSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"b", NULL}), _text_selection_remove, 0 },
2488 { "SetSelection", ELDBUS_ARGS({"i", "selectionNum"}, {"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_set, 0 },
2489 { "GetRangeExtents", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_range_extents_get, 0 },
2490 { "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 },
2491 { "GetAttributeRun", ELDBUS_ARGS({"i", "offset"}, {"b", "includeDefaults"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_run_attributes_get, 0 },
2492 { "GetDefaultAttributeSet", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2493 { NULL, NULL, NULL, NULL, 0 }
2496 static Eldbus_Message *
2497 _editable_text_text_content_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2499 const char *obj_path = eldbus_message_path_get(msg);
2500 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2501 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2502 const char *content;
2503 Eldbus_Message *ret;
2506 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2508 if (!eldbus_message_arguments_get(msg, "s", &content))
2509 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "String expected.");
2511 ret = eldbus_message_method_return_new(msg);
2512 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2514 eo_do(obj, res = elm_interface_atspi_editable_text_content_set(content));
2516 eldbus_message_arguments_append(ret, "b", res);
2521 static Eldbus_Message *
2522 _editable_text_text_insert(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2524 const char *obj_path = eldbus_message_path_get(msg);
2525 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2526 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2528 Eldbus_Message *ret;
2532 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2534 if (!eldbus_message_arguments_get(msg, "isi", &pos, &text, &len))
2535 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Postion, string, length expected.");
2537 ret = eldbus_message_method_return_new(msg);
2538 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2540 eo_do(obj, res = elm_interface_atspi_editable_text_insert(text, pos));
2542 eldbus_message_arguments_append(ret, "b", res);
2547 static Eldbus_Message *
2548 _editable_text_text_copy(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2550 const char *obj_path = eldbus_message_path_get(msg);
2551 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2552 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2553 Eldbus_Message *ret;
2557 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2559 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2560 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2562 ret = eldbus_message_method_return_new(msg);
2563 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2565 eo_do(obj, res = elm_interface_atspi_editable_text_copy(start, end));
2567 eldbus_message_arguments_append(ret, "b", res);
2572 static Eldbus_Message *
2573 _editable_text_text_cut(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2575 const char *obj_path = eldbus_message_path_get(msg);
2576 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2577 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2578 Eldbus_Message *ret;
2582 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2584 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2585 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2587 ret = eldbus_message_method_return_new(msg);
2588 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2590 eo_do(obj, res = elm_interface_atspi_editable_text_cut(start, end));
2592 eldbus_message_arguments_append(ret, "b", res);
2597 static Eldbus_Message *
2598 _editable_text_text_delete(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2600 const char *obj_path = eldbus_message_path_get(msg);
2601 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2602 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2603 Eldbus_Message *ret;
2607 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2609 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2610 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2612 ret = eldbus_message_method_return_new(msg);
2613 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2615 eo_do(obj, res = elm_interface_atspi_editable_text_delete(start, end));
2617 eldbus_message_arguments_append(ret, "b", res);
2622 static Eldbus_Message *
2623 _editable_text_text_paste(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2625 const char *obj_path = eldbus_message_path_get(msg);
2626 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2627 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2628 Eldbus_Message *ret;
2632 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2634 if (!eldbus_message_arguments_get(msg, "i", &pos))
2635 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2637 ret = eldbus_message_method_return_new(msg);
2638 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2640 eo_do(obj, res = elm_interface_atspi_editable_text_paste(pos));
2642 eldbus_message_arguments_append(ret, "b", res);
2648 _elm_atspi_bridge_plug_id_split(const char *plug_id, char **bus, char **path)
2650 if (!plug_id || !strcmp(plug_id, "")) return EINA_FALSE;
2651 unsigned int tokens = 0;
2652 char **split = eina_str_split_full(plug_id, ":", 0, &tokens);
2653 Eina_Bool ret = EINA_FALSE;
2656 if (!split[0] || !split[1])
2660 if (bus) *bus = strdup(split[0]);
2661 if (path) *path = strdup(split[1]);
2665 else if (tokens == 3)
2667 if (!split[0] || !split[1] || !split[2])
2672 snprintf(buf, sizeof(buf), "%s:%s",split[0], split[1]);
2673 if (bus) *bus = strdup(buf);
2674 if (path) *path = strdup(split[2]);
2684 static Eldbus_Message *
2685 _socket_embedded(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
2688 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2689 const char *obj_path = eldbus_message_path_get(msg);
2691 const char *bus, *path;
2692 Eo *bridge = _elm_atspi_bridge_get();
2693 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2694 eo_do(obj, proxy = elm_interface_atspi_accessible_parent_get());
2696 if (!eo_isa(proxy, ELM_ATSPI_PROXY_CLASS))
2697 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to embed object.");
2699 if (!eldbus_message_arguments_get(msg, "s", &path))
2700 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Plug id expected.");
2702 bus = eldbus_message_sender_get(msg);
2704 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
2706 _bridge_cache_build(bridge, proxy);
2708 return eldbus_message_method_return_new(msg);
2711 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2712 static Eldbus_Message *
2713 _socket_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2717 Eo *obj = eldbus_service_object_data_get(iface, "_atspi_obj");
2718 eo_do(obj, parent = eo_parent_get());
2719 Evas_Object *top = elm_object_top_widget_get(parent);
2721 if (!eldbus_message_arguments_get(msg, "ii", &x, &y))
2722 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
2724 eo_do(top, elm_interface_atspi_component_socket_offset_set(x, y));
2726 return eldbus_message_method_return_new(msg);
2730 static const Eldbus_Method editable_text_methods[] = {
2731 { "SetTextContents", ELDBUS_ARGS({"s", "newcontents"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_content_set, 0 },
2732 { "InsertText", ELDBUS_ARGS({"i", "position"}, {"s", "text"}, {"i", "length"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_insert, 0 },
2733 { "CopyText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), NULL, _editable_text_text_copy, 0 },
2734 { "CutText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_cut, 0 },
2735 { "DeleteText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_delete, 0 },
2736 { "PasteText", ELDBUS_ARGS({"i", "position"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_paste, 0 },
2737 { NULL, NULL, NULL, NULL, 0 }
2740 static const Eldbus_Method socket_methods[] = {
2741 { "Embedded", ELDBUS_ARGS({"s", "id"}), ELDBUS_ARGS({NULL, NULL}), _socket_embedded, 0 },
2742 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2743 { "SetOffset", ELDBUS_ARGS({"i", "x"}, {"i", "y"}), ELDBUS_ARGS({NULL, NULL}), _socket_offset_set, 0 },
2745 { NULL, NULL, NULL, NULL, 0 }
2748 static const Eldbus_Service_Interface_Desc socket_iface_desc = {
2749 ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL
2753 _bridge_object_from_path(Eo *bridge, const char *path)
2755 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2756 unsigned long long eo_ptr = 0;
2758 const char *tmp = path;
2761 int len = strlen(ELM_ACCESS_OBJECT_PATH_PREFIX);
2762 if (strncmp(path, ELM_ACCESS_OBJECT_PATH_PREFIX, len))
2765 tmp = path + len; /* Skip over the prefix */
2766 if (!strcmp(ELM_ACCESS_OBJECT_PATH_ROOT, tmp))
2767 return elm_atspi_bridge_root_get(bridge);
2769 sscanf(tmp, "%llu", &eo_ptr);
2770 eo = (Eo *) (uintptr_t) eo_ptr;
2772 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
2773 if (!eina_hash_find(pd->cache, &eo))
2775 WRN("Request for non-registered object: %s", path);
2779 ret = eo_isa(eo, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN) ? eo : NULL;
2785 _bridge_path_from_object(Eo *bridge, const Eo *eo)
2787 static char path[64];
2790 return ATSPI_DBUS_PATH_NULL;
2792 if (eo == elm_atspi_bridge_root_get(bridge))
2793 snprintf(path, sizeof(path), "%s%s", ELM_ACCESS_OBJECT_PATH_PREFIX, ELM_ACCESS_OBJECT_PATH_ROOT);
2795 snprintf(path, sizeof(path), ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE, (unsigned long long)(uintptr_t)eo);
2800 _accessible_property_get(const Eldbus_Service_Interface *interface, const char *property,
2801 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2802 Eldbus_Message **error)
2804 const char *ret = NULL, *obj_path = eldbus_message_path_get(request_msg);
2805 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2806 Eo *ret_obj = NULL, *obj = _bridge_object_from_path(bridge, obj_path);
2808 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, request_msg, error);
2810 if (!strcmp(property, "Name"))
2812 eo_do(obj, ret = elm_interface_atspi_accessible_name_get());
2815 eldbus_message_iter_basic_append(iter, 's', ret);
2818 else if (!strcmp(property, "Description"))
2820 eo_do(obj, ret = elm_interface_atspi_accessible_description_get());
2823 eldbus_message_iter_basic_append(iter, 's', ret);
2826 else if (!strcmp(property, "Parent"))
2828 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
2829 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
2830 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
2831 if ((!ret_obj) && (ELM_ATSPI_ROLE_APPLICATION == role))
2832 _object_desktop_reference_append(iter);
2834 _bridge_iter_object_reference_append(bridge, iter, ret_obj);
2837 else if (!strcmp(property, "ChildCount"))
2839 Eina_List *l = NULL;
2840 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
2841 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
2849 _selection_property_get(const Eldbus_Service_Interface *interface, const char *property,
2850 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2851 Eldbus_Message **error)
2854 const char *obj_path = eldbus_message_path_get(request_msg);
2855 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2856 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2858 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, request_msg, error);
2860 if (!strcmp(property, "NSelectedChildren"))
2862 eo_do(obj, n = elm_interface_atspi_selection_selected_children_count_get());
2863 eldbus_message_iter_basic_append(iter, 'i', n);
2870 _action_property_get(const Eldbus_Service_Interface *interface, const char *property,
2871 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2872 Eldbus_Message **error)
2875 const char *obj_path = eldbus_message_path_get(request_msg);
2876 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2877 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2879 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, request_msg, error);
2881 if (!strcmp(property, "NActions"))
2883 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
2884 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(actions));
2885 eina_list_free(actions);
2891 static Eldbus_Message*
2892 _value_properties_set(const Eldbus_Service_Interface *interface, const char *property,
2893 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg)
2897 const char *obj_path = eldbus_message_path_get(request_msg);
2898 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2899 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2901 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg);
2903 if (!eldbus_message_iter_arguments_get(iter, "d", &value))
2905 return eldbus_message_error_new(request_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: double.");
2908 if (!strcmp(property, "CurrentValue"))
2910 eo_do(obj, ret = elm_interface_atspi_value_and_text_set(value, NULL));
2911 Eldbus_Message *answer = eldbus_message_method_return_new(request_msg);
2912 eldbus_message_arguments_append(answer, "b", ret);
2920 _value_properties_get(const Eldbus_Service_Interface *interface, const char *property,
2921 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2922 Eldbus_Message **error)
2925 const char *obj_path = eldbus_message_path_get(request_msg);
2926 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2927 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2929 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg, error);
2931 if (!strcmp(property, "CurrentValue"))
2933 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
2934 eldbus_message_iter_basic_append(iter, 'd', value);
2937 if (!strcmp(property, "MinimumValue"))
2939 eo_do(obj, elm_interface_atspi_value_range_get(&value, NULL, NULL));
2940 eldbus_message_iter_basic_append(iter, 'd', value);
2943 if (!strcmp(property, "MaximumValue"))
2945 eo_do(obj, elm_interface_atspi_value_range_get(NULL, &value, NULL));
2946 eldbus_message_iter_basic_append(iter, 'd', value);
2949 if (!strcmp(property, "MinimumIncrement"))
2951 eo_do(obj, value = elm_interface_atspi_value_increment_get());
2952 eldbus_message_iter_basic_append(iter, 'd', value);
2959 _image_properties_get(const Eldbus_Service_Interface *interface, const char *property,
2960 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2961 Eldbus_Message **error)
2964 const char *obj_path = eldbus_message_path_get(request_msg);
2965 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2966 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2968 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, request_msg, error);
2970 if (!strcmp(property, "ImageDescription"))
2972 eo_do(obj, value = elm_interface_atspi_image_description_get());
2973 value = value ? value : "";
2974 eldbus_message_iter_basic_append(iter, 's', value);
2977 if (!strcmp(property, "ImageLocale"))
2979 eo_do(obj, value = elm_interface_atspi_image_locale_get());
2980 value = value ? value : "";
2981 eldbus_message_iter_basic_append(iter, 's', value);
2988 _text_properties_get(const Eldbus_Service_Interface *interface, const char *property,
2989 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2990 Eldbus_Message **error)
2992 const char *obj_path = eldbus_message_path_get(request_msg);
2993 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2994 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2997 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, request_msg, error);
2999 if (!strcmp(property, "CharacterCount"))
3001 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
3002 eldbus_message_iter_basic_append(iter, 'i', val);
3005 if (!strcmp(property, "CaretOffset"))
3007 eo_do(obj, val = elm_interface_atspi_text_caret_offset_get());
3008 eldbus_message_iter_basic_append(iter, 'i', val);
3014 static Eldbus_Message*
3015 _application_properties_set(const Eldbus_Service_Interface *iface, const char *property, Eldbus_Message_Iter *iter, const Eldbus_Message *input_msg)
3017 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3018 const char *obj_path = eldbus_message_path_get(input_msg);
3019 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3022 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
3023 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, input_msg);
3025 if (!eldbus_message_iter_arguments_get(iter, "i", &value))
3027 return eldbus_message_error_new(input_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: int.");
3030 if (!strcmp(property, "Id"))
3033 Eldbus_Message *answer = eldbus_message_method_return_new(input_msg);
3034 eldbus_message_arguments_append(answer, "b", EINA_TRUE);
3042 _application_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3043 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3044 Eldbus_Message **error)
3046 const char *obj_path = eldbus_message_path_get(request_msg);
3047 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3048 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3050 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
3051 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, request_msg, error);
3053 if (!strcmp(property, "ToolkitName"))
3055 eldbus_message_iter_basic_append(iter, 's', "elementary");
3058 if (!strcmp(property, "Version"))
3061 snprintf(buf, sizeof(buf), "%d.%d", ELM_VERSION_MAJOR, ELM_VERSION_MINOR);
3062 eldbus_message_iter_basic_append(iter, 's', buf);
3065 if (!strcmp(property, "Id"))
3067 eldbus_message_iter_basic_append(iter, 'i', pd->id);
3073 static const Eldbus_Property accessible_properties[] = {
3074 { "Name", "s", NULL, NULL, 0 },
3075 { "Description", "s", NULL, NULL, 0 },
3076 { "Parent", "(so)", NULL, NULL, 0 },
3077 { "ChildCount", "i", NULL, NULL, 0 },
3078 { NULL, NULL, NULL, NULL, 0 }
3081 static const Eldbus_Property action_properties[] = {
3082 { "NActions", "i", _action_property_get, NULL, 0 },
3083 { NULL, NULL, NULL, NULL, 0 }
3086 static const Eldbus_Property value_properties[] = {
3087 { "MinimumValue", "d", NULL, NULL, 0 },
3088 { "MaximumValue", "d", NULL, NULL, 0 },
3089 { "MinimumIncrement", "d", NULL, NULL, 0 },
3090 { "CurrentValue", "d", NULL, NULL, 0 },
3091 { NULL, NULL, NULL, NULL, 0 }
3094 static const Eldbus_Property image_properties[] = {
3095 { "ImageDescription", "s", NULL, NULL, 0 },
3096 { "ImageLocale", "s", NULL, NULL, 0 },
3097 { NULL, NULL, NULL, NULL, 0 }
3100 static const Eldbus_Property selection_properties[] = {
3101 { "NSelectedChildren", "i", _selection_property_get, NULL, 0 },
3102 { NULL, NULL, NULL, NULL, 0 }
3105 static const Eldbus_Property text_properties[] = {
3106 { "CharacterCount", "i", NULL, NULL, 0 },
3107 { "CaretOffset", "i", NULL, NULL, 0 },
3108 { NULL, NULL, NULL, NULL, 0 }
3111 static const Eldbus_Property application_properties[] = {
3112 { "ToolkitName", "s", NULL, NULL, 0 },
3113 { "Version", "s", NULL, NULL, 0 },
3114 { "Id", "i", NULL, NULL, 0 },
3115 { NULL, NULL, NULL, NULL, 0 }
3118 static const Eldbus_Service_Interface_Desc accessible_iface_desc = {
3119 ATSPI_DBUS_INTERFACE_ACCESSIBLE, accessible_methods, NULL, accessible_properties, _accessible_property_get, NULL
3122 static const Eldbus_Service_Interface_Desc action_iface_desc = {
3123 ATSPI_DBUS_INTERFACE_ACTION, action_methods, NULL, action_properties, NULL, NULL
3126 static const Eldbus_Service_Interface_Desc value_iface_desc = {
3127 ATSPI_DBUS_INTERFACE_VALUE, NULL, NULL, value_properties, _value_properties_get, _value_properties_set
3130 static const Eldbus_Service_Interface_Desc image_iface_desc = {
3131 ATSPI_DBUS_INTERFACE_IMAGE, image_methods, NULL, image_properties, _image_properties_get, NULL
3134 static const Eldbus_Service_Interface_Desc selection_iface_desc = {
3135 ATSPI_DBUS_INTERFACE_SELECTION, selection_methods, NULL, selection_properties, NULL, NULL
3138 static const Eldbus_Service_Interface_Desc text_iface_desc = {
3139 ATSPI_DBUS_INTERFACE_TEXT, text_methods, NULL, text_properties, _text_properties_get, NULL
3142 static const Eldbus_Service_Interface_Desc editable_text_iface_desc = {
3143 ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, editable_text_methods, NULL, NULL, NULL, NULL
3146 static const Eldbus_Service_Interface_Desc application_iface_desc = {
3147 ATSPI_DBUS_INTERFACE_APPLICATION, NULL, NULL, application_properties, _application_properties_get, _application_properties_set
3151 _collection_match_rule_free(struct collection_match_rule *rule)
3153 Elm_Atspi_Attribute *attr;
3154 eina_list_free(rule->ifaces);
3155 EINA_LIST_FREE(rule->attributes, attr)
3157 eina_stringshare_del(attr->key);
3158 eina_stringshare_del(attr->value);
3163 _collection_roles_convert(uint64_t roles[2])
3165 // Currently elm roles and atspi roles are binary compatible.
3166 // Implement this function when it will be needed.
3171 _collection_iter_match_rule_get(Eldbus_Message_Iter *iter, struct collection_match_rule *rule)
3173 Eldbus_Message_Iter *states_iter, *attrib_iter, *iter_arg, *role_iter, *ifc_iter;
3174 unsigned int *array;
3175 int array_count, state_match, attrib_match, role_match, ifc_match, reverse;
3176 const char *ifc_name;
3178 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))
3180 ERR("Unable to get message arguments");
3184 memset(rule, 0x0, sizeof(struct collection_match_rule));
3185 rule->statematchtype = state_match;
3186 rule->attributematchtype = attrib_match;
3187 rule->rolematchtype = role_match;
3188 rule->interfacematchtype = ifc_match;
3189 rule->reverse = reverse;
3191 if (!eldbus_message_iter_fixed_array_get(states_iter, 'i', &array, &array_count))
3194 //Roles according to libatspi impementation are transferred in 2-int element fixed bit array
3195 if (array_count != 2)
3197 ERR("Unexpected states array size");
3200 uint64_t states = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3201 rule->states = _atspi_state_set_to_elm_atspi_state_set(states);
3203 //Roles according to libatspi impementation are transferred in 4-int element fixed bit array
3204 if (!eldbus_message_iter_fixed_array_get(role_iter, 'i', &array, &array_count))
3207 if (array_count != 4)
3209 ERR("Unexpected roles array size");
3213 //convert atspi roles to elm_roles
3214 rule->roles[0] = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3215 rule->roles[1] = ((uint64_t)array[2] | ((uint64_t)array[3] << 32));
3217 _collection_roles_convert(rule->roles);
3219 //Get matching properties
3220 while (eldbus_message_iter_get_and_next(attrib_iter, '{', &iter_arg))
3222 const char *key, *value;
3223 if (eldbus_message_iter_arguments_get(iter_arg, "ss", &key, &value))
3225 Elm_Atspi_Attribute *attrib = calloc(sizeof(Elm_Atspi_Attribute), 1);
3226 attrib->key = eina_stringshare_add(key);
3227 attrib->value = eina_stringshare_add(value);
3228 rule->attributes = eina_list_append(rule->attributes, attrib);
3232 //Get interfaces to match
3233 while (eldbus_message_iter_get_and_next(ifc_iter, 's', &ifc_name))
3235 const Eo_Class *class = NULL;
3236 if (!strcmp(ifc_name, "action"))
3237 class = ELM_INTERFACE_ATSPI_ACTION_MIXIN;
3238 else if (!strcmp(ifc_name, "component"))
3239 class = ELM_INTERFACE_ATSPI_COMPONENT_MIXIN;
3240 else if (!strcmp(ifc_name, "editabletext"))
3241 class = ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE;
3242 else if (!strcmp(ifc_name, "text"))
3243 class = ELM_INTERFACE_ATSPI_TEXT_INTERFACE;
3244 else if (!strcmp(ifc_name, "image"))
3245 class = ELM_INTERFACE_ATSPI_SELECTION_INTERFACE;
3246 else if (!strcmp(ifc_name, "value"))
3247 class = ELM_INTERFACE_ATSPI_VALUE_INTERFACE;
3250 rule->ifaces = eina_list_append(rule->ifaces, class);
3253 _collection_match_rule_free(rule);
3262 _collection_match_interfaces_helper(Eo *obj, Eina_List *ifcs, Eina_Bool condition, Eina_Bool ret_if_true, Eina_Bool ret_if_false)
3267 EINA_LIST_FOREACH(ifcs, l, class)
3269 if (eo_isa(obj, class) == condition)
3272 return ret_if_false;
3276 _collection_match_interfaces_lookup(Eo *obj, struct collection_match_rule *rule)
3278 Eina_Bool ret = EINA_FALSE;
3280 switch (rule->interfacematchtype)
3282 case ATSPI_Collection_MATCH_INVALID:
3285 case ATSPI_Collection_MATCH_ALL:
3286 ret = _collection_match_interfaces_helper(
3287 obj, rule->ifaces, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3289 case ATSPI_Collection_MATCH_ANY:
3290 ret = _collection_match_interfaces_helper(
3291 obj, rule->ifaces, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3293 case ATSPI_Collection_MATCH_NONE:
3294 ret = _collection_match_interfaces_helper(
3295 obj, rule->ifaces, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3304 _collection_match_states_lookup(Eo *obj, struct collection_match_rule *rule)
3306 Eina_Bool ret = EINA_FALSE;
3307 Elm_Atspi_State_Set ss;
3309 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
3311 switch (rule->statematchtype)
3313 case ATSPI_Collection_MATCH_INVALID:
3316 case ATSPI_Collection_MATCH_ALL:
3317 ret = (ss & rule->states) == rule->states;
3319 case ATSPI_Collection_MATCH_ANY:
3320 ret = (ss & rule->states) > 0;
3322 case ATSPI_Collection_MATCH_NONE:
3323 ret = (ss & rule->states) == 0;
3333 _collection_match_roles_lookup(Eo *obj, struct collection_match_rule *rule)
3335 Eina_Bool ret = EINA_FALSE;
3336 Elm_Atspi_Role role;
3339 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
3344 role_set = rule->roles[1];
3347 role_set = rule->roles[0];
3351 ERR("Elm_Atspi_Role enum value exceeds 127. Unable to compare with roles bit field.");
3355 switch (rule->rolematchtype)
3357 case ATSPI_Collection_MATCH_INVALID:
3360 case ATSPI_Collection_MATCH_ALL:
3361 case ATSPI_Collection_MATCH_ANY:
3362 ret = (role_set & (1ULL << role)) > 0;
3364 case ATSPI_Collection_MATCH_NONE:
3365 ret = (role_set & (1ULL << role)) == 0;
3375 _collection_match_attributes_helper(Eina_List *obj_attribs, Eina_List *attribs, Eina_Bool compare, Eina_Bool ret_if_compare, Eina_Bool ret_default)
3378 Elm_Atspi_Attribute *attr, *attr2;
3380 EINA_LIST_FOREACH(attribs, l, attr)
3382 EINA_LIST_FOREACH(obj_attribs, l2, attr2)
3384 if ((attr->key && attr2->key &&
3385 attr->value && attr2->value &&
3386 !strcmp(attr->key, attr2->key) &&
3387 !strcmp(attr->value, attr2->value)) == compare)
3389 return ret_if_compare;
3398 _collection_match_attributes_lookup(Eo *obj, struct collection_match_rule *rule)
3400 Eina_Bool ret = EINA_FALSE;
3401 Eina_List *obj_attribs;
3403 eo_do(obj, obj_attribs = elm_interface_atspi_accessible_attributes_get());
3405 switch (rule->attributematchtype)
3407 case ATSPI_Collection_MATCH_INVALID:
3410 case ATSPI_Collection_MATCH_ALL:
3411 ret = _collection_match_attributes_helper(
3412 obj_attribs, rule->attributes, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3414 case ATSPI_Collection_MATCH_ANY:
3415 ret = _collection_match_attributes_helper(
3416 obj_attribs, rule->attributes, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3418 case ATSPI_Collection_MATCH_NONE:
3419 ret = _collection_match_attributes_helper(
3420 obj_attribs, rule->attributes, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3426 elm_atspi_attributes_list_free(obj_attribs);
3432 _collection_sort_order_canonical(struct collection_match_rule *rule, Eina_List **ls,
3434 Eo *obj, long index, Eina_Bool flag,
3435 Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3438 Eina_List *children;
3439 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
3440 long acount = eina_list_count(children);
3441 Eina_Bool prev = pobj ? EINA_TRUE : EINA_FALSE;
3443 for (; i < acount && (max == 0 || count < max); i++)
3445 Eo *child = eina_list_nth(children, i);
3447 if (prev && child == pobj)
3449 eina_list_free(children);
3453 if (flag && _collection_match_interfaces_lookup(child, rule)
3454 && _collection_match_states_lookup(child, rule)
3455 && _collection_match_roles_lookup(child, rule)
3456 && _collection_match_attributes_lookup(child, rule))
3458 *ls = eina_list_append(*ls, child);
3465 if (recurse && traverse)
3466 count = _collection_sort_order_canonical(rule, ls, count,
3467 max, child, 0, EINA_TRUE,
3468 pobj, recurse, traverse);
3470 eina_list_free(children);
3475 _collection_sort_order_reverse_canonical(struct collection_match_rule *rule, Eina_List **ls,
3476 int count, int max, Eo *obj, Eina_Bool flag, Eo *pobj)
3478 Eo *nextobj, *parent;
3480 Eina_List *children;
3482 /* This breaks us out of the recursion. */
3483 if (!obj || obj == pobj)
3488 /* Add to the list if it matches */
3489 if (flag && _collection_match_interfaces_lookup(obj, rule)
3490 && _collection_match_states_lookup(obj, rule)
3491 && _collection_match_roles_lookup(obj, rule)
3492 && _collection_match_attributes_lookup(obj, rule)
3493 && (max == 0 || count < max))
3495 *ls = eina_list_append(*ls, obj);
3502 /* Get the current nodes index in it's parent and the parent object. */
3504 indexinparent = elm_interface_atspi_accessible_index_in_parent_get(),
3505 parent = elm_interface_atspi_accessible_parent_get());
3507 if ((indexinparent > 0) && ((max == 0) || (count < max)))
3509 /* there are still some siblings to visit so get the previous sibling
3510 and get it's last descendant.
3511 First, get the previous sibling */
3512 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
3513 nextobj = eina_list_nth(children, indexinparent - 1);
3514 eina_list_free(children);
3516 /* Now, drill down the right side to the last descendant */
3518 eo_do(nextobj, children = elm_interface_atspi_accessible_children_get());
3519 if (children) nextobj = eina_list_last_data_get(children);
3520 eina_list_free(children);
3523 /* recurse with the last descendant */
3524 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3525 nextobj, EINA_TRUE, pobj);
3527 else if (max == 0 || count < max)
3529 /* no more siblings so next node must be the parent */
3530 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3531 parent, EINA_TRUE, pobj);
3538 _collection_inbackorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3541 *list = eina_list_append(*list, obj);
3543 _collection_sort_order_reverse_canonical(rule, list, 0, max, obj, EINA_TRUE, collection);
3545 *list = eina_list_remove_list(*list, *list);
3551 _collection_inorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3552 int count, int max, Eo *obj, Eina_Bool traverse)
3556 count = _collection_sort_order_canonical(rule, list, count, max, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3558 while ((max == 0 || count < max) && obj && obj != collection)
3562 parent = elm_interface_atspi_accessible_parent_get(),
3563 idx = elm_interface_atspi_accessible_index_in_parent_get());
3564 count = _collection_sort_order_canonical(rule, list, count, max, parent,
3565 idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3569 if (max == 0 || count < max)
3570 count = _collection_sort_order_canonical(rule, list, count, max,
3571 obj, idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3577 _collection_query(struct collection_match_rule *rule, AtspiCollectionSortOrder sortby,
3578 Eina_List **list, int count, int max, Eo *obj, long index,
3579 Eina_Bool flag, Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3583 case ATSPI_Collection_SORT_ORDER_CANONICAL:
3584 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3585 pobj, recurse, traverse);
3587 case ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL:
3588 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3589 pobj, recurse, traverse);
3590 *list = eina_list_reverse(*list);
3594 WRN("Unhandled sort method");
3600 static Eldbus_Message*
3601 _collection_return_msg_from_list(Elm_Atspi_Bridge *bridge, const Eldbus_Message *msg, const Eina_List *objs)
3603 Eldbus_Message *ret;
3605 Eldbus_Message_Iter *iter, *array_iter;
3608 ret = eldbus_message_method_return_new(msg);
3609 if (!ret) return NULL;
3611 iter = eldbus_message_iter_get(ret);
3612 array_iter = eldbus_message_iter_container_new(iter, 'a', "(so)");
3614 EINA_LIST_FOREACH(objs, l, obj)
3616 _bridge_object_register(bridge, obj);
3617 _bridge_iter_object_reference_append(bridge, array_iter, obj);
3620 eldbus_message_iter_container_close(iter, array_iter);
3625 _collection_get_matches_from_handle(Eo *collection, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, int max, Eina_Bool traverse)
3627 Eina_List *result = NULL;
3633 case ATSPI_Collection_TREE_INORDER:
3634 _collection_inorder(collection, rule, &result, 0, max, current, traverse);
3635 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3636 result = eina_list_reverse(result);
3638 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3640 idx = elm_interface_atspi_accessible_index_in_parent_get(),
3641 parent = elm_interface_atspi_accessible_parent_get());
3642 _collection_query(rule, sortby, &result, 0, max, parent, idx, EINA_FALSE, NULL, EINA_TRUE, traverse);
3644 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3645 _collection_query(rule, sortby, &result, 0, max, current, 0, EINA_FALSE, NULL, EINA_TRUE, traverse);
3648 ERR("Tree parameter value not handled");
3654 static Eldbus_Message*
3655 _collection_get_matches_from(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3657 const char *obj_path = eldbus_message_path_get(msg);
3658 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3659 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3660 Eldbus_Message *ret;
3661 Eldbus_Message_Iter *iter, *rule_iter;
3662 struct collection_match_rule rule;
3664 AtspiCollectionTreeTraversalType tree;
3666 AtspiCollectionSortOrder sortby;
3667 Eina_List *result = NULL;
3669 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3671 iter = eldbus_message_iter_get(msg);
3672 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3674 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uuib", &obj_path, &rule_iter, &sortby, &tree, &count, &traverse))
3676 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3679 current = _bridge_object_from_path(bridge, obj_path);
3681 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3683 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3684 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3686 result = _collection_get_matches_from_handle(obj, current, &rule, sortby, tree, count, traverse);
3687 ret = _collection_return_msg_from_list(bridge, msg, result);
3689 eina_list_free(result);
3690 _collection_match_rule_free(&rule);
3696 _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)
3698 Eina_List *result = NULL;
3699 Eo *collection = obj;
3702 eo_do(obj, collection = elm_interface_atspi_accessible_parent_get());
3706 case ATSPI_Collection_TREE_INORDER:
3707 _collection_inbackorder(obj, rule, &result, max, current);
3708 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3709 result = eina_list_reverse(result);
3711 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3712 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3714 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3715 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3718 ERR("Tree parameter value not handled");
3725 static Eldbus_Message*
3726 _collection_get_matches_to(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3728 const char *obj_path = eldbus_message_path_get(msg);
3729 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3730 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3731 Eldbus_Message *ret;
3732 Eldbus_Message_Iter *iter, *rule_iter;
3733 struct collection_match_rule rule;
3735 AtspiCollectionTreeTraversalType tree;
3737 AtspiCollectionSortOrder sortby;
3738 Eina_List *result = NULL;
3741 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3743 iter = eldbus_message_iter_get(msg);
3744 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3746 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uubib", &obj_path, &rule_iter, &sortby, &tree, &limit, &count, &traverse))
3748 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, tree, limit count or traverse values.");
3751 current = _bridge_object_from_path(bridge, obj_path);
3753 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3755 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3756 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3758 result = _collection_get_matches_to_handle(obj, current, &rule, sortby, tree, limit, count, traverse);
3759 ret = _collection_return_msg_from_list(bridge, msg, result);
3761 eina_list_free(result);
3762 _collection_match_rule_free(&rule);
3767 static Eldbus_Message*
3768 _collection_get_matches(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
3770 const char *obj_path = eldbus_message_path_get(msg);
3771 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3772 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3773 Eldbus_Message *ret;
3774 Eldbus_Message_Iter *iter, *rule_iter;
3775 struct collection_match_rule rule;
3778 AtspiCollectionSortOrder sortby;
3779 Eina_List *result = NULL;
3781 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3783 iter = eldbus_message_iter_get(msg);
3784 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3786 if (!eldbus_message_iter_arguments_get(iter, "(aiia{ss}iaiiasib)uib", &rule_iter, &sortby, &count, &traverse))
3788 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3791 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3792 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3794 _collection_query(&rule, sortby, &result, 0, count, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3796 ret = _collection_return_msg_from_list(bridge, msg, result);
3798 eina_list_free(result);
3799 _collection_match_rule_free(&rule);
3804 static const Eldbus_Method collection_methods[] = {
3806 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3807 {"u", "sortby"}, {"u", "tree"}, {"i", "count"}, {"b", "traverse"}),
3808 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_from, 0 },
3810 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3811 {"u", "sortby"}, {"u", "tree"}, {"b", "limit_scope"},
3812 {"i", "count"}, {"b", "traverse"}),
3813 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_to, 0 },
3815 ELDBUS_ARGS({"(aiia{ss}iaiiasib)", "match_rule"},
3816 {"u", "sortby"}, {"i", "count"}, {"b", "traverse"}),
3817 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches, 0 },
3818 { NULL, NULL, NULL, NULL, 0 }
3821 static const Eldbus_Service_Interface_Desc collection_iface_desc = {
3822 ATSPI_DBUS_INTERFACE_COLLECTION, collection_methods, NULL, NULL, NULL, NULL
3826 _object_get_bus_name_and_path(Eo *bridge, const Eo *obj, const char **bus_name, const char **path)
3828 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
3830 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
3831 if (eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
3833 const char *pbus = "", *ppath = ATSPI_DBUS_PATH_NULL;
3834 eo_do(obj, elm_obj_atspi_proxy_address_get(&pbus, &ppath));
3837 if (bus_name) *bus_name = pbus;
3838 if (path) *path = ppath;
3841 DBG("Invalid proxy address! Address not set before connecting/listening. Or after proxy is removed.");
3843 if (bus_name) *bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
3844 if (path) *path = _bridge_path_from_object(bridge, obj);
3849 _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj)
3851 EINA_SAFETY_ON_NULL_RETURN(iter);
3853 const char *pbus = NULL, *ppath = NULL;
3854 _object_get_bus_name_and_path(bridge, obj, &pbus, &ppath);
3855 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3856 eldbus_message_iter_basic_append(iter_struct, 's', pbus);
3857 eldbus_message_iter_basic_append(iter_struct, 'o', ppath);
3858 eldbus_message_iter_container_close(iter, iter_struct);
3862 _object_desktop_reference_append(Eldbus_Message_Iter *iter)
3864 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3865 EINA_SAFETY_ON_NULL_RETURN(iter);
3867 eldbus_message_iter_basic_append(iter_struct, 's', ATSPI_DBUS_NAME_REGISTRY);
3868 eldbus_message_iter_basic_append(iter_struct, 'o', ATSPI_DBUS_PATH_ROOT);
3869 eldbus_message_iter_container_close(iter, iter_struct);
3873 _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj)
3875 Eldbus_Message_Iter *iter_array;
3876 iter_array = eldbus_message_iter_container_new(iter, 'a', "s");
3877 if (!iter_array) return;
3879 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
3881 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE);
3882 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COLLECTION);
3884 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN))
3885 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACTION);
3886 if (eo_isa(obj, ELM_ATSPI_APP_OBJECT_CLASS))
3887 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_APPLICATION);
3888 if (eo_isa(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN))
3889 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COMPONENT);
3890 if (eo_isa(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE))
3891 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_EDITABLE_TEXT);
3892 if (eo_isa(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN))
3893 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_IMAGE);
3894 if (eo_isa(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
3895 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_SELECTION);
3896 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
3897 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_TEXT);
3898 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
3899 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_VALUE);
3901 eldbus_message_iter_container_close(iter, iter_array);
3905 _cache_item_reference_append_cb(Eo *bridge, Eo *data, Eldbus_Message_Iter *iter_array)
3907 if (!eo_ref_get(data) || eo_destructed_is(data))
3910 Eldbus_Message_Iter *iter_struct, *iter_sub_array;
3911 Elm_Atspi_State_Set states;
3912 Elm_Atspi_Role role;
3913 Eo *root = elm_atspi_bridge_root_get(bridge);
3915 eo_do(data, role = elm_interface_atspi_accessible_role_get());
3917 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
3918 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_struct, EINA_TRUE);
3920 /* Marshall object path */
3921 _bridge_iter_object_reference_append(bridge, iter_struct, data);
3923 /* Marshall application */
3924 _bridge_iter_object_reference_append(bridge, iter_struct, root);
3927 eo_do(data, parent = elm_interface_atspi_accessible_parent_get());
3928 /* Marshall parent */
3929 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
3930 _object_desktop_reference_append(iter_struct);
3932 _bridge_iter_object_reference_append(bridge, iter_struct, parent);
3934 /* Marshall children */
3935 Eina_List *children_list = NULL, *l;
3938 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3939 Elm_Atspi_State_Set ss;
3940 eo_do(data, ss = elm_interface_atspi_accessible_state_set_get());
3942 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
3943 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
3945 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3946 if (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
3948 eo_do(data, children_list = elm_interface_atspi_accessible_children_get());
3950 EINA_LIST_FOREACH(children_list, l, child)
3951 _bridge_iter_object_reference_append(bridge, iter_sub_array, child);
3953 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3954 eina_list_free(children_list);
3958 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
3960 /* Marshall interfaces */
3961 _iter_interfaces_append(iter_struct, data);
3964 const char *name = NULL;
3965 eo_do(data, name = elm_interface_atspi_accessible_name_get());
3969 eldbus_message_iter_basic_append(iter_struct, 's', name);
3972 eldbus_message_iter_basic_append(iter_struct, 'u', role);
3974 /* Marshall description */
3975 const char* descritpion = NULL;
3976 eo_do(data, descritpion = elm_interface_atspi_accessible_description_get());
3979 eldbus_message_iter_basic_append(iter_struct, 's', descritpion);
3981 /* Marshall state set */
3982 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "u");
3983 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
3985 eo_do(data, states = elm_interface_atspi_accessible_state_set_get());
3987 unsigned int s1 = states & 0xFFFFFFFF;
3988 unsigned int s2 = (states >> 32) & 0xFFFFFFFF;
3989 eldbus_message_iter_basic_append(iter_sub_array, 'u', s1);
3990 eldbus_message_iter_basic_append(iter_sub_array, 'u', s2);
3992 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
3993 eldbus_message_iter_container_close(iter_array, iter_struct);
3998 if (iter_struct) eldbus_message_iter_del(iter_struct);
4002 static Eldbus_Message *
4003 _cache_get_items(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
4005 Eldbus_Message_Iter *iter, *iter_array;
4006 Eldbus_Message *ret;
4007 Eina_List *to_process;
4010 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4011 if (!bridge) return NULL;
4013 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4015 ret = eldbus_message_method_return_new(msg);
4016 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4018 iter = eldbus_message_iter_get(ret);
4019 iter_array = eldbus_message_iter_container_new(iter, 'a', CACHE_ITEM_SIGNATURE);
4020 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
4022 eo_do(bridge, root = elm_obj_atspi_bridge_root_get());
4023 to_process = eina_list_append(NULL, root);
4027 Eo *obj = eina_list_data_get(to_process);
4028 to_process = eina_list_remove_list(to_process, to_process);
4029 _cache_item_reference_append_cb(bridge, obj, iter_array);
4030 _bridge_object_register(bridge, obj);
4032 Eina_List *children;
4033 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
4034 to_process = eina_list_merge(to_process, children);
4037 eldbus_message_iter_container_close(iter, iter_array);
4041 if (ret) eldbus_message_unref(ret);
4045 static const Eldbus_Method cache_methods[] = {
4046 { "GetItems", NULL, ELDBUS_ARGS({CACHE_ITEM_SIGNATURE, "items"}), _cache_get_items, 0 },
4047 { NULL, NULL, NULL, NULL, 0 }
4050 static const Eldbus_Signal cache_signals[] = {
4051 [ATSPI_OBJECT_CHILD_ADDED] = { "AddAccessible", ELDBUS_ARGS({"((so)(so)a(so)assusau)", "added"}), 0},
4052 [ATSPI_OBJECT_CHILD_REMOVED] = { "RemoveAccessible", ELDBUS_ARGS({ "(so)", "removed" }), 0},
4056 static const Eldbus_Service_Interface_Desc cache_iface_desc = {
4057 ATSPI_DBUS_INTERFACE_CACHE, cache_methods, cache_signals, NULL, NULL, NULL
4060 // Component interface
4061 static Eldbus_Message *
4062 _component_contains(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4064 const char *obj_path = eldbus_message_path_get(msg);
4065 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4066 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4068 Eina_Bool contains = EINA_FALSE;
4069 AtspiCoordType coord_type;
4070 Eldbus_Message *ret;
4072 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4074 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4075 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4077 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4078 eo_do(obj, contains = elm_interface_atspi_component_contains(type, x, y));
4080 ret = eldbus_message_method_return_new(msg);
4081 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4083 eldbus_message_arguments_append(ret, "b", contains);
4088 static Eldbus_Message *
4089 _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4091 const char *obj_path = eldbus_message_path_get(msg);
4092 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4093 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4094 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4096 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4098 Eo *accessible = NULL;
4099 AtspiCoordType coord_type;
4100 Eldbus_Message *ret;
4101 Eldbus_Message_Iter *iter;
4103 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4105 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
4106 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
4107 if (ecore_evas_obscured_get(ee))
4108 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
4111 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4112 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4114 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4115 Evas_Object *top = elm_object_top_widget_get(obj);
4118 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
4124 ret = eldbus_message_method_return_new(msg);
4125 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4127 iter = eldbus_message_iter_get(ret);
4128 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4129 eo_do(obj, accessible = elm_interface_atspi_component_accessible_at_point_get(type, x, y));
4130 _bridge_iter_object_reference_append(bridge, iter, accessible);
4131 _bridge_object_register(bridge, accessible);
4136 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
4138 NEIGHBOR_SEARCH_MODE_NORMAL = 0,
4139 NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT = 1,
4140 NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING = 2,
4141 NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE = 3,
4142 } GetNeighborSearchMode;
4144 typedef struct accessibility_navigation_pointer_table {
4145 AtspiRole (*object_get_role)(struct accessibility_navigation_pointer_table *t, void *ptr);
4146 uint64_t (*object_get_state_set)(struct accessibility_navigation_pointer_table *t, void *ptr);
4147 void *(*get_object_in_relation_by_type)(struct accessibility_navigation_pointer_table *t, void *ptr, AtspiRelationType type);
4148 unsigned char (*object_is_zero_size)(struct accessibility_navigation_pointer_table *t, void *ptr);
4149 void *(*get_parent)(struct accessibility_navigation_pointer_table *t, void *ptr);
4150 unsigned char (*object_is_scrollable)(struct accessibility_navigation_pointer_table *t, void *ptr);
4151 void *(*get_object_at_point)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4152 unsigned char (*object_contains)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4153 unsigned char (*object_is_proxy)(struct accessibility_navigation_pointer_table *t, void *ptr);
4154 } accessibility_navigation_pointer_table;
4156 #define CALL(fncname, ...) table->fncname(table, __VA_ARGS__)
4157 static unsigned char _accept_object_check_role(accessibility_navigation_pointer_table *table EINA_UNUSED, void *obj)
4159 return _elm_widget_atspi_role_acceptable_check(obj);
4162 static unsigned char _state_set_is_set(uint64_t state_set, AtspiStateType state)
4164 return (state_set & ((uint64_t)1 << (unsigned int)state)) != 0;
4167 static unsigned char _object_is_defunct(accessibility_navigation_pointer_table *table, void *ptr)
4169 uint64_t states = CALL(object_get_state_set, ptr);
4170 return _state_set_is_set(states, ATSPI_STATE_DEFUNCT);
4173 static unsigned char _object_role_is_acceptable_when_navigating_next_prev(accessibility_navigation_pointer_table *table, void *obj)
4175 AtspiRole role = CALL(object_get_role, obj);
4176 return role != ATSPI_ROLE_POPUP_MENU && role != ATSPI_ROLE_DIALOG;
4179 static void *_get_object_in_relation_flow(accessibility_navigation_pointer_table *table, void *source, unsigned char forward)
4181 return CALL(get_object_in_relation_by_type, source, forward ? ATSPI_RELATION_FLOWS_TO : ATSPI_RELATION_FLOWS_FROM);
4184 static unsigned char _object_is_item(accessibility_navigation_pointer_table *table, void *obj)
4186 AtspiRole role = CALL(object_get_role, obj);
4187 return role == ATSPI_ROLE_LIST_ITEM || role == ATSPI_ROLE_MENU_ITEM;
4190 static unsigned char _object_is_highlightable(accessibility_navigation_pointer_table *table, void *obj)
4192 uint64_t state_set = CALL(object_get_state_set, obj);
4193 return _state_set_is_set(state_set, ATSPI_STATE_HIGHLIGHTABLE);
4196 static unsigned char _object_is_visible(accessibility_navigation_pointer_table *table, void *obj)
4198 uint64_t state_set = CALL(object_get_state_set, obj);
4199 return _state_set_is_set(state_set, ATSPI_STATE_VISIBLE);
4202 static unsigned char _object_is_showing(accessibility_navigation_pointer_table *table, void *obj)
4204 uint64_t state_set = CALL(object_get_state_set, obj);
4205 return _state_set_is_set(state_set, ATSPI_STATE_SHOWING);
4208 static unsigned char _object_is_collapsed(accessibility_navigation_pointer_table *table, void *obj)
4210 uint64_t state_set = CALL(object_get_state_set, obj);
4212 _state_set_is_set(state_set, ATSPI_STATE_EXPANDABLE) &&
4213 !_state_set_is_set(state_set, ATSPI_STATE_EXPANDED);
4216 static unsigned char _object_has_modal_state(accessibility_navigation_pointer_table *table, void *obj)
4218 uint64_t state_set = CALL(object_get_state_set, obj);
4219 return _state_set_is_set(state_set, ATSPI_STATE_MODAL);
4222 static unsigned char _object_is_zero_size(accessibility_navigation_pointer_table *table, void *obj)
4224 return CALL(object_is_zero_size, obj);
4227 static void *_get_scrollable_parent(accessibility_navigation_pointer_table *table, void *obj)
4231 obj = CALL(get_parent, obj);
4232 if (obj && CALL(object_is_scrollable, obj)) return obj;
4236 static unsigned char _accept_object(accessibility_navigation_pointer_table *table, void *obj)
4239 if (!_object_is_visible(table, obj)) return 0;
4240 if (!_accept_object_check_role(table, obj)) return 0;
4241 if (CALL(get_object_in_relation_by_type, obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0;
4242 if (!_object_is_highlightable(table, obj)) return 0;
4244 if (_get_scrollable_parent(table, obj) != NULL)
4246 void *parent = CALL(get_parent, obj);
4250 return !_object_is_item(table, obj) || !_object_is_collapsed(table, parent);
4255 if (_object_is_zero_size(table, obj)) return 0;
4256 if (!_object_is_showing(table, obj)) return 0;
4261 static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigation_pointer_table *table,
4262 void *root, int x, int y, unsigned char coordinates_are_screen_based)
4264 if (!root) return NULL;
4266 void *return_value = NULL;
4269 void *target = CALL(get_object_at_point, root, x, y, coordinates_are_screen_based);
4272 // always return proxy, so atspi lib can call on it again
4273 if (CALL(object_is_proxy, target)) return target;
4276 void *relation_obj = CALL(get_object_in_relation_by_type, root, ATSPI_RELATION_CONTROLLED_BY);
4277 unsigned char contains = 0;
4280 contains = CALL(object_contains, relation_obj, x, y, coordinates_are_screen_based);
4281 if (contains) root = relation_obj;
4284 if (_accept_object(table, root))
4286 return_value = root;
4287 if (contains) break;
4291 if (return_value && _object_has_modal_state(table, return_value)) return_value = NULL;
4292 return return_value;
4295 static void *_find_non_defunct_child(accessibility_navigation_pointer_table *table,
4296 Eina_List *children, unsigned int current_index, unsigned char forward)
4298 unsigned int children_count = eina_list_count(children);
4299 for(; current_index < children_count; forward ? ++current_index : --current_index)
4301 void *n = eina_list_nth(children, current_index);
4302 if (n && !_object_is_defunct(table, n)) return n;
4307 static void *_directional_depth_first_search_try_non_defunct_child(accessibility_navigation_pointer_table *table,
4308 void *node, Eina_List *children, unsigned char forward)
4310 unsigned int children_count = eina_list_count(children);
4311 if (children_count > 0)
4313 unsigned char is_showing = _get_scrollable_parent(table, node) == NULL ? _object_is_showing(table, node) : 1;
4316 return _find_non_defunct_child(table, children, forward ? 0 : children_count - 1, forward);
4322 static Eina_List *_scrollable_parent_list_get(Eo *obj)
4324 Eina_List *ret = NULL;
4329 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
4332 if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4334 ret = eina_list_append(ret, parent);
4336 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4343 static void _viewport_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
4345 eo_do(obj, elm_interface_scrollable_content_viewport_geometry_get(x, y, w, h));
4346 /* widget implements scrollable interface but does not use scoller
4347 in this case, use widget geometry */
4348 if (*w == 0 || *h == 0)
4350 INF("%s is zero sized content viewport", eo_class_name_get(eo_class_get(obj)));
4351 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_FALSE, x, y, w, h));
4356 _new_scrollable_parent_viewport_geometry_get(Eo *node, Eo *start,
4357 int *x, int *y, int *w, int *h)
4359 Eina_Bool ret = EINA_FALSE;
4363 n_spl = _scrollable_parent_list_get(node);
4364 s_spl = _scrollable_parent_list_get(start);
4368 EINA_LIST_FOREACH(s_spl, l, sp)
4370 n_spl = eina_list_remove(n_spl, sp);
4373 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4375 unsigned int count = eina_list_count(n_spl);
4378 sp = eina_list_nth(n_spl, count - 1);
4379 _viewport_geometry_get(sp, &sx, &sy, &sw, &sh);
4391 static Eina_List *_valid_children_get(Eina_List *children, Eo *start, Eo *root)
4393 /* condition to find first(last) object regardless of scrollable parent.
4394 looping navigation does not care scrollable parent.
4395 1. currently highlighted object exists
4396 2. both start and root are same */
4397 Eo *current = _elm_object_accessibility_currently_highlighted_get();
4398 if (current && start == root) return children;
4401 child = eina_list_nth(children, 0);
4405 Evas_Coord x = 0, y = 0, w = 0, h = 0;
4406 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4408 if (_new_scrollable_parent_viewport_geometry_get(child, start,
4409 &sx, &sy, &sw, &sh))
4411 Eina_List *l, *l_next;
4412 EINA_LIST_FOREACH_SAFE(children, l, l_next, child)
4415 elm_interface_atspi_component_extents_get(EINA_FALSE,
4417 if (w == 0 || h == 0 ||
4418 !ELM_RECTS_INTERSECT(x, y, w, h, sx, sy, sw, sh))
4419 children = eina_list_remove_list(children, l);
4426 static void *_get_next_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4427 void *obj, void *start, void *root, unsigned char forward)
4429 if (!obj) return NULL;
4430 void *parent = CALL(get_parent, obj);
4431 if (!parent) return NULL;
4433 Eina_List *children;
4434 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
4435 children = _valid_children_get(children, start, root);
4437 unsigned int children_count = eina_list_count(children);
4438 if (children_count == 0)
4440 eina_list_free(children);
4443 unsigned int current = 0;
4444 for(; current < children_count && eina_list_nth(children, current) != obj; ++current) ;
4445 if (current >= children_count)
4447 eina_list_free(children);
4450 forward ? ++current : --current;
4451 void *ret = _find_non_defunct_child(table, children, current, forward);
4452 eina_list_free(children);
4457 _directional_depth_first_search_try_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4458 unsigned char *all_children_visited_ptr,
4459 void *node, void *start, void *root,
4460 unsigned char forward)
4464 void *sibling = _get_next_non_defunct_sibling(table, node, start, root, forward);
4465 if (sibling != NULL)
4468 *all_children_visited_ptr = 0;
4473 node = CALL(get_parent, node);
4474 if (node == NULL || node == root) return NULL;
4476 // in backward traversing stop the walk up on parent
4477 if (!forward) break;
4484 unsigned int current_search_size;
4485 unsigned int counter;
4486 } cycle_detection_data;
4488 void cycle_detection_initialize(cycle_detection_data *data, const void *key)
4492 data->current_search_size = 1;
4496 unsigned char cycle_detection_check_if_in_cycle(cycle_detection_data *data, const void *key)
4498 if (!data) return 1;
4499 if (data->key == key) return 1;
4500 if (--data->counter == 0)
4502 data->current_search_size <<= 1;
4503 if (data->current_search_size == 0) return 1;
4504 data->counter = data->current_search_size;
4513 if (eo_isa(obj, ELM_ACCESS_CLASS))
4515 Elm_Access_Info *info;
4517 info = _elm_access_info_get(obj);
4518 if (info && eo_isa(info->part_object, ELM_LAYOUT_CLASS))
4520 Eina_List *attrs, *l;
4521 Elm_Atspi_Attribute *attr;
4523 eo_do(info->part_object,
4524 attrs = elm_interface_atspi_accessible_attributes_get());
4525 EINA_LIST_FOREACH(attrs, l, attr)
4527 if (!strcmp(attr->key, "___PlugID"))
4529 elm_atspi_attributes_list_free(attrs);
4533 elm_atspi_attributes_list_free(attrs);
4540 _proxy_in_parent_get(Eo *obj)
4544 Eina_List *children_list = NULL;
4545 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4548 EINA_LIST_FOREACH(children_list, l, child)
4550 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4556 eina_list_free(children_list);
4562 _deputy_of_proxy_in_parent_get(Eo *obj)
4566 Eina_List *children_list = NULL;
4567 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4569 unsigned int index = 0;
4571 EINA_LIST_FOREACH(children_list, l, child)
4573 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4577 WRN("Proxy does not have deputy object");
4581 deputy = eina_list_nth(children_list, index - 1);
4586 eina_list_free(children_list);
4591 static void *_calculate_neighbor_impl(accessibility_navigation_pointer_table *table, void *root, void *start, unsigned char forward, GetNeighborSearchMode search_mode)
4593 if (root && _object_is_defunct(table, root)) return NULL;
4594 if (start && _object_is_defunct(table, start))
4600 if (search_mode == NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE)
4602 /* This only works if we navigate backward, and it is not possible to
4603 find in embedded process. In this case the deputy should be used */
4604 return _deputy_of_proxy_in_parent_get(start);
4607 void *node = start ? start : root;
4608 if (!node) return NULL;
4610 // initialization of all-children-visited flag for start node - we assume
4611 // that when we begin at start node and we navigate backward, then all children
4612 // are visited, so navigation will ignore start's children and go to
4613 // previous sibling available.
4614 /* Regarding condtion (start != root):
4615 The last object can be found only if all_children_visited is false.
4616 The start is same with root, when looking for the last object. */
4617 unsigned char all_children_visited = (start != root) && (search_mode != NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT && !forward);
4619 // true, if starting element should be ignored. this is only used in rare case of
4620 // recursive search failing to find an object.
4621 // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
4622 // element A algorithm has to descend into BUS_B and search element B and its children. this is done
4623 // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
4624 // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
4625 // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
4626 // this flag means, that object A was already checked previously and we should skip it and its children.
4627 unsigned char force_next = (search_mode == NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING);
4629 cycle_detection_data cycle_detection;
4630 cycle_detection_initialize(&cycle_detection, node);
4633 if (_object_is_defunct(table, node)) return NULL;
4635 // always accept proxy object from different world
4636 if (!force_next && CALL(object_is_proxy, node)) return node;
4638 Eina_List *children;
4639 eo_do(node, children = elm_interface_atspi_accessible_children_get());
4640 children = _valid_children_get(children, start, root);
4643 // 1. not start node
4644 // 2. parent after all children in backward traversing
4645 // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
4646 // Objects with those roles shouldnt be reachable, when navigating next / prev.
4647 unsigned char all_children_visited_or_moving_forward = (eina_list_count(children) == 0 || forward || all_children_visited);
4648 if (!force_next && node != start && all_children_visited_or_moving_forward && _accept_object(table, node))
4650 if (start == NULL || _object_role_is_acceptable_when_navigating_next_prev(table, node))
4652 eina_list_free(children);
4657 void *next_related_in_direction = !force_next ? _get_object_in_relation_flow(table, node, forward) : NULL;
4659 /* force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
4660 in this case the node is elm_layout which is parent of proxy object.
4661 There is an access object working for the proxy object, and the access
4662 object could have relation information. This relation information should
4663 be checked first before using the elm_layout as a node. */
4664 if (force_next && forward)
4667 deputy = _deputy_of_proxy_in_parent_get(node);
4668 next_related_in_direction =
4669 _get_object_in_relation_flow(table, deputy, forward);
4672 if (next_related_in_direction && _object_is_defunct(table, next_related_in_direction))
4673 next_related_in_direction = NULL;
4674 unsigned char want_cycle_detection = 0;
4675 if (next_related_in_direction)
4677 /* Check next_related_in_direction is deputy object */
4681 /* If the prev object is deputy, then go to inside of its proxy first */
4682 if (_deputy_is(next_related_in_direction))
4684 parent = elm_widget_parent_get(next_related_in_direction);
4685 next_related_in_direction =
4686 _proxy_in_parent_get(parent);
4691 /* If current object is deputy, and it has relation next object,
4692 then do not use the relation next object, and use proxy first */
4693 if (_deputy_is(node))
4695 parent = elm_widget_parent_get(node);
4696 next_related_in_direction =
4697 _proxy_in_parent_get(parent);
4701 node = next_related_in_direction;
4702 want_cycle_detection = 1;
4705 void *child = !force_next && !all_children_visited ?
4706 _directional_depth_first_search_try_non_defunct_child(table, node, children, forward) : NULL;
4707 if (child != NULL) want_cycle_detection = 1;
4710 if (!force_next && node == root)
4712 eina_list_free(children);
4715 all_children_visited = 1;
4716 child = _directional_depth_first_search_try_non_defunct_sibling(table, &all_children_visited, node, start, root, forward);
4722 if (want_cycle_detection && cycle_detection_check_if_in_cycle(&cycle_detection, node))
4724 eina_list_free(children);
4727 eina_list_free(children);
4732 typedef struct accessibility_navigation_pointer_table_impl {
4733 accessibility_navigation_pointer_table ptrs;
4735 } accessibility_navigation_pointer_table_impl;
4737 static AtspiRole _object_get_role_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4739 Elm_Atspi_Role role;
4741 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
4742 return _elm_role_to_atspi_role(role);
4745 static uint64_t _object_get_state_set_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4747 Elm_Atspi_State_Set states;
4749 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
4750 return _elm_atspi_state_set_to_atspi_state_set(states);
4753 static void *_get_object_in_relation_by_type_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr, AtspiRelationType type)
4757 const Eo *source = ptr;
4758 Elm_Atspi_Relation_Set relations;
4759 Elm_Atspi_Relation_Type expected_relation_type = _atspi_relation_to_elm_relation(type);
4760 eo_do(source, relations = elm_interface_atspi_accessible_relation_set_get());
4761 Elm_Atspi_Relation *rel;
4763 EINA_LIST_FOREACH(relations, l, rel)
4765 if (rel->type == expected_relation_type)
4767 Eina_List *last = eina_list_last(rel->objects);
4768 return eina_list_data_get(last);
4775 static unsigned char _object_is_zero_size_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4779 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_TRUE, &x, &y, &w, &h));
4780 return w == 0 || h == 0;
4783 unsigned char _object_is_scrollable_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4786 return eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
4789 void *_get_parent_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4791 Eo *obj = (Eo*)ptr, *ret_obj;
4792 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
4796 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)
4798 Eo *obj = (Eo*)ptr, *target;
4799 eo_do(obj, target = elm_interface_atspi_component_accessible_at_point_get(coordinates_are_screen_based, x, y));
4803 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)
4806 Eina_Bool return_value;
4807 eo_do(obj, return_value = elm_interface_atspi_component_contains(coordinates_are_screen_based, x, y));
4808 return return_value ? 1 : 0;
4811 unsigned char _object_is_proxy_impl(struct accessibility_navigation_pointer_table *table_, void *obj)
4813 accessibility_navigation_pointer_table_impl *table = (accessibility_navigation_pointer_table_impl*)table_;
4814 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(table->bridge, pd, 0);
4815 const char *our_bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
4816 const char *obj_bus_name;
4817 _object_get_bus_name_and_path(table->bridge, (Eo*)obj, &obj_bus_name, NULL);
4818 return our_bus_name && obj_bus_name && strcmp(our_bus_name, obj_bus_name) != 0;
4821 accessibility_navigation_pointer_table_impl construct_accessibility_navigation_pointer_table(Eo *bridge)
4823 accessibility_navigation_pointer_table_impl table;
4824 #define INIT(n) table.ptrs.n = _## n ## _impl
4825 INIT(object_get_role);
4826 INIT(object_get_state_set);
4827 INIT(get_object_in_relation_by_type);
4828 INIT(object_is_zero_size);
4830 INIT(object_is_scrollable);
4831 INIT(get_object_at_point);
4832 INIT(object_contains);
4833 INIT(object_is_proxy);
4835 table.bridge = bridge;
4840 static Eo *_calculate_navigable_accessible_at_point(Eo *bridge, Eo *root, Eina_Bool coord_type, int x, int y)
4842 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4843 Eo *result = (Eo*)_calculate_navigable_accessible_at_point_impl(&table.ptrs, root, x, y, coord_type ? 1 : 0);
4847 static Eo *_calculate_neighbor(Eo *bridge, Eo *root, Eo *start, Eina_Bool forward, int search_mode)
4849 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4850 Eo *result = (Eo*)_calculate_neighbor_impl(&table.ptrs, root, start, forward ? 1 : 0, (GetNeighborSearchMode)search_mode);
4856 static Eldbus_Message *
4857 _component_get_extents(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4859 const char *obj_path = eldbus_message_path_get(msg);
4860 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4861 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4863 AtspiCoordType coord_type;
4864 Eldbus_Message *ret;
4865 Eldbus_Message_Iter *iter, *iter_struct;
4867 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4869 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4870 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4872 ret = eldbus_message_method_return_new(msg);
4873 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4875 iter = eldbus_message_iter_get(ret);
4877 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4878 eo_do(obj, elm_interface_atspi_component_extents_get(type, &x, &y, &w, &h));
4879 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
4880 EINA_SAFETY_ON_NULL_GOTO(iter_struct, fail);
4882 eldbus_message_iter_basic_append(iter_struct, 'i', x);
4883 eldbus_message_iter_basic_append(iter_struct, 'i', y);
4884 eldbus_message_iter_basic_append(iter_struct, 'i', w);
4885 eldbus_message_iter_basic_append(iter_struct, 'i', h);
4887 eldbus_message_iter_container_close(iter, iter_struct);
4891 if (ret) eldbus_message_unref(ret);
4895 static Eldbus_Message *
4896 _component_get_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4898 const char *obj_path = eldbus_message_path_get(msg);
4899 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4900 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4902 AtspiCoordType coord_type;
4903 Eldbus_Message *ret;
4905 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4907 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4908 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4910 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4911 eo_do(obj, elm_interface_atspi_component_position_get(type, &x, &y));
4913 ret = eldbus_message_method_return_new(msg);
4914 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4916 eldbus_message_arguments_append(ret, "i", x);
4917 eldbus_message_arguments_append(ret, "i", y);
4922 static Eldbus_Message *
4923 _component_get_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4925 const char *obj_path = eldbus_message_path_get(msg);
4926 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4927 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4929 Eldbus_Message *ret;
4931 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4933 eo_do(obj, elm_interface_atspi_component_size_get(&x, &y));
4935 ret = eldbus_message_method_return_new(msg);
4936 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4938 eldbus_message_arguments_append(ret, "i", x);
4939 eldbus_message_arguments_append(ret, "i", y);
4944 static AtspiComponentLayer
4945 _elm_layer_2_atspi_layer(int layer)
4947 if (layer <= ELM_OBJECT_LAYER_BACKGROUND) return ATSPI_LAYER_CANVAS;
4948 if (layer < ELM_OBJECT_LAYER_FOCUS) return ATSPI_LAYER_WIDGET;
4949 if (layer <= ELM_OBJECT_LAYER_TOOLTIP) return ATSPI_LAYER_POPUP;
4951 return ATSPI_LAYER_OVERLAY;
4954 static Eldbus_Message *
4955 _component_get_layer(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4957 const char *obj_path = eldbus_message_path_get(msg);
4958 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4959 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4961 Eldbus_Message *ret;
4962 AtspiComponentLayer atspi_layer;
4964 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4966 eo_do(obj, layer = elm_interface_atspi_component_layer_get());
4968 ret = eldbus_message_method_return_new(msg);
4969 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4971 atspi_layer = _elm_layer_2_atspi_layer(layer);
4972 eldbus_message_arguments_append(ret, "u", atspi_layer);
4977 static Eldbus_Message *
4978 _component_grab_focus(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4980 const char *obj_path = eldbus_message_path_get(msg);
4981 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4982 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4983 Eldbus_Message *ret;
4984 Eina_Bool focus = EINA_FALSE;
4987 return _dbus_invalid_ref_error_new(msg);
4989 eo_do(obj, focus = elm_interface_atspi_component_focus_grab());
4991 ret = eldbus_message_method_return_new(msg);
4992 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4994 eldbus_message_arguments_append(ret, "b", focus);
4999 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5000 static Eldbus_Message *
5001 _component_grab_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5003 const char *obj_path = eldbus_message_path_get(msg);
5004 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5005 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5006 Eldbus_Message *ret;
5007 Eina_Bool highlight = EINA_FALSE;
5009 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5011 eo_do(obj, highlight = elm_interface_atspi_component_highlight_grab());
5013 ret = eldbus_message_method_return_new(msg);
5014 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5016 eldbus_message_arguments_append(ret, "b", highlight);
5021 static Eldbus_Message *
5022 _component_clear_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5024 const char *obj_path = eldbus_message_path_get(msg);
5025 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5026 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5027 Eldbus_Message *ret;
5028 Eina_Bool highlight = EINA_FALSE;
5030 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5032 eo_do(obj, highlight = elm_interface_atspi_component_highlight_clear());
5034 ret = eldbus_message_method_return_new(msg);
5035 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5037 eldbus_message_arguments_append(ret, "b", highlight);
5043 static Eldbus_Message *
5044 _component_get_alpha(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5046 const char *obj_path = eldbus_message_path_get(msg);
5047 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5048 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5049 Eldbus_Message *ret;
5053 return _dbus_invalid_ref_error_new(msg);
5055 eo_do(obj, alpha = elm_interface_atspi_component_alpha_get());
5057 ret = eldbus_message_method_return_new(msg);
5058 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5060 eldbus_message_arguments_append(ret, "d", alpha);
5065 static Eldbus_Message *
5066 _component_set_extends(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5068 const char *obj_path = eldbus_message_path_get(msg);
5069 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5070 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5072 AtspiCoordType coord_type;
5073 Eldbus_Message *ret;
5074 Eina_Bool result = EINA_FALSE;
5076 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5078 if (!eldbus_message_arguments_get(msg, "iiiiu", &x, &y, &w, &h, &coord_type))
5079 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5081 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5082 eo_do(obj, result = elm_interface_atspi_component_extents_set(type, x, y, w, h));
5084 ret = eldbus_message_method_return_new(msg);
5085 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5087 eldbus_message_arguments_append(ret, "b", result);
5092 static Eldbus_Message *
5093 _component_set_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5095 const char *obj_path = eldbus_message_path_get(msg);
5096 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5097 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5099 Eina_Bool result = EINA_FALSE;
5100 AtspiCoordType coord_type;
5101 Eldbus_Message *ret;
5103 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5105 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
5106 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5108 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5109 eo_do(obj, result = elm_interface_atspi_component_position_set(type, x, y));
5111 ret = eldbus_message_method_return_new(msg);
5112 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5114 eldbus_message_arguments_append(ret, "b", result);
5119 static Eldbus_Message *
5120 _component_set_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5122 const char *obj_path = eldbus_message_path_get(msg);
5123 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5124 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5127 Eldbus_Message *ret;
5129 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5131 if (!eldbus_message_arguments_get(msg, "ii", &w, &h))
5132 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5134 eo_do(obj, result = elm_interface_atspi_component_size_set(w, h));
5136 ret = eldbus_message_method_return_new(msg);
5137 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5139 eldbus_message_arguments_append(ret, "b", result);
5144 static const Eldbus_Method component_methods[] = {
5145 { "Contains", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "contains"}), _component_contains, 0 },
5146 { "GetAccessibleAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)", "accessible"}), _component_get_accessible_at_point, 0 },
5147 { "GetExtents", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"(iiii)", "extents"}), _component_get_extents, 0 },
5148 { "GetPosition", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"i", "x"}, {"i","y"}), _component_get_position, 0 },
5149 { "GetSize", NULL, ELDBUS_ARGS({"i", "w"}, {"i", "h"}), _component_get_size, 0 },
5150 { "GetLayer", NULL, ELDBUS_ARGS({"u", "layer"}), _component_get_layer, 0 },
5151 // { "GetMDIZOrder", NULL, ELDBUS_ARGS({"n", "MDIZOrder"}), _component_get_mdizorder, 0 },
5152 { "GrabFocus", NULL, ELDBUS_ARGS({"b", "focus"}), _component_grab_focus, 0 },
5153 { "GetAlpha", NULL, ELDBUS_ARGS({"d", "alpha"}), _component_get_alpha, 0 },
5154 { "SetExtents", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "width"}, {"i", "height"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_extends, 0 },
5155 { "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
5156 { "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
5158 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5159 { "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
5160 { "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
5162 { NULL, NULL, NULL, NULL, 0 }
5165 static const Eldbus_Service_Interface_Desc component_iface_desc = {
5166 ATSPI_DBUS_INTERFACE_COMPONENT, component_methods, NULL, NULL, NULL, NULL
5170 _on_elm_atspi_bridge_app_register(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
5172 const char *errname, *errmsg;
5174 if (eldbus_message_error_get(msg, &errname, &errmsg))
5176 ERR("%s %s", errname, errmsg);
5179 DBG("Application successfuly registered at ATSPI2 bus.");
5183 _elm_atspi_bridge_app_register(Eo *bridge)
5185 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5187 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5188 ATSPI_DBUS_PATH_ROOT,
5189 ATSPI_DBUS_INTERFACE_SOCKET,
5191 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5193 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
5194 eldbus_connection_send(pd->a11y_bus, message, _on_elm_atspi_bridge_app_register, NULL, -1);
5200 _elm_atspi_bridge_app_unregister(Eo *bridge)
5203 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5205 root = elm_atspi_bridge_root_get(bridge);
5207 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5208 ATSPI_DBUS_PATH_ROOT,
5209 ATSPI_DBUS_INTERFACE_SOCKET,
5211 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5213 _bridge_iter_object_reference_append(bridge, iter, root);
5214 eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1);
5220 _cache_register(Eo *obj)
5222 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
5223 pd->cache_interface = eldbus_service_interface_register(pd->a11y_bus, CACHE_INTERFACE_PATH, &cache_iface_desc);
5224 eldbus_service_object_data_set(pd->cache_interface, ELM_ATSPI_BRIDGE_CLASS_NAME, obj);
5228 _set_broadcast_flag(const char *event, Eo *bridge)
5231 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5233 tokens = eina_str_split(event, ":", 3);
5235 if (!tokens) return;
5237 if (!strcmp(tokens[0], "Object"))
5239 if (!tokens[1] || *tokens[1] == '\0') return; // do not handle "Object:*"
5240 else if (!strcmp(tokens[1], "StateChanged"))
5242 if (!tokens[2] || *tokens[2] == '\0')
5243 pd->object_state_broadcast_mask = -1; // broadcast all
5244 eina_str_tolower(&tokens[2]);
5245 struct atspi_state_desc *sd = eina_hash_find(pd->state_hash, tokens[2]);
5247 STATE_TYPE_SET(pd->object_state_broadcast_mask, sd->elm_state);
5249 else if (!strcmp(tokens[1], "PropertyChange"))
5251 if (!tokens[2] || *tokens[2] == '\0')
5252 pd->object_property_broadcast_mask = -1; //broadcast all
5253 else if (!strcmp(tokens[2], "AccessibleValue"))
5254 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_VALUE);
5255 else if (!strcmp(tokens[2], "AccessibleName"))
5256 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_NAME);
5257 else if (!strcmp(tokens[2], "AccessibleDescription"))
5258 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_DESCRIPTION);
5259 else if (!strcmp(tokens[2], "AccessibleParent"))
5260 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_PARENT);
5261 else if (!strcmp(tokens[2], "AccessibleRole"))
5262 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_ROLE);
5264 else if (!strcmp(tokens[1], "ChildrenChanged"))
5266 if (!tokens[2] || *tokens[2] == '\0')
5267 pd->object_children_broadcast_mask = -1; // broadcast all
5268 else if (!strcmp(tokens[2], "add"))
5269 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_ADDED);
5270 else if (!strcmp(tokens[2], "remove"))
5271 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_REMOVED);
5273 else if (!strcmp(tokens[1], "TextChanged"))
5274 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED);
5275 else if (!strcmp(tokens[1], "TextCaretMoved"))
5276 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED);
5277 else if (!strcmp(tokens[1], "TextBoundsChanged"))
5278 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED);
5279 else if (!strcmp(tokens[1], "TextSelectionChanged"))
5280 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED);
5281 else if (!strcmp(tokens[1], "TextAttributesChanged"))
5282 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED);
5283 else if (!strcmp(tokens[1], "VisibleDataChanged"))
5284 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED);
5285 else if (!strcmp(tokens[1], "ActiveDescendantChanged"))
5286 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED);
5287 else if (!strcmp(tokens[1], "BoundsChanged"))
5288 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_BOUNDS_CHANGED);
5289 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5290 else if (!strcmp(tokens[1], "MoveOuted"))
5291 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED);
5294 else if (!strcmp(tokens[0], "Window"))
5296 if (!tokens[1] || *tokens[1] == '\0')
5297 pd->window_signal_broadcast_mask = -1; // broadcast all
5298 else if (!strcmp(tokens[1], "Create"))
5299 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_CREATE);
5300 else if (!strcmp(tokens[1], "Destroy"))
5301 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DESTROY);
5302 else if (!strcmp(tokens[1], "Activate"))
5303 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_ACTIVATE);
5304 else if (!strcmp(tokens[1], "Deactivate"))
5305 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DEACTIVATE);
5306 else if (!strcmp(tokens[1], "Maximize"))
5307 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MAXIMIZE);
5308 else if (!strcmp(tokens[1], "Minimize"))
5309 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MINIMIZE);
5310 else if (!strcmp(tokens[1], "Resize"))
5311 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESIZE);
5312 else if (!strcmp(tokens[1], "Restore"))
5313 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESTORE);
5321 _registered_listeners_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
5323 const char *event, *bus;
5325 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
5326 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
5328 DBG("Updating registered ATSPI signals list.");
5329 pd->object_broadcast_mask = 0;
5330 pd->object_children_broadcast_mask = 0;
5331 pd->object_property_broadcast_mask = 0;
5332 pd->object_state_broadcast_mask = 0;
5333 pd->window_signal_broadcast_mask = 0;
5335 if (eldbus_message_error_get(msg, &event, &bus))
5337 WRN("%s %s", event, bus);
5340 Eldbus_Message_Iter *iter, *siter;
5341 if (!eldbus_message_arguments_get(msg, "a(ss)", &iter))
5343 ERR("Invalid answer type from GetRegisteredEvents method call!");
5346 while (eldbus_message_iter_get_and_next(iter, 'r', &siter))
5348 eldbus_message_iter_arguments_get(siter, "ss", &bus, &event);
5349 _set_broadcast_flag(event, data);
5354 //TIZEN_ONLY(20170910) atspi: emit signal after atspi bridge is connected
5355 pd->connected = EINA_TRUE;
5356 eo_do(data, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_CONNECTED, NULL));
5357 _elm_win_atspi(EINA_TRUE);
5361 eo_do(data, root = elm_obj_atspi_bridge_root_get());
5362 _bridge_cache_build(data, root);
5364 // initialize pending proxy
5365 EINA_LIST_FREE(pd->socket_queue, pr)
5366 _socket_ifc_create(pd->a11y_bus, pr);
5367 EINA_LIST_FREE(pd->plug_queue, pr)
5368 _plug_connect(pd->a11y_bus, pr);
5370 pd->socket_queue = pd->plug_queue = NULL;
5375 _registered_events_list_update(Eo *bridge)
5377 Eldbus_Message *msg;
5378 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5381 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "GetRegisteredEvents");
5382 p = eldbus_connection_send(pd->a11y_bus, msg, _registered_listeners_get, bridge, -1);
5383 pd->pending_requests = eina_list_append(pd->pending_requests, p);
5387 _handle_listener_change(void *data, const Eldbus_Message *msg EINA_UNUSED)
5389 _registered_events_list_update(data);
5392 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5394 _scroll_gesture_required_is(Eo *obj)
5396 Eina_Bool ret = EINA_FALSE;
5397 Eina_List *l, *attr_list = NULL;
5398 Elm_Atspi_Attribute *attr = NULL;
5400 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5401 EINA_LIST_FOREACH(attr_list, l, attr)
5403 if (!strcmp(attr->key, "gesture_required") && !strcmp(attr->value, "scroll"))
5410 elm_atspi_attributes_list_free(attr_list);
5417 _state_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5419 Elm_Atspi_Event_State_Changed_Data *state_data = event_info;
5420 const char *type_desc;
5421 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5423 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
5424 if ((state_data->type == ELM_ATSPI_STATE_ACTIVE) && eo_isa(obj, ELM_WIN_CLASS))
5426 pd->window_activated = state_data->new_value;
5429 // TIZEN_ONLY(20161209): reduce IPC of object:state-changed:showing
5430 if ((state_data->type == ELM_ATSPI_STATE_SHOWING) ||
5431 (state_data->type == ELM_ATSPI_STATE_VISIBLE))
5433 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5434 Elm_Atspi_State_Set ss;
5436 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5437 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
5438 if (state_data->new_value) /* Showing */
5440 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5441 (role != ELM_ATSPI_ROLE_PAGE_TAB) &&
5442 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)))
5445 else /* Not Showing */
5447 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5448 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)) &&
5449 (_elm_object_accessibility_currently_highlighted_get() != (void *)obj))
5455 if (!STATE_TYPE_GET(pd->object_state_broadcast_mask, state_data->type))
5458 if ((state_data->type > ELM_ATSPI_STATE_LAST_DEFINED) ||
5459 (int)state_data->type < 0)
5462 type_desc = elm_states_to_atspi_state[state_data->type].name;
5464 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5465 unsigned int det2 = 0;
5466 if ((state_data->type == ELM_ATSPI_STATE_HIGHLIGHTED) &&
5467 (_scroll_gesture_required_is(obj)))
5470 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5471 &_event_obj_signals[ATSPI_OBJECT_EVENT_STATE_CHANGED], type_desc, state_data->new_value, det2, NULL);
5477 _bounds_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5479 Elm_Atspi_Event_Geometry_Changed_Data *geo_data = event_info;
5481 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5482 &_event_obj_signals[ATSPI_OBJECT_EVENT_BOUNDS_CHANGED], "", 0, 0, "(iiii)",
5483 geo_data->x, geo_data->y, geo_data->width, geo_data->height);
5488 _property_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5490 const char *property = event_info;
5492 enum _Atspi_Object_Property prop = ATSPI_OBJECT_PROPERTY_LAST;
5494 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5496 if (!strcmp(property, "parent"))
5498 prop = ATSPI_OBJECT_PROPERTY_PARENT;
5499 atspi_desc = "accessible-parent";
5501 else if (!strcmp(property, "name"))
5503 prop = ATSPI_OBJECT_PROPERTY_NAME;
5504 atspi_desc = "accessible-name";
5506 else if (!strcmp(property, "description"))
5508 prop = ATSPI_OBJECT_PROPERTY_DESCRIPTION;
5509 atspi_desc = "accessible-description";
5511 else if (!strcmp(property, "role"))
5513 prop = ATSPI_OBJECT_PROPERTY_ROLE;
5514 atspi_desc = "accessible-role";
5516 else if (!strcmp(property, "value"))
5518 prop = ATSPI_OBJECT_PROPERTY_VALUE;
5519 atspi_desc = "accessible-value";
5521 if (prop == ATSPI_OBJECT_PROPERTY_LAST)
5523 ERR("Unrecognized property name!");
5526 if (!STATE_TYPE_GET(pd->object_property_broadcast_mask, prop))
5528 DBG("Masking property %s changed event.", property);
5532 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5533 &_event_obj_signals[ATSPI_OBJECT_EVENT_PROPERTY_CHANGED], atspi_desc, 0, 0, NULL, NULL);
5538 _visible_data_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5540 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5542 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED))
5545 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5546 &_event_obj_signals[ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED], "",
5553 _active_descendant_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5555 Eo *child = event_info;
5558 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5560 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED))
5563 eo_do(child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5565 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5566 &_event_obj_signals[ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED], "",
5567 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), child);
5572 _children_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5574 const char *atspi_desc = NULL;
5575 Elm_Atspi_Event_Children_Changed_Data *ev_data = event_info;
5577 enum _Atspi_Object_Child_Event_Type type;
5579 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5581 type = ev_data->is_added ? ATSPI_OBJECT_CHILD_ADDED : ATSPI_OBJECT_CHILD_REMOVED;
5583 // update cached objects
5584 if (ev_data->is_added)
5585 _bridge_cache_build(data, ev_data->child);
5587 if (!STATE_TYPE_GET(pd->object_children_broadcast_mask, type))
5592 case ATSPI_OBJECT_CHILD_ADDED:
5594 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5596 case ATSPI_OBJECT_CHILD_REMOVED:
5597 atspi_desc = "remove";
5598 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5602 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5603 &_event_obj_signals[ATSPI_OBJECT_EVENT_CHILDREN_CHANGED], atspi_desc,
5604 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), ev_data->child);
5609 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5611 _move_outed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5613 const Elm_Atspi_Move_Outed_Type *type = event_info;
5615 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5617 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED))
5619 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5620 &_event_obj_signals[ATSPI_OBJECT_EVENT_MOVE_OUTED], "", *type, 0, NULL, NULL);
5626 _window_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info EINA_UNUSED)
5628 enum _Atspi_Window_Signals type;
5630 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5632 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED)
5633 type = ATSPI_WINDOW_EVENT_CREATE;
5634 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED)
5635 type = ATSPI_WINDOW_EVENT_DESTROY;
5636 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DEACTIVATED)
5637 type = ATSPI_WINDOW_EVENT_DEACTIVATE;
5638 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5639 type = ATSPI_WINDOW_EVENT_ACTIVATE;
5640 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MAXIMIZED)
5641 type = ATSPI_WINDOW_EVENT_MAXIMIZE;
5642 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MINIMIZED)
5643 type = ATSPI_WINDOW_EVENT_MINIMIZE;
5644 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_RESTORED)
5645 type = ATSPI_WINDOW_EVENT_RESTORE;
5649 if (!STATE_TYPE_GET(pd->window_signal_broadcast_mask, type))
5654 ERR("A11Y connection closed. Unable to send ATSPI event.");
5658 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_WINDOW,
5659 &_window_obj_signals[type], "", 0, 0, "i", 0);
5664 _selection_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5666 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5668 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_SELECTION_CHANGED))
5671 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5672 &_event_obj_signals[ATSPI_OBJECT_EVENT_SELECTION_CHANGED], "", 0, 0, "i", 0);
5676 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, ...)
5678 Eldbus_Message *msg;
5679 Eldbus_Message_Iter *iter , *iter_stack[64], *iter_struct;
5685 EINA_SAFETY_ON_NULL_RETURN(infc);
5686 EINA_SAFETY_ON_NULL_RETURN(signal);
5687 EINA_SAFETY_ON_NULL_RETURN(minor);
5688 EINA_SAFETY_ON_NULL_RETURN(obj);
5689 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5691 path = _bridge_path_from_object(bridge, obj);
5693 msg = eldbus_message_signal_new(path, infc, signal->name);
5696 va_start(va, variant_sig);
5698 iter = eldbus_message_iter_get(msg);
5699 eldbus_message_iter_arguments_append(iter, "sii", minor, det1, det2);
5703 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', variant_sig);
5705 const char *tmp = variant_sig;
5711 iter_stack[top + 1] = eldbus_message_iter_container_new(iter_stack[top], 'r', NULL);
5715 eldbus_message_iter_basic_append(iter_stack[top], 's', va_arg(va, char*));
5718 eldbus_message_iter_basic_append(iter_stack[top], 'i', va_arg(va, int));
5721 atspi_obj = va_arg(va, Eo*);
5722 path = _bridge_path_from_object(bridge, atspi_obj);
5723 eldbus_message_iter_basic_append(iter_stack[top], 'o', path);
5726 eldbus_message_iter_container_close(iter_stack[top - 1], iter_stack[top]);
5730 ERR("Not supported d-bus type: %c.", *tmp);
5736 else // AT-SPI implementation forces checks on variant in signature even if not used.
5738 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', "i");
5739 eldbus_message_iter_basic_append(iter_stack[top], 'i', 0);
5744 ERR("Invalid d-bus signature: () do not match.");
5746 eldbus_message_iter_container_close(iter, iter_stack[0]);
5748 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
5749 path = _bridge_path_from_object(bridge, elm_atspi_bridge_root_get(bridge));
5750 eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
5751 eldbus_message_iter_basic_append(iter_struct, 'o', path);
5752 eldbus_message_iter_container_close(iter, iter_struct);
5754 eldbus_connection_send(pd->a11y_bus, msg, NULL, NULL, -1);
5755 DBG("Send %s.%s[%s,%d,%d]", infc, signal->name, minor, det1, det2);
5759 _text_caret_moved_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5763 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5765 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED))
5768 eo_do(obj, cursor_pos = elm_interface_atspi_text_caret_offset_get());
5770 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5771 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED], "", cursor_pos, 0, NULL, NULL);
5777 _text_text_inserted_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5779 Elm_Atspi_Text_Change_Info *info = event_info;
5781 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5783 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5786 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5787 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "insert", info->pos, info->len, "s", info->content);
5793 _text_text_removed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5795 Elm_Atspi_Text_Change_Info *info = event_info;
5797 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5799 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5802 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5803 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "delete", info->pos, info->len, "s", info->content);
5809 _text_selection_changed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5811 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5813 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED))
5816 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5817 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED], "", 0, 0, NULL, NULL);
5822 //TIZEN_ONLY(20160527) - Add direct reading feature
5824 _on_reading_state_changed(void *data EINA_UNUSED, const Eldbus_Message *msg)
5827 const char *say_signal_name = "";
5828 Elm_Atspi_Say_Info *say_info;
5830 if (eldbus_message_arguments_get(msg, "is", &i, &say_signal_name))
5831 { if (read_command_id)
5833 say_info = eina_hash_find(read_command_id, &i);
5836 if (say_info->func && say_signal_name)
5837 say_info->func(say_info->data, say_signal_name);
5838 eina_hash_del(read_command_id, &i, NULL);
5847 _event_handlers_register(Eo *bridge)
5849 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5851 _registered_events_list_update(bridge);
5853 // register signal handlers in order to update list of registered listeners of ATSPI-Clients
5854 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);
5855 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);
5856 //TIZEN_ONLY(20160527) - Add direct reading feature
5857 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);
5859 pd->key_flr = ecore_event_filter_add(NULL, _elm_atspi_bridge_key_filter, NULL, bridge);
5863 _bridge_object_unregister(Eo *bridge, Eo *obj)
5865 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5867 eina_hash_del(pd->cache, &obj, obj);
5871 _on_object_add(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
5873 Eldbus_Message *sig;
5874 Eldbus_Message_Iter *iter;
5876 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5878 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_ADDED);
5879 iter = eldbus_message_iter_get(sig);
5880 _cache_item_reference_append_cb(data, obj, iter);
5882 eldbus_service_signal_send(pd->cache_interface, sig);
5888 _on_object_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
5890 Eldbus_Message *sig;
5892 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5894 _bridge_object_unregister(data, obj);
5896 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_REMOVED);
5897 Eldbus_Message_Iter *iter = eldbus_message_iter_get(sig);
5898 _bridge_iter_object_reference_append(data, iter, obj);
5899 eldbus_service_signal_send(pd->cache_interface, sig);
5905 _bridge_cache_build(Eo *bridge, void *obj)
5907 Eina_List *children;
5908 Elm_Atspi_State_Set ss;
5911 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5913 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
5916 if (!eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
5917 _bridge_object_register(bridge, obj);
5919 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
5920 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
5922 if (eo_isa(obj, ELM_INTERFACE_ATSPI_WINDOW_INTERFACE))
5924 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_ACTIVE))
5926 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
5927 pd->window_activated = EINA_TRUE;
5932 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
5933 pd->window_activated = EINA_FALSE;
5937 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
5938 EINA_LIST_FREE(children, child)
5939 _bridge_cache_build(bridge, child);
5943 _interfaces_unregister(Eo *bridge)
5945 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5947 #define INTERFACE_SAFE_FREE(ifc) \
5949 eldbus_service_interface_unregister(ifc); \
5952 INTERFACE_SAFE_FREE(pd->interfaces.accessible);
5953 INTERFACE_SAFE_FREE(pd->interfaces.application);
5954 INTERFACE_SAFE_FREE(pd->interfaces.action);
5955 INTERFACE_SAFE_FREE(pd->interfaces.component);
5956 INTERFACE_SAFE_FREE(pd->interfaces.collection);
5957 INTERFACE_SAFE_FREE(pd->interfaces.editable_text);
5958 INTERFACE_SAFE_FREE(pd->interfaces.image);
5959 INTERFACE_SAFE_FREE(pd->interfaces.selection);
5960 INTERFACE_SAFE_FREE(pd->interfaces.text);
5961 INTERFACE_SAFE_FREE(pd->interfaces.value);
5965 _a11y_connection_shutdown(Eo *bridge)
5967 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5968 Eldbus_Pending *pending;
5971 _elm_atspi_bridge_app_unregister(bridge);
5974 eina_hash_free(pd->cache);
5977 if (pd->cache_interface)
5978 eldbus_service_object_unregister(pd->cache_interface);
5979 pd->cache_interface = NULL;
5981 _interfaces_unregister(bridge);
5983 if (pd->key_flr) ecore_event_filter_del(pd->key_flr);
5986 if (pd->register_hdl) eldbus_signal_handler_del(pd->register_hdl);
5987 pd->register_hdl = NULL;
5989 if (pd->unregister_hdl) eldbus_signal_handler_del(pd->unregister_hdl);
5990 pd->unregister_hdl = NULL;
5992 //TIZEN_ONLY(20160527) - Add direct reading feature
5993 if (pd->reading_state_changed_hdl) eldbus_signal_handler_del(pd->reading_state_changed_hdl);
5994 pd->reading_state_changed_hdl = NULL;
5997 EINA_LIST_FREE(pd->pending_requests, pending)
5998 eldbus_pending_cancel(pending);
5999 pd->pending_requests = NULL;
6001 if (pd->a11y_bus) eldbus_connection_unref(pd->a11y_bus);
6002 pd->a11y_bus = NULL;
6004 if (pd->state_hash) eina_hash_free(pd->state_hash);
6005 pd->state_hash = NULL;
6007 if (pd->event_hash) eina_hash_free(pd->event_hash);
6008 pd->event_hash = NULL;
6010 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, elm_interface_atspi_accessible_event_handler_del(pd->event_hdlr));
6011 pd->event_hdlr = NULL;
6013 eo_do(bridge, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, NULL));
6014 pd->connected = EINA_FALSE;
6017 static void _disconnect_cb(void *data, Eldbus_Connection *conn EINA_UNUSED, void *event_info EINA_UNUSED)
6019 _a11y_connection_shutdown(data);
6023 _interfaces_register(Eo *bridge)
6025 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6027 pd->interfaces.accessible =
6028 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &accessible_iface_desc);
6029 eldbus_service_object_data_set(pd->interfaces.accessible, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6031 pd->interfaces.application =
6032 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &application_iface_desc);
6033 eldbus_service_object_data_set(pd->interfaces.application, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6035 pd->interfaces.action =
6036 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &action_iface_desc);
6037 eldbus_service_object_data_set(pd->interfaces.action, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6039 pd->interfaces.component =
6040 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &component_iface_desc);
6041 eldbus_service_object_data_set(pd->interfaces.component, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6043 pd->interfaces.collection =
6044 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &collection_iface_desc);
6045 eldbus_service_object_data_set(pd->interfaces.collection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6047 pd->interfaces.editable_text =
6048 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &editable_text_iface_desc);
6049 eldbus_service_object_data_set(pd->interfaces.editable_text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6051 pd->interfaces.image =
6052 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &image_iface_desc);
6053 eldbus_service_object_data_set(pd->interfaces.image, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6055 pd->interfaces.selection =
6056 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &selection_iface_desc);
6057 eldbus_service_object_data_set(pd->interfaces.selection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6059 pd->interfaces.text =
6060 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &text_iface_desc);
6061 eldbus_service_object_data_set(pd->interfaces.text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6063 pd->interfaces.value =
6064 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &value_iface_desc);
6065 eldbus_service_object_data_set(pd->interfaces.value, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6069 _bridge_accessible_event_dispatch(void *data, Eo *accessible, const Eo_Event_Description *desc, void *event_info)
6071 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6073 _bridge_object_register(data, accessible);
6075 Eo_Event_Cb cb = eina_hash_find(pd->event_hash, &desc);
6076 return cb ? cb(data, accessible, desc, event_info) : EINA_TRUE;
6080 _a11y_bus_initialize(Eo *obj, const char *socket_addr)
6082 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
6083 pd->a11y_bus = eldbus_private_address_connection_get(socket_addr);
6087 eldbus_connection_event_callback_add(pd->a11y_bus, ELDBUS_CONNECTION_EVENT_DISCONNECTED, _disconnect_cb, obj);
6089 // init data structures
6090 pd->cache = eina_hash_pointer_new(NULL);
6091 pd->state_hash = _elm_atspi_state_hash_build();
6092 pd->event_hash = _elm_atspi_event_hash_build();
6095 _cache_register(obj);
6096 _interfaces_register(obj);
6097 _event_handlers_register(obj);
6098 if (!getenv("ELM_ATSPI_NO_EMBED"))
6099 _elm_atspi_bridge_app_register(obj);
6101 // register accesible object event listener
6102 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, pd->event_hdlr = elm_interface_atspi_accessible_event_handler_add(_bridge_accessible_event_dispatch, obj));
6107 _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6109 const char *errname, *errmsg, *sock_addr = NULL;
6110 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6112 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6114 if (eldbus_message_error_get(msg, &errname, &errmsg))
6116 ERR("%s %s", errname, errmsg);
6120 if (!eldbus_message_arguments_get(msg, "s", &sock_addr) || !sock_addr)
6122 ERR("Could not get A11Y Bus socket address.");
6126 _a11y_socket_address = eina_stringshare_add(sock_addr);
6127 _a11y_bus_initialize((Eo*)data, sock_addr);
6130 static void _a11y_connection_init(Eo *bridge)
6132 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6133 Eina_Bool is_connected;
6135 eo_do(bridge, is_connected = elm_obj_atspi_bridge_connected_get());
6137 if (is_connected) return;
6139 // TIZEN_ONLY(20170512): send window activated event to at_spi2 only once per session
6140 pd->window_activated_broadcast_needed = EINA_TRUE;
6142 Eldbus_Message *m = eldbus_object_method_call_new(pd->bus_obj, A11Y_DBUS_INTERFACE, "GetAddress");
6143 Eldbus_Pending *p = eldbus_object_send(pd->bus_obj, m, _a11y_bus_address_get, bridge, 100);
6146 pd->pending_requests = eina_list_append(pd->pending_requests, p);
6150 _screen_reader_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6152 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6153 const char *errname, *errmsg;
6154 Eina_Bool is_enabled;
6155 Eldbus_Message_Iter *variant;
6157 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6159 if (eldbus_message_error_get(msg, &errname, &errmsg))
6161 WRN("%s %s", errname, errmsg);
6164 if (!eldbus_message_arguments_get(msg, "v", &variant))
6166 ERR("'ScreenReaderEnabled' not packed into variant.");
6169 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6171 ERR("Could not get 'ScreenReaderEnabled' boolean property");
6174 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6175 pd->screen_reader_enabled = !!is_enabled;
6177 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6178 //register/unregister access objects accordingly.
6179 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6180 _elm_win_screen_reader(is_enabled);
6185 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6187 _at_spi_client_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6189 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6190 const char *errname, *errmsg;
6191 Eina_Bool is_enabled;
6192 Eldbus_Message_Iter *variant;
6194 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6196 if (eldbus_message_error_get(msg, &errname, &errmsg))
6198 WRN("%s %s", errname, errmsg);
6201 if (!eldbus_message_arguments_get(msg, "v", &variant))
6203 ERR("'" A11Y_DBUS_ENABLED_PROPERTY "' not packed into variant.");
6206 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6208 ERR("Could not get '" A11Y_DBUS_ENABLED_PROPERTY "' boolean property");
6212 _a11y_connection_init(data);
6215 _elm_win_atspi(EINA_FALSE);
6216 DBG("AT-SPI2 stack not enabled.");
6222 static void _bridge_object_register(Eo *bridge, Eo *obj)
6224 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6226 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6228 WRN("Unable to register class w/o Elm_Interface_Atspi_Accessible!");
6232 if (eina_hash_find(pd->cache, &obj))
6235 eina_hash_add(pd->cache, &obj, obj);
6239 _elm_atspi_bridge_init(void)
6243 _instance = eo_add(ELM_ATSPI_BRIDGE_CLASS, NULL);
6249 _elm_atspi_bridge_get(void)
6255 _elm_atspi_bridge_shutdown(void)
6262 if (_a11y_socket_address)
6263 eina_stringshare_del(_a11y_socket_address);
6264 _a11y_socket_address = NULL;
6267 static Key_Event_Info*
6268 _key_event_info_new(int event_type, const Ecore_Event_Key *data, Eo *bridge)
6270 Key_Event_Info *ret;
6271 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
6273 ret = calloc(sizeof(Key_Event_Info), 1);
6275 ret->type = event_type;
6277 ret->bridge = bridge;
6279 ret->event.keyname = eina_stringshare_add(data->keyname);
6280 ret->event.key = eina_stringshare_add(data->key);
6281 ret->event.string = eina_stringshare_add(data->string);
6282 ret->event.compose = eina_stringshare_add(data->compose);
6284 // not sure why it is here, but explicite keep it NULLed.
6285 ret->event.data = NULL;
6291 _key_event_info_free(Key_Event_Info *data)
6293 EINA_SAFETY_ON_NULL_RETURN(data);
6295 eina_stringshare_del(data->event.keyname);
6296 eina_stringshare_del(data->event.key);
6297 eina_stringshare_del(data->event.string);
6298 eina_stringshare_del(data->event.compose);
6304 _iter_marshall_key_event(Eldbus_Message_Iter *iter, Key_Event_Info *data)
6306 Eldbus_Message_Iter *struct_iter;
6307 EINA_SAFETY_ON_NULL_RETURN(data);
6309 struct_iter = eldbus_message_iter_container_new(iter, 'r', NULL);
6311 const char *str = data->event.keyname ? data->event.keyname : "";
6312 int is_text = data->event.keyname ? 1 : 0;
6314 if (data->type == ECORE_EVENT_KEY_DOWN)
6315 type = ATSPI_KEY_PRESSED_EVENT;
6317 type = ATSPI_KEY_RELEASED_EVENT;
6319 eldbus_message_iter_arguments_append(struct_iter, "uiiiisb", type, 0, data->event.keycode, 0, data->event.timestamp, str, is_text);
6320 eldbus_message_iter_container_close(iter, struct_iter);
6324 _on_event_del(void *user_data, void *func_data EINA_UNUSED)
6326 Key_Event_Info *info = user_data;
6327 _key_event_info_free(info);
6331 _on_listener_answer(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6333 Key_Event_Info *info = data;
6334 const char *errname, *errmsg;
6335 Eina_Bool ret = EINA_TRUE;
6337 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(info->bridge, pd);
6339 if (eldbus_message_error_get(msg, &errname, &errmsg))
6341 ERR("%s %s", errname, errmsg);
6344 if (!eldbus_message_arguments_get(msg, "b", &ret))
6346 ERR("Return message doen not contian return value");
6351 _key_event_info_free(info);
6355 ecore_event_add(info->type, &info->event, _on_event_del, info);
6356 pd->reemited_events = eina_list_append(pd->reemited_events, &info->event);
6360 _elm_atspi_bridge_key_filter(void *data, void *loop EINA_UNUSED, int type, void *event)
6362 Eldbus_Message *msg;
6363 Eldbus_Message_Iter *iter;
6364 Ecore_Event_Key *key_event = event;
6368 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_TRUE);
6370 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6371 if (!pd->window_activated) return EINA_TRUE;
6374 if ((type != ECORE_EVENT_KEY_DOWN) && (type != ECORE_EVENT_KEY_UP)) return EINA_TRUE;
6376 // check if reemited
6377 if (eina_list_data_find(pd->reemited_events, event))
6379 pd->reemited_events = eina_list_remove(pd->reemited_events, event);
6383 // TIZEN_ONLY(20170118): Not handle events if keyboard is on
6386 Eina_List *children, *l;
6388 eo_do(pd->root, children = elm_interface_atspi_accessible_children_get());
6390 EINA_LIST_FOREACH(children, l, child)
6392 if (elm_widget_focus_get(child)) break;
6394 eina_list_free(children);
6396 Elm_Win_Keyboard_Mode mode;
6397 mode = elm_win_keyboard_mode_get(child);
6398 if (mode == ELM_WIN_KEYBOARD_ON) return EINA_TRUE;
6402 ke = _key_event_info_new(type, key_event, bridge);
6403 if (!ke) return EINA_TRUE;
6405 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_DEC,
6406 ATSPI_DBUS_INTERFACE_DEC, "NotifyListenersSync");
6407 iter = eldbus_message_iter_get(msg);
6408 _iter_marshall_key_event(iter, ke);
6410 // timeout should be kept reasonaby low to avoid delays
6411 if (!eldbus_connection_send(pd->a11y_bus, msg, _on_listener_answer, ke, 100))
6418 _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6420 return pd->connected;
6424 _elm_atspi_bridge_root_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6428 pd->root = eo_add(ELM_ATSPI_APP_OBJECT_CLASS, NULL);
6429 elm_interface_atspi_accessible_added(pd->root);
6436 _properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
6438 Eldbus_Proxy_Event_Property_Changed *ev = event;
6441 const char *ifc = eldbus_proxy_interface_get(ev->proxy);
6442 if (ev->name && !strcmp(ev->name, "ScreenReaderEnabled" ) &&
6443 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6445 if (!eina_value_get(ev->value, &val))
6447 ERR("Unable to get ScreenReaderEnabled property value");
6450 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6451 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6452 pd->screen_reader_enabled = !!val;
6454 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6455 //register/unregister access objects accordingly.
6456 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6457 _elm_win_screen_reader(val);
6461 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6462 if (ev->name && !strcmp(ev->name, A11Y_DBUS_ENABLED_PROPERTY) &&
6463 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6465 if (!eina_value_get(ev->value, &val))
6467 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6468 ERR("Unable to get " A11Y_DBUS_ENABLED_PROPERTY " property value");
6474 _a11y_connection_init(bridge);
6477 _elm_win_atspi(EINA_FALSE);
6478 _a11y_connection_shutdown(bridge);
6485 _elm_atspi_bridge_eo_base_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6487 Eldbus_Proxy *proxy;
6488 Eldbus_Pending *req;
6490 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_constructor());
6494 if (!(pd->session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION)))
6496 ERR("Unable to connect to Session Bus");
6499 if (!(pd->bus_obj = eldbus_object_get(pd->session_bus, A11Y_DBUS_NAME, A11Y_DBUS_PATH)))
6501 ERR("Could not get /org/a11y/bus object");
6504 if (!(proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE)))
6506 ERR("Could not get proxy object for %s interface", A11Y_DBUS_STATUS_INTERFACE);
6509 if (!(req = eldbus_proxy_property_get(proxy, "ScreenReaderEnabled", _screen_reader_enabled_get, obj)))
6511 ERR("Could not send PropertyGet request");
6514 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6516 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6517 if (!(req = eldbus_proxy_property_get(proxy, A11Y_DBUS_ENABLED_PROPERTY, _at_spi_client_enabled_get, obj)))
6519 ERR("Could not send PropertyGet request");
6523 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6526 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
6527 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
6528 _properties_changed_cb, obj);
6533 eldbus_object_unref(pd->bus_obj);
6536 eldbus_connection_unref(pd->session_bus);
6537 pd->session_bus = NULL;
6542 _elm_atspi_bridge_eo_base_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6544 _a11y_connection_shutdown(obj);
6546 if (pd->bus_obj) eldbus_object_unref(pd->bus_obj);
6547 if (pd->session_bus) eldbus_connection_unref(pd->session_bus);
6548 if (pd->root) eo_del(pd->root);
6550 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_destructor());
6554 elm_atspi_bridge_object_address_get(Eo *obj, char **bus, char **path)
6556 Eo *bridge = _elm_atspi_bridge_get();
6559 ERR("Connection with accessibility bus not established.");
6562 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
6563 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6565 ERR("Connection with accessibility bus not established.");
6568 if (bus) *bus = strdup(eldbus_connection_unique_name_get(pd->a11y_bus));
6569 if (path) *path = strdup(_bridge_path_from_object(bridge, obj));
6575 _proxy_property_get(const Eldbus_Service_Interface *interface, const char *property,
6576 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED,
6577 Eldbus_Message **error EINA_UNUSED)
6580 Eo *obj = eldbus_service_object_data_get(interface, "_atspi_obj");
6581 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6583 if (!strcmp(property, "Object"))
6586 eo_do(obj, parent = eo_parent_get());
6587 if (!elm_atspi_bridge_object_address_get(parent, &bus, &path))
6590 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
6593 eldbus_message_iter_basic_append(iter_struct, 's', bus);
6594 eldbus_message_iter_basic_append(iter_struct, 'o', path);
6595 eldbus_message_iter_container_close(iter, iter_struct);
6604 static const Eldbus_Property proxy_properties[] = {
6605 { "Object", "(so)", _proxy_property_get, NULL, 0 },
6606 { NULL, NULL, NULL, NULL, 0 }
6609 static const Eldbus_Service_Interface_Desc _proxy_iface_desc = {
6610 ELM_ATSPI_DBUS_INTERFACE_PROXY, socket_methods, NULL, proxy_properties, NULL, NULL
6613 static void _embedded_reply_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6615 Eo *parent, *proxy = data;
6616 const char *err, *txt;
6618 if (eldbus_message_error_get(msg, &err, &txt))
6620 ERR("AT-SPI: Embedded method call failed: %s %s", err, txt);
6621 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6624 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_CONNECTED, NULL));
6626 eo_do(proxy, parent = eo_parent_get());
6628 elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, proxy)
6632 _plug_embedded_send(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6634 char *obj_path = NULL;
6636 Eldbus_Message *msg = NULL;
6638 eo_do(proxy, parent = eo_parent_get());
6639 if (!parent) goto fail;
6641 msg = eldbus_message_method_call_new(bus, path, ATSPI_DBUS_INTERFACE_SOCKET, "Embedded");
6642 if (!msg) goto fail;
6644 if (!elm_atspi_bridge_object_address_get(parent, NULL, &obj_path))
6647 if (!eldbus_message_arguments_append(msg, "s", obj_path))
6650 if (!eldbus_connection_send(conn, msg, _embedded_reply_cb, proxy, 100))
6653 ELM_SAFE_FREE(obj_path, free);
6657 ERR("AT-SPI: Unable to send Embedded request.");
6658 if (msg) eldbus_message_unref(msg);
6659 ELM_SAFE_FREE(obj_path, free);
6660 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6663 static void _socket_addr_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6666 const char *bus, *path, *err, *txt;
6667 Eldbus_Message_Iter *iter, *iter_variant, *iter_struct;
6669 Eo *bridge = _elm_atspi_bridge_get();
6672 ERR("AT-SPI: Atspi bridge is not enabled.");
6675 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6677 if (eldbus_message_error_get(msg, &err, &txt))
6679 ERR("Unable to connect to socket: %s %s", err, txt);
6683 iter = eldbus_message_iter_get(msg);
6684 if (!eldbus_message_iter_arguments_get(iter, "v", &iter_variant))
6686 ERR("Unable to get variant parameter");
6690 if (!eldbus_message_iter_arguments_get(iter_variant, "(so)", &iter_struct))
6692 ERR("Unable to get so parameters");
6696 if (!eldbus_message_iter_arguments_get(iter_struct, "so", &bus, &path))
6698 ERR("Unable to get so parameters");
6702 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
6704 _plug_embedded_send(pd->a11y_bus, proxy, bus, path);
6709 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6713 eo_do(proxy, elm_obj_atspi_proxy_address_get_retry_timer_add());
6717 _plug_address_discover(Eldbus_Connection *conn, Eo *proxy, const char *svc_bus, const char *svc_path)
6719 Eldbus_Object *dobj;
6720 dobj = eldbus_object_get(conn, svc_bus, svc_path);
6723 ERR("Unable to get eldbus object from: %s %s", svc_bus, svc_path);
6727 Eldbus_Message *msg = eldbus_object_method_call_new(dobj, ELDBUS_FDO_INTERFACE_PROPERTIES, "Get");
6728 eldbus_message_arguments_append(msg, "ss", ELM_ATSPI_DBUS_INTERFACE_PROXY, "Object");
6729 eldbus_object_send(dobj, msg, _socket_addr_get_cb, proxy, 100);
6732 static void _plug_connect(Eldbus_Connection *conn, Eo *proxy)
6734 const char *bus, *path;
6736 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
6737 eo_do(proxy, path = eo_key_data_get("__svc_path"));
6741 _plug_address_discover(conn, proxy, bus, path);
6746 eo_do(proxy, elm_obj_atspi_proxy_address_get(&bus, &path));
6749 ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set. Unable to connect");
6750 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6753 _plug_embedded_send(conn, proxy, bus, path);
6758 static Eina_Bool _from_list_remove(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6760 Eina_List **list = data;
6761 *list = eina_list_remove(*list, obj);
6765 EAPI void elm_atspi_bridge_utils_proxy_connect(Eo *proxy)
6767 Eo *bridge = _elm_atspi_bridge_get();
6771 ERR("AT-SPI: Atspi bridge is not enabled.");
6772 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6775 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6779 if (!eina_list_data_find(pd->plug_queue, proxy))
6781 pd->plug_queue = eina_list_append(pd->plug_queue, proxy);
6782 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->plug_queue));
6786 _plug_connect(pd->a11y_bus, proxy);
6790 * @brief Service name sanitizer according to specs:
6791 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
6792 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
6794 char *_sanitize_service_name(const char *name)
6796 char ret[256] = "\0";
6798 if (!name) return NULL;
6800 const char *tmp = name;
6803 // name element should not begin with digit. Swallow non-charater prefix
6804 while ((*tmp != '\0') && !isalpha(*tmp)) tmp++;
6806 // append rest of character valid charactes [A-Z][a-z][0-9]_
6807 while ((*tmp != '\0') && (dst < &ret[sizeof(ret) - 1]))
6809 if (isalpha(*tmp) || isdigit(*tmp) || (*tmp == '_'))
6818 Eo* _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type)
6821 char bus[256], path[256], *name;
6824 name = _sanitize_service_name(svcname);
6825 if (!name) return NULL;
6827 res = snprintf(bus, sizeof(bus), "elm.atspi.proxy.socket.%s-%d", name, svcnum);
6828 if (res < 0 || (res >= (int)sizeof(bus)))
6834 res = snprintf(path, sizeof(path), "/elm/atspi/proxy/socket/%s/%d", name, svcnum);
6835 if (res < 0 || (res >= (int)sizeof(path)))
6843 ret = eo_add(ELM_ATSPI_PROXY_CLASS, parent, elm_obj_atspi_proxy_constructor(type));
6844 if (!ret) return NULL;
6846 eo_do(ret, eo_key_data_set("__svc_bus", eina_stringshare_add(bus)));
6847 eo_do(ret, eo_key_data_set("__svc_path", eina_stringshare_add(path)));
6853 _on_socket_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6855 Eldbus_Service_Interface *ifc = data;
6857 Eldbus_Connection *conn = eldbus_service_connection_get(ifc);
6858 eo_do(obj, bus = eo_key_data_get("__svc_bus"));
6859 eldbus_name_release(conn, bus, NULL, NULL);
6860 eldbus_service_interface_unregister(ifc);
6865 _proxy_interface_register(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6867 Eldbus_Service_Interface *proxy_infc;
6868 Eo *bridge = _elm_atspi_bridge_get();
6871 ERR("AT-SPI: Atspi bridge is not enabled.");
6874 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6876 eldbus_name_request(conn, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, NULL, NULL);
6877 proxy_infc = eldbus_service_interface_register(pd->a11y_bus, path, &_proxy_iface_desc);
6879 ERR("AT-SPI: Proxy interface registration failed");
6880 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _on_socket_del, proxy_infc));
6881 eldbus_service_object_data_set(proxy_infc, "_atspi_obj", proxy);
6884 static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy)
6886 const char *bus, *path;
6887 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6888 Eo *bridge = _elm_atspi_bridge_get();
6889 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6892 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
6893 eo_do(proxy, path = eo_key_data_get("__svc_path"));
6896 _proxy_interface_register(conn, proxy, bus, path);
6898 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6899 pd->interfaces.socket =
6900 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &socket_iface_desc);
6904 EAPI void elm_atspi_bridge_utils_proxy_listen(Eo *proxy)
6906 Eo *bridge = _elm_atspi_bridge_get();
6909 ERR("AT-SPI: Atspi bridge is not enabled.");
6912 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6915 if (!eina_list_data_find(pd->socket_queue, proxy))
6917 pd->socket_queue = eina_list_append(pd->socket_queue, proxy);
6918 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->socket_queue));
6922 _socket_ifc_create(pd->a11y_bus, proxy);
6925 //TIZEN_ONLY(20160527) - Add direct reading feature
6927 _on_read_command_call(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6929 const char *errname, *errmsg;
6933 Elm_Atspi_Say_Info *say_info = data;
6935 if (eldbus_message_error_get(msg, &errname, &errmsg))
6937 ERR("%s %s", errname, errmsg);
6943 // get read command id and map it to obj
6944 if (eldbus_message_arguments_get(msg, "sbi", &s, &b, &i))
6946 if (!read_command_id)
6947 read_command_id = eina_hash_int32_new(NULL);
6949 if (!read_command_id) {
6950 ERR("eina_hash_int32_new() failed to create new map to store callbacks for direct reading commands");
6954 eina_hash_add(read_command_id, &i, say_info);
6960 elm_atspi_bridge_utils_say(const char* text,
6961 Eina_Bool discardable,
6962 const Elm_Atspi_Say_Signal_Cb func,
6965 Eldbus_Message *msg;
6966 Eldbus_Message_Iter *iter;
6967 Elm_Atspi_Say_Info *say_info = NULL;
6968 Eo *bridge = _elm_atspi_bridge_get();
6971 ERR("AT-SPI: Atspi bridge is not enabled.");
6974 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6977 ERR("AT-SPI: a11y bus is not set.");
6981 msg = eldbus_message_method_call_new(ELM_ATSPI_DIRECT_READ_BUS,
6982 ELM_ATSPI_DIRECT_READ_PATH,
6983 ELM_ATSPI_DIRECT_READ_INTERFACE,
6985 iter = eldbus_message_iter_get(msg);
6986 eldbus_message_iter_arguments_append(iter, "sb", text, discardable);
6988 say_info = calloc(1, sizeof(Elm_Atspi_Say_Info));
6990 say_info->func = func;
6991 say_info->data = (void *)data;
6994 eldbus_connection_send(pd->a11y_bus, msg, _on_read_command_call, say_info, -1);
6998 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7000 _offset_set_reply_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7002 const char *err, *txt;
7004 if (eldbus_message_error_get(msg, &err, &txt))
7006 ERR("AT-SPI: SetOffset method call failed: %s %s", err, txt);
7011 void elm_atspi_bridge_utils_proxy_offset_set(Eo *proxy, int x, int y)
7013 const char *bus, *path;
7014 Eo *bridge = _elm_atspi_bridge_get();
7015 if (!bridge) return;
7017 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7019 if (!pd->a11y_bus) return;
7021 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7022 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7024 Eldbus_Message *msg = NULL;
7026 msg = eldbus_message_method_call_new(bus, path, ELM_ATSPI_DBUS_INTERFACE_PROXY, "SetOffset");
7027 if (!msg) goto fail;
7029 if (!eldbus_message_arguments_append(msg, "i", x))
7032 if (!eldbus_message_arguments_append(msg, "i", y))
7035 if (!eldbus_connection_send(pd->a11y_bus, msg, _offset_set_reply_cb, NULL, 100))
7041 ERR("AT-SPI: Unable to send SetOffset request.");
7042 if (msg) eldbus_message_unref(msg);
7045 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
7046 EAPI Eina_Bool elm_atspi_bridge_utils_is_screen_reader_enabled(void)
7048 Eo *bridge = _elm_atspi_bridge_get();
7051 ERR("AT-SPI: Atspi bridge is not enabled.");
7054 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
7055 return pd->screen_reader_enabled;
7058 #include "elm_atspi_bridge.eo.c"