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}
223 ELM_ACCESSIBLE_DEFAULT_LABEL_ENABLED = 0,
224 ELM_ACCESSIBLE_DEFAULT_LABEL_DISABLED = 1 << 0,
227 enum _Atspi_Object_Child_Event_Type
229 ATSPI_OBJECT_CHILD_ADDED = 0,
230 ATSPI_OBJECT_CHILD_REMOVED
233 enum _Atspi_Object_Property
235 ATSPI_OBJECT_PROPERTY_NAME = 0,
236 ATSPI_OBJECT_PROPERTY_DESCRIPTION,
237 ATSPI_OBJECT_PROPERTY_VALUE,
238 ATSPI_OBJECT_PROPERTY_ROLE,
239 ATSPI_OBJECT_PROPERTY_PARENT,
240 ATSPI_OBJECT_PROPERTY_LAST
243 enum _Atspi_Object_Signals {
244 ATSPI_OBJECT_EVENT_PROPERTY_CHANGED = 0,
245 ATSPI_OBJECT_EVENT_BOUNDS_CHANGED,
246 ATSPI_OBJECT_EVENT_LINK_SELECTED,
247 ATSPI_OBJECT_EVENT_STATE_CHANGED,
248 ATSPI_OBJECT_EVENT_CHILDREN_CHANGED,
249 ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED,
250 ATSPI_OBJECT_EVENT_SELECTION_CHANGED,
251 ATSPI_OBJECT_EVENT_MODEL_CHANGED,
252 ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED,
253 ATSPI_OBJECT_EVENT_ROW_INSERTED,
254 ATSPI_OBJECT_EVENT_ROW_REORDERED,
255 ATSPI_OBJECT_EVENT_ROW_DELETED,
256 ATSPI_OBJECT_EVENT_COLUMN_INSERTED,
257 ATSPI_OBJECT_EVENT_COLUMN_REORDERED,
258 ATSPI_OBJECT_EVENT_COLUMN_DELETED,
259 ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED,
260 ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED,
261 ATSPI_OBJECT_EVENT_TEXT_CHANGED,
262 ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED,
263 ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED,
264 ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED,
265 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
266 ATSPI_OBJECT_EVENT_MOVE_OUTED
270 enum _Atspi_Window_Signals
272 ATSPI_WINDOW_EVENT_PROPERTY_CHANGE = 0,
273 ATSPI_WINDOW_EVENT_MINIMIZE,
274 ATSPI_WINDOW_EVENT_MAXIMIZE,
275 ATSPI_WINDOW_EVENT_RESTORE,
276 ATSPI_WINDOW_EVENT_CLOSE,
277 ATSPI_WINDOW_EVENT_CREATE,
278 ATSPI_WINDOW_EVENT_REPARENT,
279 ATSPI_WINDOW_EVENT_DESKTOPCREATE,
280 ATSPI_WINDOW_EVENT_DESKTOPDESTROY,
281 ATSPI_WINDOW_EVENT_DESTROY,
282 ATSPI_WINDOW_EVENT_ACTIVATE,
283 ATSPI_WINDOW_EVENT_DEACTIVATE,
284 ATSPI_WINDOW_EVENT_RAISE,
285 ATSPI_WINDOW_EVENT_LOWER,
286 ATSPI_WINDOW_EVENT_MOVE,
287 ATSPI_WINDOW_EVENT_RESIZE,
288 ATSPI_WINDOW_EVENT_SHADE,
289 ATSPI_WINDOW_EVENT_UUSHADE,
290 ATSPI_WINDOW_EVENT_RESTYLE,
293 static const Eldbus_Signal _event_obj_signals[] = {
294 [ATSPI_OBJECT_EVENT_PROPERTY_CHANGED] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
295 [ATSPI_OBJECT_EVENT_BOUNDS_CHANGED] = {"BoundsChanged", ELDBUS_ARGS({"siiv(iiii)", NULL}), 0},
296 [ATSPI_OBJECT_EVENT_LINK_SELECTED] = {"LinkSelected", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
297 [ATSPI_OBJECT_EVENT_STATE_CHANGED] = {"StateChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
298 [ATSPI_OBJECT_EVENT_CHILDREN_CHANGED] = {"ChildrenChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
299 [ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED] = {"VisibleDataChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
300 [ATSPI_OBJECT_EVENT_SELECTION_CHANGED] = {"SelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
301 [ATSPI_OBJECT_EVENT_MODEL_CHANGED] = {"ModelChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
302 [ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED] = {"ActiveDescendantChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
303 [ATSPI_OBJECT_EVENT_ROW_INSERTED] = {"RowInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
304 [ATSPI_OBJECT_EVENT_ROW_REORDERED] = {"RowReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
305 [ATSPI_OBJECT_EVENT_ROW_DELETED] = {"RowDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
306 [ATSPI_OBJECT_EVENT_COLUMN_INSERTED] = {"ColumnInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
307 [ATSPI_OBJECT_EVENT_COLUMN_REORDERED] = {"ColumnReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
308 [ATSPI_OBJECT_EVENT_COLUMN_DELETED] = {"ColumnDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
309 [ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED] = {"TextBoundsChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
310 [ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED] = {"TextSelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
311 [ATSPI_OBJECT_EVENT_TEXT_CHANGED] = {"TextChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
312 [ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED] = {"TextAttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
313 [ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED] = {"TextCaretMoved", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
314 [ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED] = {"AttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
315 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
316 [ATSPI_OBJECT_EVENT_MOVE_OUTED] = {"MoveOuted", ELDBUS_ARGS({"siiv(i)", NULL}), 0},
318 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
321 static const Eldbus_Signal _window_obj_signals[] = {
322 [ATSPI_WINDOW_EVENT_PROPERTY_CHANGE] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
323 [ATSPI_WINDOW_EVENT_MINIMIZE] = {"Minimize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
324 [ATSPI_WINDOW_EVENT_MAXIMIZE] = {"Maximize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
325 [ATSPI_WINDOW_EVENT_RESTORE] = {"Restore", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
326 [ATSPI_WINDOW_EVENT_CLOSE] = {"Close", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
327 [ATSPI_WINDOW_EVENT_CREATE] = {"Create", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
328 [ATSPI_WINDOW_EVENT_REPARENT] = {"Reparent", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
329 [ATSPI_WINDOW_EVENT_DESKTOPCREATE] = {"DesktopCreate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
330 [ATSPI_WINDOW_EVENT_DESKTOPDESTROY] = {"DesktopDestroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
331 [ATSPI_WINDOW_EVENT_DESTROY] = {"Destroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
332 [ATSPI_WINDOW_EVENT_ACTIVATE] = {"Activate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
333 [ATSPI_WINDOW_EVENT_DEACTIVATE] = {"Deactivate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
334 [ATSPI_WINDOW_EVENT_RAISE] = {"Raise", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
335 [ATSPI_WINDOW_EVENT_LOWER] = {"Lower", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
336 [ATSPI_WINDOW_EVENT_MOVE] = {"Move", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
337 [ATSPI_WINDOW_EVENT_RESIZE] = {"Resize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
338 [ATSPI_WINDOW_EVENT_SHADE] = {"Shade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
339 [ATSPI_WINDOW_EVENT_UUSHADE] = {"uUshade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
340 [ATSPI_WINDOW_EVENT_RESTYLE] = {"Restyle", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
341 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
344 const int elm_roles_to_atspi_roles[][2] = {
345 { ELM_ATSPI_ROLE_INVALID, ATSPI_ROLE_INVALID },
346 { ELM_ATSPI_ROLE_ACCELERATOR_LABEL, ATSPI_ROLE_ACCELERATOR_LABEL },
347 { ELM_ATSPI_ROLE_ALERT, ATSPI_ROLE_ALERT },
348 { ELM_ATSPI_ROLE_ANIMATION, ATSPI_ROLE_ANIMATION },
349 { ELM_ATSPI_ROLE_ARROW, ATSPI_ROLE_ARROW },
350 { ELM_ATSPI_ROLE_CALENDAR, ATSPI_ROLE_CALENDAR },
351 { ELM_ATSPI_ROLE_CANVAS, ATSPI_ROLE_CANVAS },
352 { ELM_ATSPI_ROLE_CHECK_BOX, ATSPI_ROLE_CHECK_BOX },
353 { ELM_ATSPI_ROLE_CHECK_MENU_ITEM, ATSPI_ROLE_CHECK_MENU_ITEM },
354 { ELM_ATSPI_ROLE_COLOR_CHOOSER, ATSPI_ROLE_COLOR_CHOOSER },
355 { ELM_ATSPI_ROLE_COLUMN_HEADER, ATSPI_ROLE_COLUMN_HEADER },
356 { ELM_ATSPI_ROLE_COMBO_BOX, ATSPI_ROLE_COMBO_BOX },
357 { ELM_ATSPI_ROLE_DATE_EDITOR, ATSPI_ROLE_DATE_EDITOR },
358 { ELM_ATSPI_ROLE_DESKTOP_ICON, ATSPI_ROLE_DESKTOP_ICON },
359 { ELM_ATSPI_ROLE_DESKTOP_FRAME, ATSPI_ROLE_DESKTOP_FRAME },
360 { ELM_ATSPI_ROLE_DIAL, ATSPI_ROLE_DIAL },
361 { ELM_ATSPI_ROLE_DIALOG, ATSPI_ROLE_DIALOG },
362 { ELM_ATSPI_ROLE_DIRECTORY_PANE, ATSPI_ROLE_DIRECTORY_PANE },
363 { ELM_ATSPI_ROLE_DRAWING_AREA, ATSPI_ROLE_DRAWING_AREA },
364 { ELM_ATSPI_ROLE_FILE_CHOOSER, ATSPI_ROLE_FILE_CHOOSER },
365 { ELM_ATSPI_ROLE_FILLER, ATSPI_ROLE_FILLER },
366 { ELM_ATSPI_ROLE_FOCUS_TRAVERSABLE, ATSPI_ROLE_FOCUS_TRAVERSABLE },
367 { ELM_ATSPI_ROLE_FONT_CHOOSER, ATSPI_ROLE_FONT_CHOOSER },
368 { ELM_ATSPI_ROLE_FRAME, ATSPI_ROLE_FRAME },
369 { ELM_ATSPI_ROLE_GLASS_PANE, ATSPI_ROLE_GLASS_PANE },
370 { ELM_ATSPI_ROLE_HTML_CONTAINER, ATSPI_ROLE_HTML_CONTAINER },
371 { ELM_ATSPI_ROLE_ICON, ATSPI_ROLE_ICON },
372 { ELM_ATSPI_ROLE_IMAGE, ATSPI_ROLE_IMAGE },
373 { ELM_ATSPI_ROLE_INTERNAL_FRAME, ATSPI_ROLE_INTERNAL_FRAME },
374 { ELM_ATSPI_ROLE_LABEL, ATSPI_ROLE_LABEL },
375 { ELM_ATSPI_ROLE_LAYERED_PANE, ATSPI_ROLE_LAYERED_PANE },
376 { ELM_ATSPI_ROLE_LIST, ATSPI_ROLE_LIST },
377 { ELM_ATSPI_ROLE_LIST_ITEM, ATSPI_ROLE_LIST_ITEM },
378 { ELM_ATSPI_ROLE_MENU, ATSPI_ROLE_MENU },
379 { ELM_ATSPI_ROLE_MENU_BAR, ATSPI_ROLE_MENU_BAR },
380 { ELM_ATSPI_ROLE_MENU_ITEM, ATSPI_ROLE_MENU_ITEM },
381 { ELM_ATSPI_ROLE_OPTION_PANE, ATSPI_ROLE_OPTION_PANE },
382 { ELM_ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_PAGE_TAB },
383 { ELM_ATSPI_ROLE_PAGE_TAB_LIST, ATSPI_ROLE_PAGE_TAB_LIST },
384 { ELM_ATSPI_ROLE_PANEL, ATSPI_ROLE_PANEL },
385 { ELM_ATSPI_ROLE_PASSWORD_TEXT, ATSPI_ROLE_PASSWORD_TEXT },
386 { ELM_ATSPI_ROLE_POPUP_MENU, ATSPI_ROLE_POPUP_MENU },
387 { ELM_ATSPI_ROLE_PROGRESS_BAR, ATSPI_ROLE_PROGRESS_BAR },
388 { ELM_ATSPI_ROLE_PUSH_BUTTON, ATSPI_ROLE_PUSH_BUTTON },
389 { ELM_ATSPI_ROLE_RADIO_BUTTON, ATSPI_ROLE_RADIO_BUTTON },
390 { ELM_ATSPI_ROLE_RADIO_MENU_ITEM, ATSPI_ROLE_RADIO_MENU_ITEM },
391 { ELM_ATSPI_ROLE_ROOT_PANE, ATSPI_ROLE_ROOT_PANE },
392 { ELM_ATSPI_ROLE_ROW_HEADER, ATSPI_ROLE_ROW_HEADER },
393 { ELM_ATSPI_ROLE_SCROLL_BAR, ATSPI_ROLE_SCROLL_BAR },
394 { ELM_ATSPI_ROLE_SCROLL_PANE, ATSPI_ROLE_SCROLL_PANE },
395 { ELM_ATSPI_ROLE_SEPARATOR, ATSPI_ROLE_SEPARATOR },
396 { ELM_ATSPI_ROLE_SLIDER, ATSPI_ROLE_SLIDER },
397 { ELM_ATSPI_ROLE_SPIN_BUTTON, ATSPI_ROLE_SPIN_BUTTON },
398 { ELM_ATSPI_ROLE_SPLIT_PANE, ATSPI_ROLE_SPLIT_PANE },
399 { ELM_ATSPI_ROLE_STATUS_BAR, ATSPI_ROLE_STATUS_BAR },
400 { ELM_ATSPI_ROLE_TABLE, ATSPI_ROLE_TABLE },
401 { ELM_ATSPI_ROLE_TABLE_CELL, ATSPI_ROLE_TABLE_CELL },
402 { ELM_ATSPI_ROLE_TABLE_COLUMN_HEADER, ATSPI_ROLE_TABLE_COLUMN_HEADER },
403 { ELM_ATSPI_ROLE_TABLE_ROW_HEADER, ATSPI_ROLE_TABLE_ROW_HEADER },
404 { ELM_ATSPI_ROLE_TEAROFF_MENU_ITEM, ATSPI_ROLE_TEAROFF_MENU_ITEM },
405 { ELM_ATSPI_ROLE_TERMINAL, ATSPI_ROLE_TERMINAL },
406 { ELM_ATSPI_ROLE_TEXT, ATSPI_ROLE_TEXT },
407 { ELM_ATSPI_ROLE_TOGGLE_BUTTON, ATSPI_ROLE_TOGGLE_BUTTON },
408 { ELM_ATSPI_ROLE_TOOL_BAR, ATSPI_ROLE_TOOL_BAR },
409 { ELM_ATSPI_ROLE_TOOL_TIP, ATSPI_ROLE_TOOL_TIP },
410 { ELM_ATSPI_ROLE_TREE, ATSPI_ROLE_TREE },
411 { ELM_ATSPI_ROLE_TREE_TABLE, ATSPI_ROLE_TREE_TABLE },
412 { ELM_ATSPI_ROLE_UNKNOWN, ATSPI_ROLE_UNKNOWN },
413 { ELM_ATSPI_ROLE_VIEWPORT, ATSPI_ROLE_VIEWPORT },
414 { ELM_ATSPI_ROLE_WINDOW, ATSPI_ROLE_WINDOW },
415 { ELM_ATSPI_ROLE_EXTENDED, ATSPI_ROLE_EXTENDED },
416 { ELM_ATSPI_ROLE_HEADER, ATSPI_ROLE_HEADER },
417 { ELM_ATSPI_ROLE_FOOTER, ATSPI_ROLE_FOOTER },
418 { ELM_ATSPI_ROLE_PARAGRAPH, ATSPI_ROLE_PARAGRAPH },
419 { ELM_ATSPI_ROLE_RULER, ATSPI_ROLE_RULER },
420 { ELM_ATSPI_ROLE_APPLICATION, ATSPI_ROLE_APPLICATION },
421 { ELM_ATSPI_ROLE_AUTOCOMPLETE, ATSPI_ROLE_AUTOCOMPLETE },
422 { ELM_ATSPI_ROLE_EDITBAR, ATSPI_ROLE_EDITBAR },
423 { ELM_ATSPI_ROLE_EMBEDDED, ATSPI_ROLE_EMBEDDED },
424 { ELM_ATSPI_ROLE_ENTRY, ATSPI_ROLE_ENTRY },
425 { ELM_ATSPI_ROLE_CHART, ATSPI_ROLE_CHART },
426 { ELM_ATSPI_ROLE_CAPTION, ATSPI_ROLE_CAPTION },
427 { ELM_ATSPI_ROLE_DOCUMENT_FRAME, ATSPI_ROLE_DOCUMENT_FRAME },
428 { ELM_ATSPI_ROLE_HEADING, ATSPI_ROLE_HEADING },
429 { ELM_ATSPI_ROLE_PAGE, ATSPI_ROLE_PAGE },
430 { ELM_ATSPI_ROLE_SECTION, ATSPI_ROLE_SECTION },
431 { ELM_ATSPI_ROLE_REDUNDANT_OBJECT, ATSPI_ROLE_REDUNDANT_OBJECT },
432 { ELM_ATSPI_ROLE_FORM, ATSPI_ROLE_FORM },
433 { ELM_ATSPI_ROLE_LINK, ATSPI_ROLE_LINK },
434 { ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW, ATSPI_ROLE_INPUT_METHOD_WINDOW },
435 { ELM_ATSPI_ROLE_TABLE_ROW, ATSPI_ROLE_TABLE_ROW },
436 { ELM_ATSPI_ROLE_TREE_ITEM, ATSPI_ROLE_TREE_ITEM },
437 { ELM_ATSPI_ROLE_DOCUMENT_SPREADSHEET, ATSPI_ROLE_DOCUMENT_SPREADSHEET },
438 { ELM_ATSPI_ROLE_DOCUMENT_PRESENTATION, ATSPI_ROLE_DOCUMENT_PRESENTATION },
439 { ELM_ATSPI_ROLE_DOCUMENT_TEXT, ATSPI_ROLE_DOCUMENT_TEXT },
440 { ELM_ATSPI_ROLE_DOCUMENT_WEB, ATSPI_ROLE_DOCUMENT_WEB },
441 { ELM_ATSPI_ROLE_DOCUMENT_EMAIL, ATSPI_ROLE_DOCUMENT_EMAIL },
442 { ELM_ATSPI_ROLE_COMMENT, ATSPI_ROLE_COMMENT },
443 { ELM_ATSPI_ROLE_LIST_BOX, ATSPI_ROLE_LIST_BOX },
444 { ELM_ATSPI_ROLE_GROUPING, ATSPI_ROLE_GROUPING },
445 { ELM_ATSPI_ROLE_IMAGE_MAP, ATSPI_ROLE_IMAGE_MAP },
446 { ELM_ATSPI_ROLE_NOTIFICATION, ATSPI_ROLE_NOTIFICATION },
447 { ELM_ATSPI_ROLE_INFO_BAR, ATSPI_ROLE_INFO_BAR },
448 { ELM_ATSPI_ROLE_LAST_DEFINED, ATSPI_ROLE_LAST_DEFINED },
451 struct atspi_state_desc
453 Elm_Atspi_State_Type elm_state;
454 AtspiStateType atspi_state;
458 const struct atspi_state_desc elm_states_to_atspi_state[] = {
459 { ELM_ATSPI_STATE_INVALID, ATSPI_STATE_INVALID, "invalid" },
460 { ELM_ATSPI_STATE_ACTIVE, ATSPI_STATE_ACTIVE, "active" },
461 { ELM_ATSPI_STATE_ARMED, ATSPI_STATE_ARMED, "armed" },
462 { ELM_ATSPI_STATE_BUSY, ATSPI_STATE_BUSY, "busy" },
463 { ELM_ATSPI_STATE_CHECKED, ATSPI_STATE_CHECKED, "checked" },
464 { ELM_ATSPI_STATE_COLLAPSED, ATSPI_STATE_COLLAPSED, "collapsed" },
465 { ELM_ATSPI_STATE_DEFUNCT, ATSPI_STATE_DEFUNCT, "defunct" },
466 { ELM_ATSPI_STATE_EDITABLE, ATSPI_STATE_EDITABLE, "editable" },
467 { ELM_ATSPI_STATE_ENABLED, ATSPI_STATE_ENABLED, "enabled" },
468 { ELM_ATSPI_STATE_EXPANDABLE, ATSPI_STATE_EXPANDABLE, "expandable" },
469 { ELM_ATSPI_STATE_EXPANDED, ATSPI_STATE_EXPANDED, "expanded" },
470 { ELM_ATSPI_STATE_FOCUSABLE, ATSPI_STATE_FOCUSABLE, "focusable" },
471 { ELM_ATSPI_STATE_FOCUSED, ATSPI_STATE_FOCUSED, "focused" },
472 { ELM_ATSPI_STATE_HAS_TOOLTIP, ATSPI_STATE_HAS_TOOLTIP, "has-tooltip" },
473 { ELM_ATSPI_STATE_HORIZONTAL, ATSPI_STATE_HORIZONTAL, "horizontal" },
474 { ELM_ATSPI_STATE_ICONIFIED, ATSPI_STATE_ICONIFIED, "iconified" },
475 { ELM_ATSPI_STATE_MODAL, ATSPI_STATE_MODAL, "modal" },
476 { ELM_ATSPI_STATE_MULTI_LINE, ATSPI_STATE_MULTI_LINE, "multi-line" },
477 { ELM_ATSPI_STATE_MULTISELECTABLE, ATSPI_STATE_MULTISELECTABLE, "multiselectable" },
478 { ELM_ATSPI_STATE_OPAQUE, ATSPI_STATE_OPAQUE, "opaque" },
479 { ELM_ATSPI_STATE_PRESSED, ATSPI_STATE_PRESSED, "pressed" },
480 { ELM_ATSPI_STATE_RESIZABLE, ATSPI_STATE_RESIZABLE, "resizable" },
481 { ELM_ATSPI_STATE_SELECTABLE, ATSPI_STATE_SELECTABLE, "selectable" },
482 { ELM_ATSPI_STATE_SELECTED, ATSPI_STATE_SELECTED, "selected" },
483 { ELM_ATSPI_STATE_SENSITIVE, ATSPI_STATE_SENSITIVE, "sensitive" },
484 { ELM_ATSPI_STATE_SHOWING, ATSPI_STATE_SHOWING, "showing" },
485 { ELM_ATSPI_STATE_SINGLE_LINE, ATSPI_STATE_SINGLE_LINE, "single-line" },
486 { ELM_ATSPI_STATE_STALE, ATSPI_STATE_STALE, "stale" },
487 { ELM_ATSPI_STATE_TRANSIENT, ATSPI_STATE_TRANSIENT, "transient" },
488 { ELM_ATSPI_STATE_VERTICAL, ATSPI_STATE_VERTICAL, "vertical" },
489 { ELM_ATSPI_STATE_VISIBLE, ATSPI_STATE_VISIBLE, "visible" },
490 { ELM_ATSPI_STATE_MANAGES_DESCENDANTS, ATSPI_STATE_MANAGES_DESCENDANTS, "manages-descendants" },
491 { ELM_ATSPI_STATE_INDETERMINATE, ATSPI_STATE_INDETERMINATE, "indeterminate" },
492 { ELM_ATSPI_STATE_REQUIRED, ATSPI_STATE_REQUIRED, "required" },
493 { ELM_ATSPI_STATE_TRUNCATED, ATSPI_STATE_TRUNCATED, "truncated" },
494 { ELM_ATSPI_STATE_ANIMATED, ATSPI_STATE_ANIMATED, "animated" },
495 { ELM_ATSPI_STATE_INVALID_ENTRY, ATSPI_STATE_INVALID_ENTRY, "invalid-entry" },
496 { ELM_ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, "supports-autocompletion" },
497 { ELM_ATSPI_STATE_SELECTABLE_TEXT, ATSPI_STATE_SELECTABLE_TEXT, "selectable-text" },
498 { ELM_ATSPI_STATE_IS_DEFAULT, ATSPI_STATE_IS_DEFAULT, "is-default" },
499 { ELM_ATSPI_STATE_VISITED, ATSPI_STATE_VISITED, "visited" },
500 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
501 { ELM_ATSPI_STATE_CHECKABLE, ATSPI_STATE_CHECKABLE, "checkable" },
502 { ELM_ATSPI_STATE_HAS_POPUP, ATSPI_STATE_HAS_POPUP, "has-popup" },
503 { ELM_ATSPI_STATE_READ_ONLY, ATSPI_STATE_READ_ONLY, "read-only" },
504 { ELM_ATSPI_STATE_HIGHLIGHTED, ATSPI_STATE_HIGHLIGHTED, "highlighted" },
505 { ELM_ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_HIGHLIGHTABLE, "highlightable" },
507 { ELM_ATSPI_STATE_LAST_DEFINED, ATSPI_STATE_LAST_DEFINED, "last-defined" }
510 const int elm_relation_to_atspi_relation_mapping[] = {
511 [ELM_ATSPI_RELATION_NULL] = ATSPI_RELATION_NULL,
512 [ELM_ATSPI_RELATION_LABEL_FOR] = ATSPI_RELATION_LABEL_FOR,
513 [ELM_ATSPI_RELATION_LABELLED_BY] = ATSPI_RELATION_LABELLED_BY,
514 [ELM_ATSPI_RELATION_CONTROLLER_FOR] = ATSPI_RELATION_CONTROLLER_FOR,
515 [ELM_ATSPI_RELATION_CONTROLLED_BY] = ATSPI_RELATION_CONTROLLED_BY,
516 [ELM_ATSPI_RELATION_MEMBER_OF] = ATSPI_RELATION_MEMBER_OF,
517 [ELM_ATSPI_RELATION_TOOLTIP_FOR] = ATSPI_RELATION_TOOLTIP_FOR,
518 [ELM_ATSPI_RELATION_NODE_CHILD_OF] = ATSPI_RELATION_NODE_CHILD_OF,
519 [ELM_ATSPI_RELATION_NODE_PARENT_OF] = ATSPI_RELATION_NODE_PARENT_OF,
520 [ELM_ATSPI_RELATION_EXTENDED] = ATSPI_RELATION_EXTENDED,
521 [ELM_ATSPI_RELATION_FLOWS_TO] = ATSPI_RELATION_FLOWS_TO,
522 [ELM_ATSPI_RELATION_FLOWS_FROM] = ATSPI_RELATION_FLOWS_FROM,
523 [ELM_ATSPI_RELATION_SUBWINDOW_OF] = ATSPI_RELATION_SUBWINDOW_OF,
524 [ELM_ATSPI_RELATION_EMBEDS] = ATSPI_RELATION_EMBEDS,
525 [ELM_ATSPI_RELATION_EMBEDDED_BY] = ATSPI_RELATION_EMBEDDED_BY,
526 [ELM_ATSPI_RELATION_POPUP_FOR] = ATSPI_RELATION_POPUP_FOR,
527 [ELM_ATSPI_RELATION_PARENT_WINDOW_OF] = ATSPI_RELATION_PARENT_WINDOW_OF,
528 [ELM_ATSPI_RELATION_DESCRIPTION_FOR] = ATSPI_RELATION_DESCRIPTION_FOR,
529 [ELM_ATSPI_RELATION_DESCRIBED_BY] = ATSPI_RELATION_DESCRIBED_BY,
530 [ELM_ATSPI_RELATION_LAST_DEFINED] = ATSPI_RELATION_LAST_DEFINED,
533 static inline Eldbus_Message *_dbus_invalid_ref_error_new(const Eldbus_Message *msg)
535 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.UnknownObject", "Path is not valid accessible object reference.");
538 static AtspiRelationType _elm_relation_to_atspi_relation(Elm_Atspi_Relation_Type type)
540 if ((type < ELM_ATSPI_RELATION_LAST_DEFINED) && (type > ELM_ATSPI_RELATION_NULL))
541 return elm_relation_to_atspi_relation_mapping[type];
542 return ATSPI_RELATION_NULL;
545 static Elm_Atspi_Relation_Type _atspi_relation_to_elm_relation(AtspiRelationType type)
548 for(i = 0; i < sizeof(elm_relation_to_atspi_relation_mapping) / sizeof(elm_relation_to_atspi_relation_mapping[0]); ++i)
550 if (elm_relation_to_atspi_relation_mapping[i] == (int)type) return (Elm_Atspi_Relation_Type)i;
552 return ELM_ATSPI_RELATION_NULL;
555 static AtspiRole _elm_role_to_atspi_role(Elm_Atspi_Role role)
557 return role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
560 static Eldbus_Message *
561 _accessible_get_role(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
563 const char *obj_path = eldbus_message_path_get(msg);
564 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
565 Eo *obj = _bridge_object_from_path(bridge, obj_path);
568 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
570 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
572 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
573 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
575 AtspiRole atspi_role = _elm_role_to_atspi_role(role);
576 eldbus_message_arguments_append(ret, "u", atspi_role);
580 static Eldbus_Message *
581 _accessible_get_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
583 const char *role_name = NULL, *obj_path = eldbus_message_path_get(msg);
584 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
585 Eo *obj = _bridge_object_from_path(bridge, obj_path);
587 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
589 eo_do(obj, role_name = elm_interface_atspi_accessible_role_name_get());
591 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
592 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
593 eldbus_message_arguments_append(ret, "s", role_name);
598 static Eldbus_Message *
599 _accessible_get_localized_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
601 const char *l_role_name = NULL, *obj_path = eldbus_message_path_get(msg);
602 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
603 Eo *obj = _bridge_object_from_path(bridge, obj_path);
605 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
607 eo_do(obj, l_role_name = elm_interface_atspi_accessible_localized_role_name_get());
608 EINA_SAFETY_ON_NULL_RETURN_VAL(l_role_name, NULL);
610 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
611 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
612 eldbus_message_arguments_append(ret, "s", l_role_name);
617 static Eldbus_Message *
618 _accessible_get_children(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
620 const char *obj_path = eldbus_message_path_get(msg);
621 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
622 Eo *obj = _bridge_object_from_path(bridge, obj_path);
623 Eina_List *children_list = NULL, *l;
625 Eldbus_Message_Iter *iter, *iter_array;
628 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
630 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
632 ret = eldbus_message_method_return_new(msg);
633 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
635 iter = eldbus_message_iter_get(ret);
636 iter_array = eldbus_message_iter_container_new(iter, 'a', "(so)");
637 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
639 EINA_LIST_FOREACH(children_list, l, children)
641 _bridge_iter_object_reference_append(bridge, iter_array, children);
642 _bridge_object_register(bridge, children);
645 eldbus_message_iter_container_close(iter, iter_array);
646 eina_list_free(children_list);
651 if (ret) eldbus_message_unref(ret);
655 static Eldbus_Message *
656 _accessible_get_application(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
659 const char *obj_path = eldbus_message_path_get(msg);
660 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
661 Eo *obj = _bridge_object_from_path(bridge, obj_path);
663 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
665 ret = eldbus_message_method_return_new(msg);
666 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
668 Eldbus_Message_Iter *iter = eldbus_message_iter_get(ret);
669 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
674 static Eldbus_Message *
675 _accessible_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
677 Eina_List *attrs, *l;
678 Elm_Atspi_Attribute *attr;
679 Eldbus_Message_Iter *iter, *iter_dict, *iter_entry;
682 const char *obj_path = eldbus_message_path_get(msg);
683 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
684 Eo *obj = _bridge_object_from_path(bridge, obj_path);
686 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
688 ret = eldbus_message_method_return_new(msg);
689 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
691 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
693 iter = eldbus_message_iter_get(ret);
694 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
695 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
697 EINA_LIST_FOREACH(attrs, l, attr)
699 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
700 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
701 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
702 eldbus_message_iter_container_close(iter_dict, iter_entry);
705 eldbus_message_iter_container_close(iter, iter_dict);
706 elm_atspi_attributes_list_free(attrs);
711 static Eldbus_Message *
712 _accessible_interfaces_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
715 Eldbus_Message_Iter *iter;
716 const char *obj_path = eldbus_message_path_get(msg);
717 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
718 Eo *obj = _bridge_object_from_path(bridge, obj_path);
720 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
722 ret = eldbus_message_method_return_new(msg);
723 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
725 iter = eldbus_message_iter_get(ret);
726 _iter_interfaces_append(iter, obj);
732 _elm_atspi_state_set_to_atspi_state_set(Elm_Atspi_State_Set states)
737 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
739 if (STATE_TYPE_GET(states, elm_states_to_atspi_state[i].elm_state))
740 STATE_TYPE_SET(ret, elm_states_to_atspi_state[i].atspi_state);
745 static Elm_Atspi_State_Set
746 _atspi_state_set_to_elm_atspi_state_set(uint64_t states)
748 //Currently Elm_Atspi_State and Atspi_State_Set are binary compatible,
749 //implement proper coversion when it will be needed.
750 Elm_Atspi_State_Set ret = states;
755 _elm_atspi_state_hash_build(void)
757 Eina_Hash *ret = eina_hash_string_superfast_new(NULL);
760 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
761 eina_hash_add(ret, elm_states_to_atspi_state[i].name, &elm_states_to_atspi_state[i]);
767 _elm_atspi_event_hash_build(void)
769 Eina_Hash *ret = eina_hash_pointer_new(NULL);
772 for (i = 0; i < SIZE(event_handlers); i++)
773 eina_hash_add(ret, &(event_handlers[i].desc), event_handlers[i].callback);
778 static Eldbus_Message *
779 _accessible_get_state(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
782 Eldbus_Message_Iter *iter, *iter_array;
783 Elm_Atspi_State_Set states;
784 uint64_t atspi_states = 0;
786 const char *obj_path = eldbus_message_path_get(msg);
787 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
788 Eo *obj = _bridge_object_from_path(bridge, obj_path);
790 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
792 ret = eldbus_message_method_return_new(msg);
793 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
795 iter = eldbus_message_iter_get(ret);
796 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
797 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
799 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
801 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
803 unsigned int s1 = atspi_states & 0xFFFFFFFF;
804 unsigned int s2 = (atspi_states >> 32) & 0xFFFFFFFF;
806 eldbus_message_iter_basic_append(iter_array, 'u', s1);
807 eldbus_message_iter_basic_append(iter_array, 'u', s2);
808 eldbus_message_iter_container_close(iter, iter_array);
813 if (ret) eldbus_message_unref(ret);
817 static Eldbus_Message *
818 _accessible_get_index_in_parent(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
820 const char *obj_path = eldbus_message_path_get(msg);
821 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
822 Eo *obj = _bridge_object_from_path(bridge, obj_path);
826 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
828 ret = eldbus_message_method_return_new(msg);
829 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
831 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
833 eldbus_message_arguments_append(ret, "i", idx);
838 static Eldbus_Message *
839 _accessible_child_at_index(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
841 const char *obj_path = eldbus_message_path_get(msg);
842 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
843 Eo *obj = _bridge_object_from_path(bridge, obj_path);
845 Eina_List *children = NULL;
848 Eldbus_Message_Iter *iter;
850 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
852 if (!eldbus_message_arguments_get(msg, "i", &idx))
853 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
855 ret = eldbus_message_method_return_new(msg);
856 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
858 iter = eldbus_message_iter_get(ret);
859 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
861 child = eina_list_nth(children, idx);
862 _bridge_iter_object_reference_append(bridge, iter, child);
863 _bridge_object_register(bridge, child);
864 eina_list_free(children);
869 static Eldbus_Message *
870 _accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
872 const char *obj_path = eldbus_message_path_get(msg);
873 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
874 Eo *rel_obj, *obj = _bridge_object_from_path(bridge, obj_path);
875 Eldbus_Message *ret = NULL;
876 Eldbus_Message_Iter *iter = NULL, *iter_array = NULL, *iter_array2 = NULL, *iter_struct;
877 Elm_Atspi_Relation *rel;
879 Elm_Atspi_Relation_Set rels;
881 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
883 ret = eldbus_message_method_return_new(msg);
884 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
886 iter = eldbus_message_iter_get(ret);
887 iter_array = eldbus_message_iter_container_new(iter, 'a', "(ua(so))");
888 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
890 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
892 EINA_LIST_FOREACH(rels, l, rel)
894 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
895 eldbus_message_iter_basic_append(iter_struct, 'u', _elm_relation_to_atspi_relation(rel->type));
896 iter_array2 = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
897 EINA_SAFETY_ON_NULL_GOTO(iter_array2, fail);
898 EINA_LIST_FOREACH(rel->objects, l2, rel_obj)
900 _bridge_iter_object_reference_append(bridge, iter_array2, rel_obj);
901 _bridge_object_register(bridge, rel_obj);
903 eldbus_message_iter_container_close(iter_struct, iter_array2);
904 eldbus_message_iter_container_close(iter_array, iter_struct);
906 elm_atspi_relation_set_free(&rels);
907 eldbus_message_iter_container_close(iter, iter_array);
912 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get relation set.");
915 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
916 static Eldbus_Message *
917 _accessible_gesture_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
919 const char *obj_path = eldbus_message_path_get(msg);
920 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
921 Eo *obj = _bridge_object_from_path(bridge, obj_path);
922 int type, x_beg, y_beg, x_end, y_end, state;
923 unsigned int event_time;
925 Eina_Bool result = EINA_FALSE;
927 if (!eldbus_message_arguments_get(msg, "iiiiiiu", &type, &x_beg, &y_beg,
928 &x_end, &y_end, &state, &event_time))
929 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
931 ret = eldbus_message_method_return_new(msg);
932 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
934 Elm_Atspi_Gesture_Info gesture_info;
935 gesture_info.type = (Elm_Atspi_Gesture_Type)type;
936 gesture_info.x_beg = x_beg;
937 gesture_info.y_beg = y_beg;
938 gesture_info.x_end = x_end;
939 gesture_info.y_end = y_end;
940 gesture_info.state = (Elm_Atspi_Gesture_State)state;
941 gesture_info.event_time = event_time;
942 eo_do(obj, result = elm_interface_atspi_accessible_gesture_do(gesture_info));
943 eldbus_message_arguments_append(ret, "b", result);
948 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
949 static Eldbus_Message *
950 _accessible_get_neighbor(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
952 const char *start_path = eldbus_message_path_get(msg);
953 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
954 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
955 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
957 Eo *start = _bridge_object_from_path(bridge, start_path);
959 Eldbus_Message_Iter *iter;
960 int direction, search_mode;
962 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(start, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
964 char *root_path = "";
965 if (!eldbus_message_arguments_get(msg, "sii", &root_path, &direction, &search_mode))
966 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
968 Eo *root = _bridge_object_from_path(bridge, root_path);
970 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
973 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(root));
974 if (ecore_evas_obscured_get(ee))
975 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
979 ret = eldbus_message_method_return_new(msg);
980 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
982 iter = eldbus_message_iter_get(ret);
984 Eo *accessible = _calculate_neighbor(bridge, root, start, direction == 1, search_mode);
985 _bridge_iter_object_reference_append(bridge, iter, accessible);
986 _bridge_object_register(bridge, accessible);
988 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
989 _object_get_bus_name_and_path(bridge, start, &obj_bus_name, NULL);
990 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
992 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
993 eldbus_message_iter_basic_append(iter, 'y', recurse);
997 static Eldbus_Message *
998 _accessible_get_navigable_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1000 const char *obj_path = eldbus_message_path_get(msg);
1001 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1002 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
1003 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
1005 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1007 Eldbus_Message *ret;
1008 AtspiCoordType coord_type;
1009 Eldbus_Message_Iter *iter;
1011 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1013 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
1014 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
1015 if (ecore_evas_obscured_get(ee))
1016 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
1019 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
1020 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1022 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
1023 Evas_Object *top = elm_object_top_widget_get(obj);
1026 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
1031 ret = eldbus_message_method_return_new(msg);
1032 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1034 iter = eldbus_message_iter_get(ret);
1036 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1037 Eo *accessible = _calculate_navigable_accessible_at_point(bridge, obj, type, x, y);
1041 if (accessible && eo_isa(accessible, ELM_ACCESS_CLASS))
1043 Evas_Object *parent = elm_widget_parent_get(accessible);
1045 Elm_Widget_Smart_Data *wd;
1046 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
1050 Evas_Object *widget;
1052 EINA_LIST_FOREACH(wd->subobjs, l, widget)
1056 proxy = evas_object_data_get(widget, "__widget_proxy");
1060 evas_object_geometry_get(widget, &px, &py, &pw, &ph);
1061 if (x >= px && x <= px + pw && y >= py && y <= py +ph)
1063 /* proxy is also selectable */
1064 deputy = accessible;
1073 _bridge_iter_object_reference_append(bridge, iter, accessible);
1074 _bridge_object_register(bridge, accessible);
1076 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
1077 _object_get_bus_name_and_path(bridge, obj, &obj_bus_name, NULL);
1078 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
1079 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
1080 eldbus_message_iter_basic_append(iter, 'y', recurse);
1083 _bridge_iter_object_reference_append(bridge, iter, deputy);
1084 if (deputy) _bridge_object_register(bridge, deputy);
1090 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1092 _list_children_count_check(Eo *obj)
1096 Eina_List *children;
1098 Elm_Atspi_Role role;
1103 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1104 if (role == ELM_ATSPI_ROLE_LIST)
1106 int children_count = 0;
1107 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1108 children_count = eina_list_count(children);
1110 for (i = 0; i < children_count; i++)
1112 child = eina_list_nth(children, i);
1113 eo_do(child, role = elm_interface_atspi_accessible_role_get());
1114 if (role == ELM_ATSPI_ROLE_LIST_ITEM)
1117 eina_list_free(children);
1124 _list_children_count(Eo *obj)
1126 Eina_List *children;
1127 int list_items_count = 0;
1128 int children_count = 0;
1130 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1131 children_count = eina_list_count(children);
1136 list_items_count = _list_children_count_check(obj);
1137 if (list_items_count > 0)
1139 eina_list_free(children);
1140 return list_items_count;
1143 for (i = 0; i < children_count; i++)
1145 child = eina_list_nth(children, i);
1146 list_items_count = _list_children_count(child);
1147 if (list_items_count > 0)
1149 eina_list_free(children);
1150 return list_items_count;
1157 static Eldbus_Message *
1158 _accessible_reading_material_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1160 Eldbus_Message *ret;
1161 Eldbus_Message_Iter *iter, *iter_array, *iter_dict, *iter_entry;
1162 Eina_List *attrs, *l, *children;
1163 const char *name = NULL;
1164 unsigned int s1, s2;
1166 double increment = 0;
1167 double max_value = 0;
1168 double min_value = 0;
1170 int child_count = 0;
1171 int selected_child_count = 0;
1172 uint64_t atspi_states = 0;
1173 Elm_Atspi_Role role;
1174 Elm_Atspi_Attribute *attr;
1175 Elm_Atspi_State_Set states;
1176 Elm_Atspi_Relation_Set rels = NULL;
1177 Elm_Atspi_Relation *rel;
1178 Eo *relation_obj = NULL;
1181 Eina_Bool is_selected = EINA_FALSE;
1182 AtspiRole atspi_role = ATSPI_ROLE_INVALID;
1184 const char *obj_path = eldbus_message_path_get(msg);
1185 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1186 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1188 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1190 ret = eldbus_message_method_return_new(msg);
1191 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1193 iter = eldbus_message_iter_get(ret);
1195 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
1196 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
1197 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
1198 EINA_LIST_FOREACH(attrs, l, attr)
1200 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
1201 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
1202 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
1203 eldbus_message_iter_container_close(iter_dict, iter_entry);
1206 eldbus_message_iter_container_close(iter, iter_dict);
1207 elm_atspi_attributes_list_free(attrs);
1210 eo_do(obj, name = elm_interface_atspi_accessible_name_get());
1213 eldbus_message_iter_basic_append(iter, 's', name);
1215 /* name - LABELED_BY relation */
1216 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
1217 EINA_LIST_FOREACH(rels, l, rel)
1219 if (rel->type == ELM_ATSPI_RELATION_LABELLED_BY)
1221 int last_index = eina_list_count(rel->objects) - 1;
1222 relation_obj = eina_list_nth(rel->objects, last_index);
1226 eo_do(relation_obj, name = elm_interface_atspi_accessible_name_get());
1229 eldbus_message_iter_basic_append(iter, 's', name);
1231 /* name - text interface */
1233 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
1236 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
1237 eo_do(obj, name = elm_interface_atspi_text_get(0, val));
1241 eldbus_message_iter_basic_append(iter, 's', name);
1244 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1245 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1246 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1249 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1250 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1251 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1252 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1253 s1 = atspi_states & 0xFFFFFFFF;
1254 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1255 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1256 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1257 eldbus_message_iter_container_close(iter, iter_array);
1259 /* localized role name */
1260 eo_do(obj, name = elm_interface_atspi_accessible_localized_role_name_get());
1263 eldbus_message_iter_basic_append(iter, 's', name);
1266 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
1267 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1270 /* current value, increment, max, min */
1275 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
1277 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
1278 eo_do(obj, increment = elm_interface_atspi_value_increment_get());
1279 eo_do(obj, elm_interface_atspi_value_range_get(&min_value, &max_value, NULL));
1281 eldbus_message_iter_basic_append(iter, 'd', value);
1282 eldbus_message_iter_basic_append(iter, 'd', increment);
1283 eldbus_message_iter_basic_append(iter, 'd', max_value);
1284 eldbus_message_iter_basic_append(iter, 'd', min_value);
1287 eo_do(obj, name = elm_interface_atspi_accessible_description_get());
1290 eldbus_message_iter_basic_append(iter, 's', name);
1292 /* index in parent */
1293 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
1294 eldbus_message_iter_basic_append(iter, 'i', idx);
1296 /* is selected in parent */
1297 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
1298 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1300 eo_do(parent, is_selected = elm_interface_atspi_selection_is_child_selected(idx));
1302 eldbus_message_arguments_append(ret, "b", is_selected);
1304 /* has checkbox child */
1305 is_selected = EINA_FALSE;
1306 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1307 EINA_LIST_FOREACH(children, l, child)
1309 if (eo_isa(child, ELM_CHECK_CLASS))
1311 is_selected = EINA_TRUE;
1315 eldbus_message_iter_basic_append(iter, 'b', is_selected);
1316 eina_list_free(children);
1318 /* list children count */
1320 if (role == ELM_ATSPI_ROLE_DIALOG)
1322 child_count = _list_children_count(obj);
1324 eldbus_message_iter_basic_append(iter, 'i', child_count);
1326 /* first selected child index */
1328 if (eo_isa(obj, ELM_INDEX_CLASS))
1330 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1331 EINA_LIST_FOREACH(children, l, child)
1333 eo_do(child, states = elm_interface_atspi_accessible_state_set_get());
1334 if (STATE_TYPE_GET(states, ELM_ATSPI_STATE_SELECTED))
1338 eina_list_free(children);
1340 eldbus_message_iter_basic_append(iter, 'i', idx);
1343 role = ELM_ATSPI_ROLE_INVALID;
1344 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1345 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
1346 _object_desktop_reference_append(iter);
1348 _bridge_iter_object_reference_append(bridge, iter, parent);
1350 /* parent - states */
1351 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1352 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1353 eo_do(parent, states = elm_interface_atspi_accessible_state_set_get());
1354 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1355 s1 = atspi_states & 0xFFFFFFFF;
1356 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1357 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1358 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1359 eldbus_message_iter_container_close(iter, iter_array);
1361 /* parent - child count */
1362 eo_do(parent, l = elm_interface_atspi_accessible_children_get());
1363 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1367 eo_do(parent, role = elm_interface_atspi_accessible_role_get());
1368 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1369 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1371 /* parent - child count */
1372 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1374 eo_do(parent, selected_child_count = elm_interface_atspi_selection_selected_children_count_get());
1376 eldbus_message_iter_basic_append(iter, 'i', selected_child_count);
1378 /* relation object - DESCRIBED_BY */
1379 relation_obj = NULL;
1380 EINA_LIST_FOREACH(rels, l, rel)
1382 if (rel->type == ELM_ATSPI_RELATION_DESCRIBED_BY)
1384 int last_index = eina_list_count(rel->objects) - 1;
1385 relation_obj = eina_list_nth(rel->objects, last_index);
1389 _bridge_iter_object_reference_append(bridge, iter, relation_obj);
1390 elm_atspi_relation_set_free(&rels);
1395 if (rels) elm_atspi_relation_set_free(&rels);
1396 if (ret) eldbus_message_unref(ret);
1400 //TIZEN_ONLY(20170919): Handle default label object
1401 static Eldbus_Message *
1402 _accessible_default_label_info_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1404 Eldbus_Message *ret;
1405 Eldbus_Message_Iter *iter;
1406 const char *obj_path = eldbus_message_path_get(msg);
1407 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1408 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1409 Eo *default_label_obj;
1410 Elm_Atspi_Role role;
1411 AtspiRole atspi_role = ATSPI_ROLE_INVALID;
1413 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1415 ret = eldbus_message_method_return_new(msg);
1416 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1418 iter = eldbus_message_iter_get(ret);
1420 default_label_obj = _elm_win_default_label_obj_get(obj);
1421 if (!default_label_obj) default_label_obj = obj;
1422 _bridge_iter_object_reference_append(bridge, iter, default_label_obj);
1423 _bridge_object_register(bridge, default_label_obj);
1425 eo_do(default_label_obj, role = elm_interface_atspi_accessible_role_get());
1426 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1427 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1433 static const Eldbus_Method accessible_methods[] = {
1434 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
1435 { "GetNavigableAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)y", "accessible"}, {"(so)", "deputy"}), _accessible_get_navigable_at_point, 0 },
1436 { "GetNeighbor", ELDBUS_ARGS({"s", "current"}, {"i", "direction"}, {"i", "force_next"}), ELDBUS_ARGS({"(so)y", "accessible"}), _accessible_get_neighbor, 0 },
1438 { "GetChildAtIndex", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"(so)", "Accessible"}), _accessible_child_at_index, 0 },
1439 { "GetChildren", NULL, ELDBUS_ARGS({"a(so)", "children"}), _accessible_get_children, 0 },
1440 { "GetIndexInParent", NULL, ELDBUS_ARGS({"i", "index"}), _accessible_get_index_in_parent, 0 },
1441 { "GetRelationSet", NULL, ELDBUS_ARGS({"a(ua(so))", NULL}), _accessible_get_relation_set, 0 },
1442 { "GetRole", NULL, ELDBUS_ARGS({"u", "Role"}), _accessible_get_role, 0 },
1443 { "GetRoleName", NULL, ELDBUS_ARGS({"s", "Name"}), _accessible_get_role_name, 0 },
1444 { "GetLocalizedRoleName", NULL, ELDBUS_ARGS({"s", "LocalizedName"}), _accessible_get_localized_role_name, 0},
1445 { "GetState", NULL, ELDBUS_ARGS({"au", NULL}), _accessible_get_state, 0},
1446 { "GetApplication", NULL, ELDBUS_ARGS({"(so)", NULL}), _accessible_get_application, 0},
1447 { "GetAttributes", NULL, ELDBUS_ARGS({"a{ss}", NULL}), _accessible_attributes_get, 0},
1448 { "GetInterfaces", NULL, ELDBUS_ARGS({"as", NULL}), _accessible_interfaces_get, 0},
1449 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
1451 ELDBUS_ARGS({"i", "type"}, {"i", "x_beg"}, {"i", "y_beg"},
1452 {"i", "x_end"}, {"i", "y_end"}, {"i", "state"},
1453 {"u", "event_time"}),
1454 ELDBUS_ARGS({"b", "result"}), _accessible_gesture_do, 0},
1456 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1457 { "GetReadingMaterial",
1459 ELDBUS_ARGS({"a{ss}", "attributes"}, {"s", "name"},
1460 {"s", "labledByName"},{"s", "textIfceName"},
1461 {"u", "role"}, {"au", "stateSet"},
1462 {"s", "localizedName"}, {"i", "childCount"},
1463 {"d", "currentValue"},{"d", "minimumIncrement"},
1464 {"d", "maximumValue"},{"d", "minimumValue"},
1465 {"s", "description"}, {"i", "indexInParent"},
1466 {"b", "isSelectedInParent"}, {"b", "hasCheckboxChild"},
1467 {"i", "listChildrenCount"},
1468 {"i", "firstSelectedChildIndex"},
1469 {"(so)", "parent"}, {"au", "parentStateSet"},
1470 {"i", "parentChildCount"}, {"u", "parentRole"},
1471 {"i", "selectedChildCount"},
1472 {"(so)", "describecByObject"}),
1473 _accessible_reading_material_get, 0},
1475 //TIZEN_ONLY(20170919): Handle default label object
1476 { "GetDefaultLabelInfo",
1477 NULL, ELDBUS_ARGS({"(so)", "defaultLabelObject"}, {"u", "defaultLabelRole"}),
1478 _accessible_default_label_info_get, 0},
1480 { NULL, NULL, NULL, NULL, 0 }
1484 _is_operation_permitted(Eo *obj)
1486 Elm_Atspi_State_Set states;
1487 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1489 if (!STATE_TYPE_GET(states, ELM_ATSPI_STATE_SHOWING)) return EINA_FALSE;
1494 if (evas_object_freeze_events_get(parent)) return EINA_FALSE;
1495 parent = evas_object_smart_parent_get(parent);
1500 static Eldbus_Message *
1501 _selection_selected_child_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1503 const char *obj_path = eldbus_message_path_get(msg);
1504 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1505 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1509 Eldbus_Message *ret;
1510 Eldbus_Message_Iter *iter;
1512 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1514 if (!eldbus_message_arguments_get(msg, "i", &idx))
1515 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1517 ret = eldbus_message_method_return_new(msg);
1518 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1520 iter = eldbus_message_iter_get(ret);
1521 eo_do(obj, child = elm_interface_atspi_selection_selected_child_get(idx));
1523 _bridge_iter_object_reference_append(bridge, iter, child);
1524 _bridge_object_register(bridge, child);
1529 static Eldbus_Message *
1530 _selection_child_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1532 const char *obj_path = eldbus_message_path_get(msg);
1533 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1534 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1536 Eldbus_Message *ret;
1537 Eina_Bool result = EINA_FALSE;
1539 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1541 if (!eldbus_message_arguments_get(msg, "i", &idx))
1542 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1544 ret = eldbus_message_method_return_new(msg);
1545 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1547 if (_is_operation_permitted(obj))
1548 eo_do(obj, result = elm_interface_atspi_selection_child_select(idx));
1549 eldbus_message_arguments_append(ret, "b", result);
1554 static Eldbus_Message *
1555 _selection_selected_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1557 const char *obj_path = eldbus_message_path_get(msg);
1558 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1559 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1561 Eldbus_Message *ret;
1562 Eina_Bool result = EINA_FALSE;
1564 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1566 if (!eldbus_message_arguments_get(msg, "i", &idx))
1567 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1569 ret = eldbus_message_method_return_new(msg);
1570 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1572 if (_is_operation_permitted(obj))
1573 eo_do(obj, result = elm_interface_atspi_selection_selected_child_deselect(idx));
1574 eldbus_message_arguments_append(ret, "b", result);
1579 static Eldbus_Message *
1580 _selection_is_child_selected(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1582 const char *obj_path = eldbus_message_path_get(msg);
1583 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1584 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1586 Eldbus_Message *ret;
1589 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1591 if (!eldbus_message_arguments_get(msg, "i", &idx))
1592 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1594 ret = eldbus_message_method_return_new(msg);
1595 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1597 eo_do(obj, result = elm_interface_atspi_selection_is_child_selected(idx));
1598 eldbus_message_arguments_append(ret, "b", result);
1603 static Eldbus_Message *
1604 _selection_all_children_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1606 const char *obj_path = eldbus_message_path_get(msg);
1607 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1608 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 ret = eldbus_message_method_return_new(msg);
1615 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1617 if (_is_operation_permitted(obj))
1618 eo_do(obj, result = elm_interface_atspi_selection_all_children_select());
1619 eldbus_message_arguments_append(ret, "b", result);
1624 static Eldbus_Message *
1625 _selection_clear(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1627 const char *obj_path = eldbus_message_path_get(msg);
1628 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1629 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1630 Eldbus_Message *ret;
1631 Eina_Bool result = EINA_FALSE;
1633 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1635 ret = eldbus_message_method_return_new(msg);
1636 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1638 if (_is_operation_permitted(obj))
1639 eo_do(obj, result = elm_interface_atspi_selection_clear());
1640 eldbus_message_arguments_append(ret, "b", result);
1645 static Eldbus_Message *
1646 _selection_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1648 const char *obj_path = eldbus_message_path_get(msg);
1649 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1650 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1652 Eldbus_Message *ret;
1653 Eina_Bool result = EINA_FALSE;
1655 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1657 if (!eldbus_message_arguments_get(msg, "i", &idx))
1658 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1660 ret = eldbus_message_method_return_new(msg);
1661 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1663 if (_is_operation_permitted(obj))
1664 eo_do(obj, result = elm_interface_atspi_selection_child_deselect(idx));
1665 eldbus_message_arguments_append(ret, "b", result);
1670 static const Eldbus_Method selection_methods[] = {
1671 { "GetSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"(so)", "Accessible"}), _selection_selected_child_get, 0 },
1672 { "SelectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_select, 0 },
1673 { "DeselectSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_selected_child_deselect, 0 },
1674 { "IsChildSelected", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_is_child_selected, 0 },
1675 { "SelectAll", NULL, ELDBUS_ARGS({"b", "result"}), _selection_all_children_select, 0},
1676 { "ClearSelection", NULL, ELDBUS_ARGS({"b", "result"}), _selection_clear, 0},
1677 { "DeselectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_deselect, 0 },
1678 { NULL, NULL, NULL, NULL, 0 }
1681 static Eldbus_Message *
1682 _action_description_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1684 const char *description, *obj_path = eldbus_message_path_get(msg);
1685 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1686 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1688 Eldbus_Message *ret;
1690 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1692 if (!eldbus_message_arguments_get(msg, "i", &idx))
1693 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1695 ret = eldbus_message_method_return_new(msg);
1696 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1698 eo_do(obj, description = elm_interface_atspi_action_description_get(idx));
1699 description = description ? description : "";
1700 eldbus_message_arguments_append(ret, "s", description);
1705 static Eldbus_Message *
1706 _action_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1708 const char *name, *obj_path = eldbus_message_path_get(msg);
1709 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1710 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1712 Eldbus_Message *ret;
1714 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1716 if (!eldbus_message_arguments_get(msg, "i", &idx))
1717 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1719 ret = eldbus_message_method_return_new(msg);
1720 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1722 eo_do(obj, name = elm_interface_atspi_action_name_get(idx));
1723 name = name ? name : "";
1724 eldbus_message_arguments_append(ret, "s", name);
1729 static Eldbus_Message *
1730 _action_localized_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1732 const char *name, *obj_path = eldbus_message_path_get(msg);
1733 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1734 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1736 Eldbus_Message *ret;
1738 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1740 if (!eldbus_message_arguments_get(msg, "i", &idx))
1741 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1743 ret = eldbus_message_method_return_new(msg);
1744 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1746 eo_do(obj, name = elm_interface_atspi_action_localized_name_get(idx));
1747 name = name ? name : "";
1748 eldbus_message_arguments_append(ret, "s", name);
1753 static Eldbus_Message *
1754 _action_key_binding_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1756 const char *obj_path = eldbus_message_path_get(msg);
1758 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1759 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1761 Eldbus_Message *ret;
1763 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1765 if (!eldbus_message_arguments_get(msg, "i", &idx))
1766 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1768 ret = eldbus_message_method_return_new(msg);
1769 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1771 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(idx));
1772 eldbus_message_arguments_append(ret, "s", key ? key : "");
1778 static Eldbus_Message *
1779 _action_actions_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1781 const char *action, *obj_path = eldbus_message_path_get(msg);
1782 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1783 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1785 Eldbus_Message *ret;
1786 Eldbus_Message_Iter *iter, *iter_array;
1788 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1790 ret = eldbus_message_method_return_new(msg);
1791 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1793 iter = eldbus_message_iter_get(ret);
1794 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
1796 iter_array = eldbus_message_iter_container_new(iter, 'a', "sss");
1797 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_array, NULL);
1799 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1802 EINA_LIST_FREE(actions, action)
1806 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(id));
1807 eo_do(obj, descr = elm_interface_atspi_action_description_get(id));
1808 descr = descr ? descr : "";
1809 eldbus_message_iter_arguments_append(iter_array, "sss", action, descr, key ? key : "");
1814 eldbus_message_iter_container_close(iter, iter_array);
1819 static Eldbus_Message *
1820 _action_action_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1822 const char *obj_path = eldbus_message_path_get(msg);
1823 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1824 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1826 Eldbus_Message *ret;
1827 Eina_Bool result = EINA_FALSE;
1829 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1831 if (!eldbus_message_arguments_get(msg, "i", &idx))
1832 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1834 ret = eldbus_message_method_return_new(msg);
1835 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1837 if (_is_operation_permitted(obj))
1838 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1840 eldbus_message_arguments_append(ret, "b", result);
1845 static Eldbus_Message *
1846 _action_action_name_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1848 const char *obj_path = eldbus_message_path_get(msg);
1849 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1850 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1855 Eldbus_Message *ret;
1856 Eina_Bool result = EINA_FALSE;
1858 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1860 if (!eldbus_message_arguments_get(msg, "s", &action_name))
1861 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1863 ret = eldbus_message_method_return_new(msg);
1864 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1866 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1867 EINA_LIST_FREE(actions, action)
1869 if (!result && action && !strcmp(action, action_name))
1877 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1879 eldbus_message_arguments_append(ret, "b", result);
1884 static const Eldbus_Method action_methods[] = {
1885 { "GetDescription", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "description"}), _action_description_get, 0 },
1886 { "GetName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_name_get, 0 },
1887 { "GetLocalizedName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_localized_name_get, 0 },
1888 { "GetKeyBinding", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "key"}), _action_key_binding_get, 0 },
1889 { "GetActions", NULL, ELDBUS_ARGS({"a(sss)", "actions"}), _action_actions_get, 0 },
1890 { "DoAction", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"b", "result"}), _action_action_do, 0 },
1891 { "DoActionName", ELDBUS_ARGS({"s", "name"}), ELDBUS_ARGS({"b", "result"}), _action_action_name_do, 0 },
1892 { NULL, NULL, NULL, NULL, 0 }
1895 static Eldbus_Message *
1896 _image_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1898 AtspiCoordType type;
1899 Eldbus_Message *ret;
1900 const char *obj_path = eldbus_message_path_get(msg);
1902 Eina_Bool screen_coords;
1903 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1904 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1908 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1910 if (!eldbus_message_arguments_get(msg, "u", &type))
1911 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1913 ret = eldbus_message_method_return_new(msg);
1914 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1916 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1917 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, &w, &h));
1918 eldbus_message_arguments_append(ret, "iiii", x, y, w, h);
1923 static Eldbus_Message *
1924 _image_position_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1926 AtspiCoordType type;
1927 Eldbus_Message *ret;
1928 const char *obj_path = eldbus_message_path_get(msg);
1929 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1930 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1932 Eina_Bool screen_coords;
1934 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1936 if (!eldbus_message_arguments_get(msg, "u", &type))
1937 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1939 ret = eldbus_message_method_return_new(msg);
1940 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1942 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1943 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, NULL, NULL));
1944 eldbus_message_arguments_append(ret, "i", x);
1945 eldbus_message_arguments_append(ret, "i", y);
1950 static Eldbus_Message *
1951 _image_size_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1953 Eldbus_Message *ret;
1954 const char *obj_path = eldbus_message_path_get(msg);
1955 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1956 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1959 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1961 ret = eldbus_message_method_return_new(msg);
1962 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1964 eo_do(obj, elm_interface_atspi_image_extents_get(EINA_FALSE, NULL, NULL, &w, &h));
1965 eldbus_message_arguments_append(ret, "i", w);
1966 eldbus_message_arguments_append(ret, "i", h);
1971 static const Eldbus_Method image_methods[] = {
1972 { "GetImageExtents", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"iiii", "extents"}), _image_extents_get, 0 },
1973 { "GetImagePosition", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}), _image_position_get, 0 },
1974 { "GetImageSize", NULL, ELDBUS_ARGS({"i", "width"}, {"i", "height"}), _image_size_get, 0 },
1975 { NULL, NULL, NULL, NULL, 0 }
1978 static Eldbus_Message *
1979 _text_string_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1981 const char *obj_path = eldbus_message_path_get(msg);
1983 Elm_Atspi_Text_Granularity gran;
1985 Eldbus_Message *ret;
1986 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1987 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1989 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
1991 if (!eldbus_message_arguments_get(msg, "iu", &start, &gran))
1992 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
1994 ret = eldbus_message_method_return_new(msg);
1995 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1997 eo_do(obj, str = elm_interface_atspi_text_string_get(gran, &start, &end));
1998 str = str ? str : strdup("");
2000 eldbus_message_arguments_append(ret, "sii", str, start, end);
2006 static Eldbus_Message *
2007 _text_text_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2009 const char *obj_path = eldbus_message_path_get(msg);
2011 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2012 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2015 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2017 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2018 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
2020 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
2021 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2023 eo_do(obj, str = elm_interface_atspi_text_get(start, end));
2024 str = str ? str : strdup("");
2026 eldbus_message_arguments_append(ret, "s", str);
2032 static Eldbus_Message *
2033 _text_caret_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2035 const char *obj_path = eldbus_message_path_get(msg);
2036 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2037 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2039 Eldbus_Message *ret;
2042 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2044 if (!eldbus_message_arguments_get(msg, "i", &offset))
2045 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2047 ret = eldbus_message_method_return_new(msg);
2048 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2050 eo_do(obj, res = elm_interface_atspi_text_caret_offset_set(offset));
2052 eldbus_message_arguments_append(ret, "b", res);
2057 static Eldbus_Message *
2058 _text_character_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2060 const char *obj_path = eldbus_message_path_get(msg);
2061 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2062 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2064 Eldbus_Message *ret;
2067 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2069 if (!eldbus_message_arguments_get(msg, "i", &offset))
2070 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2072 ret = eldbus_message_method_return_new(msg);
2073 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2075 eo_do(obj, res = elm_interface_atspi_text_character_get(offset));
2077 eldbus_message_arguments_append(ret, "i", res);
2082 static Eldbus_Message *
2083 _text_attribute_value_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2085 const char *name, *obj_path = eldbus_message_path_get(msg);
2087 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2088 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2090 Eldbus_Message *ret;
2093 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2095 if (!eldbus_message_arguments_get(msg, "is", &start, &name))
2096 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and attribute name expected.");
2098 ret = eldbus_message_method_return_new(msg);
2099 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2101 eo_do(obj, res = elm_interface_atspi_text_attribute_get(name, &start, &end, &value));
2102 eldbus_message_arguments_append(ret, "siib", value ? value : "", start, end, res);
2104 if (value) free(value);
2108 static Eldbus_Message *
2109 _text_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2111 const char *obj_path = eldbus_message_path_get(msg);
2112 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2113 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2115 Eldbus_Message *ret;
2116 Eldbus_Message_Iter *iter, *iter_array;
2118 Elm_Atspi_Text_Attribute *attr;
2120 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2122 if (!eldbus_message_arguments_get(msg, "i", &start))
2123 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2125 ret = eldbus_message_method_return_new(msg);
2126 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2128 iter = eldbus_message_iter_get(ret);
2129 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2130 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2132 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2134 EINA_LIST_FREE(attrs, attr)
2136 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2137 elm_atspi_text_text_attribute_free(attr);
2140 eldbus_message_iter_container_close(iter, iter_array);
2141 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2146 if (ret) eldbus_message_unref(ret);
2150 static Eldbus_Message *
2151 _text_default_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2153 const char *obj_path = eldbus_message_path_get(msg);
2154 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2155 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2156 int start = -1, end;
2157 Eldbus_Message *ret;
2158 Eldbus_Message_Iter *iter, *iter_array;
2160 Elm_Atspi_Text_Attribute *attr;
2162 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2164 ret = eldbus_message_method_return_new(msg);
2165 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2167 iter = eldbus_message_iter_get(ret);
2168 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2169 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2171 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2173 EINA_LIST_FREE(attrs, attr)
2175 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2176 elm_atspi_text_text_attribute_free(attr);
2179 eldbus_message_iter_container_close(iter, iter_array);
2180 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2185 if (ret) eldbus_message_unref(ret);
2189 static Eldbus_Message *
2190 _text_character_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2192 const char *obj_path = eldbus_message_path_get(msg);
2193 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2194 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2196 Eina_Rectangle rect;
2197 AtspiCoordType type;
2198 Eina_Bool screen_coords, res;
2199 Eldbus_Message *ret;
2201 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2203 if (!eldbus_message_arguments_get(msg, "iu", &offset, &type))
2204 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2206 ret = eldbus_message_method_return_new(msg);
2207 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2209 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2211 eo_do(obj, res = elm_interface_atspi_text_character_extents_get(offset, screen_coords, &rect));
2215 eldbus_message_unref(ret);
2216 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get character extents.");
2218 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2223 static Eldbus_Message *
2224 _text_offset_at_point_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2226 const char *obj_path = eldbus_message_path_get(msg);
2227 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2228 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2230 AtspiCoordType type;
2231 Eina_Bool screen_coords;
2232 Eldbus_Message *ret;
2234 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2236 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &type))
2237 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2239 ret = eldbus_message_method_return_new(msg);
2240 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2243 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2245 eo_do(obj, offset = elm_interface_atspi_text_offset_at_point_get(screen_coords, x, y));
2247 eldbus_message_arguments_append(ret, "i", offset);
2252 static Eldbus_Message *
2253 _text_n_selections_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2255 const char *obj_path = eldbus_message_path_get(msg);
2256 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2257 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2259 Eldbus_Message *ret;
2261 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2263 ret = eldbus_message_method_return_new(msg);
2264 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2266 eo_do(obj, n = elm_interface_atspi_text_selections_count_get());
2268 eldbus_message_arguments_append(ret, "i", n);
2273 static Eldbus_Message *
2274 _text_selection_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2276 const char *obj_path = eldbus_message_path_get(msg);
2277 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2278 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2279 int sel_num, start, end;
2280 Eldbus_Message *ret;
2282 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2284 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2285 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2287 ret = eldbus_message_method_return_new(msg);
2288 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2290 eo_do(obj, elm_interface_atspi_text_selection_get(sel_num, &start, &end));
2292 eldbus_message_arguments_append(ret, "ii", start, end);
2297 static Eldbus_Message *
2298 _text_selection_add(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2300 const char *obj_path = eldbus_message_path_get(msg);
2301 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2302 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2305 Eldbus_Message *ret;
2307 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2309 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2310 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end text offset expected.");
2312 ret = eldbus_message_method_return_new(msg);
2313 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2315 eo_do(obj, res = elm_interface_atspi_text_selection_add(start, end));
2317 eldbus_message_arguments_append(ret, "b", res);
2322 static Eldbus_Message *
2323 _text_selection_remove(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2325 const char *obj_path = eldbus_message_path_get(msg);
2326 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2327 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2330 Eldbus_Message *ret;
2332 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2334 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2335 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2337 ret = eldbus_message_method_return_new(msg);
2338 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2340 eo_do(obj, res = elm_interface_atspi_text_selection_remove(sel_num));
2342 eldbus_message_arguments_append(ret, "b", res);
2347 static Eldbus_Message *
2348 _text_selection_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2350 const char *obj_path = eldbus_message_path_get(msg);
2351 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2352 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2353 int sel_num, start, end;
2355 Eldbus_Message *ret;
2357 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2359 if (!eldbus_message_arguments_get(msg, "iii", &sel_num, &start, &end))
2360 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2362 ret = eldbus_message_method_return_new(msg);
2363 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2365 eo_do(obj, res = elm_interface_atspi_text_selection_set(sel_num, start, end));
2367 eldbus_message_arguments_append(ret, "b", res);
2372 static Eldbus_Message *
2373 _text_range_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2375 const char *obj_path = eldbus_message_path_get(msg);
2376 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2377 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2379 Eina_Rectangle rect;
2380 Eina_Bool screen_coords, res;
2381 AtspiCoordType type;
2382 Eldbus_Message *ret;
2384 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2386 if (!eldbus_message_arguments_get(msg, "iiu", &start, &end, &type))
2387 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2389 ret = eldbus_message_method_return_new(msg);
2390 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2392 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2393 eo_do(obj, res = elm_interface_atspi_text_range_extents_get(screen_coords, start, end, &rect));
2396 eldbus_message_unref(ret);
2397 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Can't get range extents.");
2400 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2405 static Eldbus_Message *
2406 _text_bounded_ranges_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2408 const char *obj_path = eldbus_message_path_get(msg);
2409 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2410 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2411 Eina_Rectangle rect;
2412 Eina_Bool screen_coords;
2413 AtspiCoordType type;
2414 Elm_Atspi_Text_Clip_Type xclip, yclip;
2416 Eldbus_Message *ret;
2417 Elm_Atspi_Text_Range *range;
2418 Eldbus_Message_Iter *iter, *iter_array, *iter_struct, *iter_var;
2420 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2422 if (!eldbus_message_arguments_get(msg, "iiiiuuu", &rect.x, &rect.y, &rect.w, &rect.h, &type, &xclip, &yclip))
2423 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.");
2425 ret = eldbus_message_method_return_new(msg);
2426 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2428 iter = eldbus_message_iter_get(ret);
2429 iter_array = eldbus_message_iter_container_new(iter, 'a', "(iisv)");
2430 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2432 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2433 eo_do(obj, ranges = elm_interface_atspi_text_bounded_ranges_get(screen_coords, rect, xclip, yclip));
2435 EINA_LIST_FREE(ranges, range)
2437 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
2440 eldbus_message_iter_basic_append(iter_struct, 'i', range->start_offset);
2441 eldbus_message_iter_basic_append(iter_struct, 'i', range->end_offset);
2442 range->content = range->content ? range->content : strdup("");
2443 eldbus_message_iter_basic_append(iter_struct, 's', range->content);
2444 /* AT-SPI specification requires variant type in return, however
2445 * ATK or other implementations as well as AT Clients don't use it .
2446 * To cover spec a dummy value will be returned */
2447 iter_var = eldbus_message_iter_container_new(iter_struct, 'v', "i");
2450 eldbus_message_iter_basic_append(iter_var, 'i', 0);
2451 eldbus_message_iter_container_close(iter_struct, iter_var);
2453 eldbus_message_iter_container_close(iter_array, iter_struct);
2455 if (range->content) free(range->content);
2459 eldbus_message_iter_container_close(iter, iter_array);
2464 if (ret) eldbus_message_unref(ret);
2468 static Eldbus_Message *
2469 _text_run_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2471 const char *obj_path = eldbus_message_path_get(msg);
2472 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2473 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2475 Eldbus_Message *ret;
2476 Eldbus_Message_Iter *iter, *iter_array;
2477 Eina_List *attrs, *defaults;
2478 Elm_Atspi_Text_Attribute *attr;
2481 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2483 if (!eldbus_message_arguments_get(msg, "ib", &start, &incl_def))
2484 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and include defaults flag expected.");
2486 ret = eldbus_message_method_return_new(msg);
2487 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2489 iter = eldbus_message_iter_get(ret);
2490 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2491 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2493 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2497 eo_do(obj, defaults = elm_interface_atspi_text_default_attributes_get());
2498 attrs = eina_list_merge(attrs, defaults);
2501 EINA_LIST_FREE(attrs, attr)
2503 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2504 elm_atspi_text_text_attribute_free(attr);
2507 eldbus_message_iter_container_close(iter, iter_array);
2508 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2513 if (ret) eldbus_message_unref(ret);
2517 static const Eldbus_Method text_methods[] = {
2518 { "GetTextAtOffset", ELDBUS_ARGS({"i", "offset"}, {"u", "granularity"}), ELDBUS_ARGS({"s", "string"}, {"i", "startOffset"}, {"i", "endOffset"}), _text_string_at_offset_get, 0 },
2519 { "GetText", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"s", "string"}), _text_text_get, 0 },
2520 { "SetCaretOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"b", NULL}), _text_caret_offset_set, 0 },
2521 { "GetCharacterAtOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"i", NULL}), _text_character_at_offset_get, 0 },
2522 { "GetAttributeValue", ELDBUS_ARGS({"i", "offset"}, {"s", "attributeName"}), ELDBUS_ARGS({"s", NULL}, {"i", "startOffset"}, {"i", "endOffset"}, {"b", "defined"}), _text_attribute_value_get, 0 },
2523 { "GetAttributes", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_attributes_get, 0 },
2524 { "GetDefaultAttributes", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2525 { "GetCharacterExtents", ELDBUS_ARGS({"i", "offset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_character_extents_get, 0 },
2526 { "GetOffsetAtPoint", ELDBUS_ARGS({"i", "x"}, {"i","y"}, {"u", "coordType"}), ELDBUS_ARGS({"i", NULL}), _text_offset_at_point_get, 0 },
2527 { "GetNSelections", NULL, ELDBUS_ARGS({"i", NULL}), _text_n_selections_get, 0 },
2528 { "GetSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), _text_selection_get, 0 },
2529 { "AddSelection", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_add, 0 },
2530 { "RemoveSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"b", NULL}), _text_selection_remove, 0 },
2531 { "SetSelection", ELDBUS_ARGS({"i", "selectionNum"}, {"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_set, 0 },
2532 { "GetRangeExtents", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_range_extents_get, 0 },
2533 { "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 },
2534 { "GetAttributeRun", ELDBUS_ARGS({"i", "offset"}, {"b", "includeDefaults"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_run_attributes_get, 0 },
2535 { "GetDefaultAttributeSet", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2536 { NULL, NULL, NULL, NULL, 0 }
2539 static Eldbus_Message *
2540 _editable_text_text_content_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2542 const char *obj_path = eldbus_message_path_get(msg);
2543 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2544 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2545 const char *content;
2546 Eldbus_Message *ret;
2549 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2551 if (!eldbus_message_arguments_get(msg, "s", &content))
2552 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "String expected.");
2554 ret = eldbus_message_method_return_new(msg);
2555 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2557 eo_do(obj, res = elm_interface_atspi_editable_text_content_set(content));
2559 eldbus_message_arguments_append(ret, "b", res);
2564 static Eldbus_Message *
2565 _editable_text_text_insert(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2567 const char *obj_path = eldbus_message_path_get(msg);
2568 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2569 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2571 Eldbus_Message *ret;
2575 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2577 if (!eldbus_message_arguments_get(msg, "isi", &pos, &text, &len))
2578 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Postion, string, length expected.");
2580 ret = eldbus_message_method_return_new(msg);
2581 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2583 eo_do(obj, res = elm_interface_atspi_editable_text_insert(text, pos));
2585 eldbus_message_arguments_append(ret, "b", res);
2590 static Eldbus_Message *
2591 _editable_text_text_copy(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2593 const char *obj_path = eldbus_message_path_get(msg);
2594 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2595 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2596 Eldbus_Message *ret;
2600 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2602 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2603 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2605 ret = eldbus_message_method_return_new(msg);
2606 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2608 eo_do(obj, res = elm_interface_atspi_editable_text_copy(start, end));
2610 eldbus_message_arguments_append(ret, "b", res);
2615 static Eldbus_Message *
2616 _editable_text_text_cut(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2618 const char *obj_path = eldbus_message_path_get(msg);
2619 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2620 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2621 Eldbus_Message *ret;
2625 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2627 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2628 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2630 ret = eldbus_message_method_return_new(msg);
2631 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2633 eo_do(obj, res = elm_interface_atspi_editable_text_cut(start, end));
2635 eldbus_message_arguments_append(ret, "b", res);
2640 static Eldbus_Message *
2641 _editable_text_text_delete(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2643 const char *obj_path = eldbus_message_path_get(msg);
2644 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2645 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2646 Eldbus_Message *ret;
2650 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2652 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2653 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2655 ret = eldbus_message_method_return_new(msg);
2656 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2658 eo_do(obj, res = elm_interface_atspi_editable_text_delete(start, end));
2660 eldbus_message_arguments_append(ret, "b", res);
2665 static Eldbus_Message *
2666 _editable_text_text_paste(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2668 const char *obj_path = eldbus_message_path_get(msg);
2669 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2670 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2671 Eldbus_Message *ret;
2675 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2677 if (!eldbus_message_arguments_get(msg, "i", &pos))
2678 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2680 ret = eldbus_message_method_return_new(msg);
2681 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2683 eo_do(obj, res = elm_interface_atspi_editable_text_paste(pos));
2685 eldbus_message_arguments_append(ret, "b", res);
2691 _elm_atspi_bridge_plug_id_split(const char *plug_id, char **bus, char **path)
2693 if (!plug_id || !strcmp(plug_id, "")) return EINA_FALSE;
2694 unsigned int tokens = 0;
2695 char **split = eina_str_split_full(plug_id, ":", 0, &tokens);
2696 Eina_Bool ret = EINA_FALSE;
2699 if (!split[0] || !split[1])
2703 if (bus) *bus = strdup(split[0]);
2704 if (path) *path = strdup(split[1]);
2708 else if (tokens == 3)
2710 if (!split[0] || !split[1] || !split[2])
2715 snprintf(buf, sizeof(buf), "%s:%s",split[0], split[1]);
2716 if (bus) *bus = strdup(buf);
2717 if (path) *path = strdup(split[2]);
2727 static Eldbus_Message *
2728 _socket_embedded(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
2731 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2732 const char *obj_path = eldbus_message_path_get(msg);
2734 const char *bus, *path;
2735 Eo *bridge = _elm_atspi_bridge_get();
2736 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2737 eo_do(obj, proxy = elm_interface_atspi_accessible_parent_get());
2739 if (!eo_isa(proxy, ELM_ATSPI_PROXY_CLASS))
2740 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to embed object.");
2742 if (!eldbus_message_arguments_get(msg, "s", &path))
2743 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Plug id expected.");
2745 bus = eldbus_message_sender_get(msg);
2747 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
2749 _bridge_cache_build(bridge, proxy);
2751 return eldbus_message_method_return_new(msg);
2754 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2755 static Eldbus_Message *
2756 _socket_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2760 Eo *obj = eldbus_service_object_data_get(iface, "_atspi_obj");
2761 eo_do(obj, parent = eo_parent_get());
2762 Evas_Object *top = elm_object_top_widget_get(parent);
2764 if (!eldbus_message_arguments_get(msg, "ii", &x, &y))
2765 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
2767 eo_do(top, elm_interface_atspi_component_socket_offset_set(x, y));
2769 return eldbus_message_method_return_new(msg);
2773 static const Eldbus_Method editable_text_methods[] = {
2774 { "SetTextContents", ELDBUS_ARGS({"s", "newcontents"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_content_set, 0 },
2775 { "InsertText", ELDBUS_ARGS({"i", "position"}, {"s", "text"}, {"i", "length"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_insert, 0 },
2776 { "CopyText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), NULL, _editable_text_text_copy, 0 },
2777 { "CutText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_cut, 0 },
2778 { "DeleteText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_delete, 0 },
2779 { "PasteText", ELDBUS_ARGS({"i", "position"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_paste, 0 },
2780 { NULL, NULL, NULL, NULL, 0 }
2783 static const Eldbus_Method socket_methods[] = {
2784 { "Embedded", ELDBUS_ARGS({"s", "id"}), ELDBUS_ARGS({NULL, NULL}), _socket_embedded, 0 },
2785 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2786 { "SetOffset", ELDBUS_ARGS({"i", "x"}, {"i", "y"}), ELDBUS_ARGS({NULL, NULL}), _socket_offset_set, 0 },
2788 { NULL, NULL, NULL, NULL, 0 }
2791 static const Eldbus_Service_Interface_Desc socket_iface_desc = {
2792 ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL
2796 _bridge_object_from_path(Eo *bridge, const char *path)
2798 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2799 unsigned long long eo_ptr = 0;
2801 const char *tmp = path;
2804 int len = strlen(ELM_ACCESS_OBJECT_PATH_PREFIX);
2805 if (strncmp(path, ELM_ACCESS_OBJECT_PATH_PREFIX, len))
2808 tmp = path + len; /* Skip over the prefix */
2809 if (!strcmp(ELM_ACCESS_OBJECT_PATH_ROOT, tmp))
2810 return elm_atspi_bridge_root_get(bridge);
2812 sscanf(tmp, "%llu", &eo_ptr);
2813 eo = (Eo *) (uintptr_t) eo_ptr;
2815 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
2816 if (!eina_hash_find(pd->cache, &eo))
2818 WRN("Request for non-registered object: %s", path);
2822 ret = eo_isa(eo, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN) ? eo : NULL;
2828 _bridge_path_from_object(Eo *bridge, const Eo *eo)
2830 static char path[64];
2833 return ATSPI_DBUS_PATH_NULL;
2835 if (eo == elm_atspi_bridge_root_get(bridge))
2836 snprintf(path, sizeof(path), "%s%s", ELM_ACCESS_OBJECT_PATH_PREFIX, ELM_ACCESS_OBJECT_PATH_ROOT);
2838 snprintf(path, sizeof(path), ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE, (unsigned long long)(uintptr_t)eo);
2843 _accessible_property_get(const Eldbus_Service_Interface *interface, const char *property,
2844 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2845 Eldbus_Message **error)
2847 const char *ret = NULL, *obj_path = eldbus_message_path_get(request_msg);
2848 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2849 Eo *ret_obj = NULL, *obj = _bridge_object_from_path(bridge, obj_path);
2851 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, request_msg, error);
2853 if (!strcmp(property, "Name"))
2855 eo_do(obj, ret = elm_interface_atspi_accessible_name_get());
2858 eldbus_message_iter_basic_append(iter, 's', ret);
2861 else if (!strcmp(property, "Description"))
2863 eo_do(obj, ret = elm_interface_atspi_accessible_description_get());
2866 eldbus_message_iter_basic_append(iter, 's', ret);
2869 else if (!strcmp(property, "Parent"))
2871 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
2872 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
2873 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
2874 if ((!ret_obj) && (ELM_ATSPI_ROLE_APPLICATION == role))
2875 _object_desktop_reference_append(iter);
2877 _bridge_iter_object_reference_append(bridge, iter, ret_obj);
2880 else if (!strcmp(property, "ChildCount"))
2882 Eina_List *l = NULL;
2883 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
2884 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
2892 _selection_property_get(const Eldbus_Service_Interface *interface, const char *property,
2893 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2894 Eldbus_Message **error)
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_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, request_msg, error);
2903 if (!strcmp(property, "NSelectedChildren"))
2905 eo_do(obj, n = elm_interface_atspi_selection_selected_children_count_get());
2906 eldbus_message_iter_basic_append(iter, 'i', n);
2913 _action_property_get(const Eldbus_Service_Interface *interface, const char *property,
2914 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2915 Eldbus_Message **error)
2918 const char *obj_path = eldbus_message_path_get(request_msg);
2919 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2920 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2922 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, request_msg, error);
2924 if (!strcmp(property, "NActions"))
2926 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
2927 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(actions));
2928 eina_list_free(actions);
2934 static Eldbus_Message*
2935 _value_properties_set(const Eldbus_Service_Interface *interface, const char *property,
2936 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg)
2940 const char *obj_path = eldbus_message_path_get(request_msg);
2941 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2942 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2944 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg);
2946 if (!eldbus_message_iter_arguments_get(iter, "d", &value))
2948 return eldbus_message_error_new(request_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: double.");
2951 if (!strcmp(property, "CurrentValue"))
2953 eo_do(obj, ret = elm_interface_atspi_value_and_text_set(value, NULL));
2954 Eldbus_Message *answer = eldbus_message_method_return_new(request_msg);
2955 eldbus_message_arguments_append(answer, "b", ret);
2963 _value_properties_get(const Eldbus_Service_Interface *interface, const char *property,
2964 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2965 Eldbus_Message **error)
2968 const char *obj_path = eldbus_message_path_get(request_msg);
2969 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2970 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2972 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg, error);
2974 if (!strcmp(property, "CurrentValue"))
2976 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
2977 eldbus_message_iter_basic_append(iter, 'd', value);
2980 if (!strcmp(property, "MinimumValue"))
2982 eo_do(obj, elm_interface_atspi_value_range_get(&value, NULL, NULL));
2983 eldbus_message_iter_basic_append(iter, 'd', value);
2986 if (!strcmp(property, "MaximumValue"))
2988 eo_do(obj, elm_interface_atspi_value_range_get(NULL, &value, NULL));
2989 eldbus_message_iter_basic_append(iter, 'd', value);
2992 if (!strcmp(property, "MinimumIncrement"))
2994 eo_do(obj, value = elm_interface_atspi_value_increment_get());
2995 eldbus_message_iter_basic_append(iter, 'd', value);
3002 _image_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3003 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3004 Eldbus_Message **error)
3007 const char *obj_path = eldbus_message_path_get(request_msg);
3008 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3009 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3011 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, request_msg, error);
3013 if (!strcmp(property, "ImageDescription"))
3015 eo_do(obj, value = elm_interface_atspi_image_description_get());
3016 value = value ? value : "";
3017 eldbus_message_iter_basic_append(iter, 's', value);
3020 if (!strcmp(property, "ImageLocale"))
3022 eo_do(obj, value = elm_interface_atspi_image_locale_get());
3023 value = value ? value : "";
3024 eldbus_message_iter_basic_append(iter, 's', value);
3031 _text_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3032 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3033 Eldbus_Message **error)
3035 const char *obj_path = eldbus_message_path_get(request_msg);
3036 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3037 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3040 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, request_msg, error);
3042 if (!strcmp(property, "CharacterCount"))
3044 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
3045 eldbus_message_iter_basic_append(iter, 'i', val);
3048 if (!strcmp(property, "CaretOffset"))
3050 eo_do(obj, val = elm_interface_atspi_text_caret_offset_get());
3051 eldbus_message_iter_basic_append(iter, 'i', val);
3057 static Eldbus_Message*
3058 _application_properties_set(const Eldbus_Service_Interface *iface, const char *property, Eldbus_Message_Iter *iter, const Eldbus_Message *input_msg)
3060 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3061 const char *obj_path = eldbus_message_path_get(input_msg);
3062 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3065 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
3066 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, input_msg);
3068 if (!eldbus_message_iter_arguments_get(iter, "i", &value))
3070 return eldbus_message_error_new(input_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: int.");
3073 if (!strcmp(property, "Id"))
3076 Eldbus_Message *answer = eldbus_message_method_return_new(input_msg);
3077 eldbus_message_arguments_append(answer, "b", EINA_TRUE);
3085 _application_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3086 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3087 Eldbus_Message **error)
3089 const char *obj_path = eldbus_message_path_get(request_msg);
3090 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3091 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3093 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
3094 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, request_msg, error);
3096 if (!strcmp(property, "ToolkitName"))
3098 eldbus_message_iter_basic_append(iter, 's', "elementary");
3101 if (!strcmp(property, "Version"))
3104 snprintf(buf, sizeof(buf), "%d.%d", ELM_VERSION_MAJOR, ELM_VERSION_MINOR);
3105 eldbus_message_iter_basic_append(iter, 's', buf);
3108 if (!strcmp(property, "Id"))
3110 eldbus_message_iter_basic_append(iter, 'i', pd->id);
3116 static const Eldbus_Property accessible_properties[] = {
3117 { "Name", "s", NULL, NULL, 0 },
3118 { "Description", "s", NULL, NULL, 0 },
3119 { "Parent", "(so)", NULL, NULL, 0 },
3120 { "ChildCount", "i", NULL, NULL, 0 },
3121 { NULL, NULL, NULL, NULL, 0 }
3124 static const Eldbus_Property action_properties[] = {
3125 { "NActions", "i", _action_property_get, NULL, 0 },
3126 { NULL, NULL, NULL, NULL, 0 }
3129 static const Eldbus_Property value_properties[] = {
3130 { "MinimumValue", "d", NULL, NULL, 0 },
3131 { "MaximumValue", "d", NULL, NULL, 0 },
3132 { "MinimumIncrement", "d", NULL, NULL, 0 },
3133 { "CurrentValue", "d", NULL, NULL, 0 },
3134 { NULL, NULL, NULL, NULL, 0 }
3137 static const Eldbus_Property image_properties[] = {
3138 { "ImageDescription", "s", NULL, NULL, 0 },
3139 { "ImageLocale", "s", NULL, NULL, 0 },
3140 { NULL, NULL, NULL, NULL, 0 }
3143 static const Eldbus_Property selection_properties[] = {
3144 { "NSelectedChildren", "i", _selection_property_get, NULL, 0 },
3145 { NULL, NULL, NULL, NULL, 0 }
3148 static const Eldbus_Property text_properties[] = {
3149 { "CharacterCount", "i", NULL, NULL, 0 },
3150 { "CaretOffset", "i", NULL, NULL, 0 },
3151 { NULL, NULL, NULL, NULL, 0 }
3154 static const Eldbus_Property application_properties[] = {
3155 { "ToolkitName", "s", NULL, NULL, 0 },
3156 { "Version", "s", NULL, NULL, 0 },
3157 { "Id", "i", NULL, NULL, 0 },
3158 { NULL, NULL, NULL, NULL, 0 }
3161 static const Eldbus_Service_Interface_Desc accessible_iface_desc = {
3162 ATSPI_DBUS_INTERFACE_ACCESSIBLE, accessible_methods, NULL, accessible_properties, _accessible_property_get, NULL
3165 static const Eldbus_Service_Interface_Desc action_iface_desc = {
3166 ATSPI_DBUS_INTERFACE_ACTION, action_methods, NULL, action_properties, NULL, NULL
3169 static const Eldbus_Service_Interface_Desc value_iface_desc = {
3170 ATSPI_DBUS_INTERFACE_VALUE, NULL, NULL, value_properties, _value_properties_get, _value_properties_set
3173 static const Eldbus_Service_Interface_Desc image_iface_desc = {
3174 ATSPI_DBUS_INTERFACE_IMAGE, image_methods, NULL, image_properties, _image_properties_get, NULL
3177 static const Eldbus_Service_Interface_Desc selection_iface_desc = {
3178 ATSPI_DBUS_INTERFACE_SELECTION, selection_methods, NULL, selection_properties, NULL, NULL
3181 static const Eldbus_Service_Interface_Desc text_iface_desc = {
3182 ATSPI_DBUS_INTERFACE_TEXT, text_methods, NULL, text_properties, _text_properties_get, NULL
3185 static const Eldbus_Service_Interface_Desc editable_text_iface_desc = {
3186 ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, editable_text_methods, NULL, NULL, NULL, NULL
3189 static const Eldbus_Service_Interface_Desc application_iface_desc = {
3190 ATSPI_DBUS_INTERFACE_APPLICATION, NULL, NULL, application_properties, _application_properties_get, _application_properties_set
3194 _collection_match_rule_free(struct collection_match_rule *rule)
3196 Elm_Atspi_Attribute *attr;
3197 eina_list_free(rule->ifaces);
3198 EINA_LIST_FREE(rule->attributes, attr)
3200 eina_stringshare_del(attr->key);
3201 eina_stringshare_del(attr->value);
3206 _collection_roles_convert(uint64_t roles[2])
3208 // Currently elm roles and atspi roles are binary compatible.
3209 // Implement this function when it will be needed.
3214 _collection_iter_match_rule_get(Eldbus_Message_Iter *iter, struct collection_match_rule *rule)
3216 Eldbus_Message_Iter *states_iter, *attrib_iter, *iter_arg, *role_iter, *ifc_iter;
3217 unsigned int *array;
3218 int array_count, state_match, attrib_match, role_match, ifc_match, reverse;
3219 const char *ifc_name;
3221 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))
3223 ERR("Unable to get message arguments");
3227 memset(rule, 0x0, sizeof(struct collection_match_rule));
3228 rule->statematchtype = state_match;
3229 rule->attributematchtype = attrib_match;
3230 rule->rolematchtype = role_match;
3231 rule->interfacematchtype = ifc_match;
3232 rule->reverse = reverse;
3234 if (!eldbus_message_iter_fixed_array_get(states_iter, 'i', &array, &array_count))
3237 //Roles according to libatspi impementation are transferred in 2-int element fixed bit array
3238 if (array_count != 2)
3240 ERR("Unexpected states array size");
3243 uint64_t states = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3244 rule->states = _atspi_state_set_to_elm_atspi_state_set(states);
3246 //Roles according to libatspi impementation are transferred in 4-int element fixed bit array
3247 if (!eldbus_message_iter_fixed_array_get(role_iter, 'i', &array, &array_count))
3250 if (array_count != 4)
3252 ERR("Unexpected roles array size");
3256 //convert atspi roles to elm_roles
3257 rule->roles[0] = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3258 rule->roles[1] = ((uint64_t)array[2] | ((uint64_t)array[3] << 32));
3260 _collection_roles_convert(rule->roles);
3262 //Get matching properties
3263 while (eldbus_message_iter_get_and_next(attrib_iter, '{', &iter_arg))
3265 const char *key, *value;
3266 if (eldbus_message_iter_arguments_get(iter_arg, "ss", &key, &value))
3268 Elm_Atspi_Attribute *attrib = calloc(sizeof(Elm_Atspi_Attribute), 1);
3269 attrib->key = eina_stringshare_add(key);
3270 attrib->value = eina_stringshare_add(value);
3271 rule->attributes = eina_list_append(rule->attributes, attrib);
3275 //Get interfaces to match
3276 while (eldbus_message_iter_get_and_next(ifc_iter, 's', &ifc_name))
3278 const Eo_Class *class = NULL;
3279 if (!strcmp(ifc_name, "action"))
3280 class = ELM_INTERFACE_ATSPI_ACTION_MIXIN;
3281 else if (!strcmp(ifc_name, "component"))
3282 class = ELM_INTERFACE_ATSPI_COMPONENT_MIXIN;
3283 else if (!strcmp(ifc_name, "editabletext"))
3284 class = ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE;
3285 else if (!strcmp(ifc_name, "text"))
3286 class = ELM_INTERFACE_ATSPI_TEXT_INTERFACE;
3287 else if (!strcmp(ifc_name, "image"))
3288 class = ELM_INTERFACE_ATSPI_SELECTION_INTERFACE;
3289 else if (!strcmp(ifc_name, "value"))
3290 class = ELM_INTERFACE_ATSPI_VALUE_INTERFACE;
3293 rule->ifaces = eina_list_append(rule->ifaces, class);
3296 _collection_match_rule_free(rule);
3305 _collection_match_interfaces_helper(Eo *obj, Eina_List *ifcs, Eina_Bool condition, Eina_Bool ret_if_true, Eina_Bool ret_if_false)
3310 EINA_LIST_FOREACH(ifcs, l, class)
3312 if (eo_isa(obj, class) == condition)
3315 return ret_if_false;
3319 _collection_match_interfaces_lookup(Eo *obj, struct collection_match_rule *rule)
3321 Eina_Bool ret = EINA_FALSE;
3323 switch (rule->interfacematchtype)
3325 case ATSPI_Collection_MATCH_INVALID:
3328 case ATSPI_Collection_MATCH_ALL:
3329 ret = _collection_match_interfaces_helper(
3330 obj, rule->ifaces, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3332 case ATSPI_Collection_MATCH_ANY:
3333 ret = _collection_match_interfaces_helper(
3334 obj, rule->ifaces, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3336 case ATSPI_Collection_MATCH_NONE:
3337 ret = _collection_match_interfaces_helper(
3338 obj, rule->ifaces, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3347 _collection_match_states_lookup(Eo *obj, struct collection_match_rule *rule)
3349 Eina_Bool ret = EINA_FALSE;
3350 Elm_Atspi_State_Set ss;
3352 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
3354 switch (rule->statematchtype)
3356 case ATSPI_Collection_MATCH_INVALID:
3359 case ATSPI_Collection_MATCH_ALL:
3360 ret = (ss & rule->states) == rule->states;
3362 case ATSPI_Collection_MATCH_ANY:
3363 ret = (ss & rule->states) > 0;
3365 case ATSPI_Collection_MATCH_NONE:
3366 ret = (ss & rule->states) == 0;
3376 _collection_match_roles_lookup(Eo *obj, struct collection_match_rule *rule)
3378 Eina_Bool ret = EINA_FALSE;
3379 Elm_Atspi_Role role;
3382 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
3387 role_set = rule->roles[1];
3390 role_set = rule->roles[0];
3394 ERR("Elm_Atspi_Role enum value exceeds 127. Unable to compare with roles bit field.");
3398 switch (rule->rolematchtype)
3400 case ATSPI_Collection_MATCH_INVALID:
3403 case ATSPI_Collection_MATCH_ALL:
3404 case ATSPI_Collection_MATCH_ANY:
3405 ret = (role_set & (1ULL << role)) > 0;
3407 case ATSPI_Collection_MATCH_NONE:
3408 ret = (role_set & (1ULL << role)) == 0;
3418 _collection_match_attributes_helper(Eina_List *obj_attribs, Eina_List *attribs, Eina_Bool compare, Eina_Bool ret_if_compare, Eina_Bool ret_default)
3421 Elm_Atspi_Attribute *attr, *attr2;
3423 EINA_LIST_FOREACH(attribs, l, attr)
3425 EINA_LIST_FOREACH(obj_attribs, l2, attr2)
3427 if ((attr->key && attr2->key &&
3428 attr->value && attr2->value &&
3429 !strcmp(attr->key, attr2->key) &&
3430 !strcmp(attr->value, attr2->value)) == compare)
3432 return ret_if_compare;
3441 _collection_match_attributes_lookup(Eo *obj, struct collection_match_rule *rule)
3443 Eina_Bool ret = EINA_FALSE;
3444 Eina_List *obj_attribs;
3446 eo_do(obj, obj_attribs = elm_interface_atspi_accessible_attributes_get());
3448 switch (rule->attributematchtype)
3450 case ATSPI_Collection_MATCH_INVALID:
3453 case ATSPI_Collection_MATCH_ALL:
3454 ret = _collection_match_attributes_helper(
3455 obj_attribs, rule->attributes, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3457 case ATSPI_Collection_MATCH_ANY:
3458 ret = _collection_match_attributes_helper(
3459 obj_attribs, rule->attributes, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3461 case ATSPI_Collection_MATCH_NONE:
3462 ret = _collection_match_attributes_helper(
3463 obj_attribs, rule->attributes, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3469 elm_atspi_attributes_list_free(obj_attribs);
3475 _collection_sort_order_canonical(struct collection_match_rule *rule, Eina_List **ls,
3477 Eo *obj, long index, Eina_Bool flag,
3478 Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3481 Eina_List *children;
3482 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
3483 long acount = eina_list_count(children);
3484 Eina_Bool prev = pobj ? EINA_TRUE : EINA_FALSE;
3486 for (; i < acount && (max == 0 || count < max); i++)
3488 Eo *child = eina_list_nth(children, i);
3490 if (prev && child == pobj)
3492 eina_list_free(children);
3496 if (flag && _collection_match_interfaces_lookup(child, rule)
3497 && _collection_match_states_lookup(child, rule)
3498 && _collection_match_roles_lookup(child, rule)
3499 && _collection_match_attributes_lookup(child, rule))
3501 *ls = eina_list_append(*ls, child);
3508 if (recurse && traverse)
3509 count = _collection_sort_order_canonical(rule, ls, count,
3510 max, child, 0, EINA_TRUE,
3511 pobj, recurse, traverse);
3513 eina_list_free(children);
3518 _collection_sort_order_reverse_canonical(struct collection_match_rule *rule, Eina_List **ls,
3519 int count, int max, Eo *obj, Eina_Bool flag, Eo *pobj)
3521 Eo *nextobj, *parent;
3523 Eina_List *children;
3525 /* This breaks us out of the recursion. */
3526 if (!obj || obj == pobj)
3531 /* Add to the list if it matches */
3532 if (flag && _collection_match_interfaces_lookup(obj, rule)
3533 && _collection_match_states_lookup(obj, rule)
3534 && _collection_match_roles_lookup(obj, rule)
3535 && _collection_match_attributes_lookup(obj, rule)
3536 && (max == 0 || count < max))
3538 *ls = eina_list_append(*ls, obj);
3545 /* Get the current nodes index in it's parent and the parent object. */
3547 indexinparent = elm_interface_atspi_accessible_index_in_parent_get(),
3548 parent = elm_interface_atspi_accessible_parent_get());
3550 if ((indexinparent > 0) && ((max == 0) || (count < max)))
3552 /* there are still some siblings to visit so get the previous sibling
3553 and get it's last descendant.
3554 First, get the previous sibling */
3555 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
3556 nextobj = eina_list_nth(children, indexinparent - 1);
3557 eina_list_free(children);
3559 /* Now, drill down the right side to the last descendant */
3561 eo_do(nextobj, children = elm_interface_atspi_accessible_children_get());
3562 if (children) nextobj = eina_list_last_data_get(children);
3563 eina_list_free(children);
3566 /* recurse with the last descendant */
3567 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3568 nextobj, EINA_TRUE, pobj);
3570 else if (max == 0 || count < max)
3572 /* no more siblings so next node must be the parent */
3573 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3574 parent, EINA_TRUE, pobj);
3581 _collection_inbackorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3584 *list = eina_list_append(*list, obj);
3586 _collection_sort_order_reverse_canonical(rule, list, 0, max, obj, EINA_TRUE, collection);
3588 *list = eina_list_remove_list(*list, *list);
3594 _collection_inorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3595 int count, int max, Eo *obj, Eina_Bool traverse)
3599 count = _collection_sort_order_canonical(rule, list, count, max, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3601 while ((max == 0 || count < max) && obj && obj != collection)
3605 parent = elm_interface_atspi_accessible_parent_get(),
3606 idx = elm_interface_atspi_accessible_index_in_parent_get());
3607 count = _collection_sort_order_canonical(rule, list, count, max, parent,
3608 idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3612 if (max == 0 || count < max)
3613 count = _collection_sort_order_canonical(rule, list, count, max,
3614 obj, idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3620 _collection_query(struct collection_match_rule *rule, AtspiCollectionSortOrder sortby,
3621 Eina_List **list, int count, int max, Eo *obj, long index,
3622 Eina_Bool flag, Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3626 case ATSPI_Collection_SORT_ORDER_CANONICAL:
3627 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3628 pobj, recurse, traverse);
3630 case ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL:
3631 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3632 pobj, recurse, traverse);
3633 *list = eina_list_reverse(*list);
3637 WRN("Unhandled sort method");
3643 static Eldbus_Message*
3644 _collection_return_msg_from_list(Elm_Atspi_Bridge *bridge, const Eldbus_Message *msg, const Eina_List *objs)
3646 Eldbus_Message *ret;
3648 Eldbus_Message_Iter *iter, *array_iter;
3651 ret = eldbus_message_method_return_new(msg);
3652 if (!ret) return NULL;
3654 iter = eldbus_message_iter_get(ret);
3655 array_iter = eldbus_message_iter_container_new(iter, 'a', "(so)");
3657 EINA_LIST_FOREACH(objs, l, obj)
3659 _bridge_object_register(bridge, obj);
3660 _bridge_iter_object_reference_append(bridge, array_iter, obj);
3663 eldbus_message_iter_container_close(iter, array_iter);
3668 _collection_get_matches_from_handle(Eo *collection, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, int max, Eina_Bool traverse)
3670 Eina_List *result = NULL;
3676 case ATSPI_Collection_TREE_INORDER:
3677 _collection_inorder(collection, rule, &result, 0, max, current, traverse);
3678 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3679 result = eina_list_reverse(result);
3681 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3683 idx = elm_interface_atspi_accessible_index_in_parent_get(),
3684 parent = elm_interface_atspi_accessible_parent_get());
3685 _collection_query(rule, sortby, &result, 0, max, parent, idx, EINA_FALSE, NULL, EINA_TRUE, traverse);
3687 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3688 _collection_query(rule, sortby, &result, 0, max, current, 0, EINA_FALSE, NULL, EINA_TRUE, traverse);
3691 ERR("Tree parameter value not handled");
3697 static Eldbus_Message*
3698 _collection_get_matches_from(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3700 const char *obj_path = eldbus_message_path_get(msg);
3701 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3702 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3703 Eldbus_Message *ret;
3704 Eldbus_Message_Iter *iter, *rule_iter;
3705 struct collection_match_rule rule;
3707 AtspiCollectionTreeTraversalType tree;
3709 AtspiCollectionSortOrder sortby;
3710 Eina_List *result = NULL;
3712 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3714 iter = eldbus_message_iter_get(msg);
3715 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3717 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uuib", &obj_path, &rule_iter, &sortby, &tree, &count, &traverse))
3719 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3722 current = _bridge_object_from_path(bridge, obj_path);
3724 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3726 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3727 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3729 result = _collection_get_matches_from_handle(obj, current, &rule, sortby, tree, count, traverse);
3730 ret = _collection_return_msg_from_list(bridge, msg, result);
3732 eina_list_free(result);
3733 _collection_match_rule_free(&rule);
3739 _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)
3741 Eina_List *result = NULL;
3742 Eo *collection = obj;
3745 eo_do(obj, collection = elm_interface_atspi_accessible_parent_get());
3749 case ATSPI_Collection_TREE_INORDER:
3750 _collection_inbackorder(obj, rule, &result, max, current);
3751 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3752 result = eina_list_reverse(result);
3754 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3755 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3757 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3758 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3761 ERR("Tree parameter value not handled");
3768 static Eldbus_Message*
3769 _collection_get_matches_to(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3771 const char *obj_path = eldbus_message_path_get(msg);
3772 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3773 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3774 Eldbus_Message *ret;
3775 Eldbus_Message_Iter *iter, *rule_iter;
3776 struct collection_match_rule rule;
3778 AtspiCollectionTreeTraversalType tree;
3780 AtspiCollectionSortOrder sortby;
3781 Eina_List *result = NULL;
3784 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3786 iter = eldbus_message_iter_get(msg);
3787 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3789 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uubib", &obj_path, &rule_iter, &sortby, &tree, &limit, &count, &traverse))
3791 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, tree, limit count or traverse values.");
3794 current = _bridge_object_from_path(bridge, obj_path);
3796 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3798 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3799 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3801 result = _collection_get_matches_to_handle(obj, current, &rule, sortby, tree, limit, count, traverse);
3802 ret = _collection_return_msg_from_list(bridge, msg, result);
3804 eina_list_free(result);
3805 _collection_match_rule_free(&rule);
3810 static Eldbus_Message*
3811 _collection_get_matches(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
3813 const char *obj_path = eldbus_message_path_get(msg);
3814 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3815 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3816 Eldbus_Message *ret;
3817 Eldbus_Message_Iter *iter, *rule_iter;
3818 struct collection_match_rule rule;
3821 AtspiCollectionSortOrder sortby;
3822 Eina_List *result = NULL;
3824 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3826 iter = eldbus_message_iter_get(msg);
3827 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3829 if (!eldbus_message_iter_arguments_get(iter, "(aiia{ss}iaiiasib)uib", &rule_iter, &sortby, &count, &traverse))
3831 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3834 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3835 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3837 _collection_query(&rule, sortby, &result, 0, count, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3839 ret = _collection_return_msg_from_list(bridge, msg, result);
3841 eina_list_free(result);
3842 _collection_match_rule_free(&rule);
3847 static const Eldbus_Method collection_methods[] = {
3849 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3850 {"u", "sortby"}, {"u", "tree"}, {"i", "count"}, {"b", "traverse"}),
3851 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_from, 0 },
3853 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3854 {"u", "sortby"}, {"u", "tree"}, {"b", "limit_scope"},
3855 {"i", "count"}, {"b", "traverse"}),
3856 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_to, 0 },
3858 ELDBUS_ARGS({"(aiia{ss}iaiiasib)", "match_rule"},
3859 {"u", "sortby"}, {"i", "count"}, {"b", "traverse"}),
3860 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches, 0 },
3861 { NULL, NULL, NULL, NULL, 0 }
3864 static const Eldbus_Service_Interface_Desc collection_iface_desc = {
3865 ATSPI_DBUS_INTERFACE_COLLECTION, collection_methods, NULL, NULL, NULL, NULL
3869 _object_get_bus_name_and_path(Eo *bridge, const Eo *obj, const char **bus_name, const char **path)
3871 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
3873 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
3874 if (eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
3876 const char *pbus = "", *ppath = ATSPI_DBUS_PATH_NULL;
3877 eo_do(obj, elm_obj_atspi_proxy_address_get(&pbus, &ppath));
3880 if (bus_name) *bus_name = pbus;
3881 if (path) *path = ppath;
3884 DBG("Invalid proxy address! Address not set before connecting/listening. Or after proxy is removed.");
3886 if (bus_name) *bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
3887 if (path) *path = _bridge_path_from_object(bridge, obj);
3892 _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj)
3894 EINA_SAFETY_ON_NULL_RETURN(iter);
3896 const char *pbus = NULL, *ppath = NULL;
3897 _object_get_bus_name_and_path(bridge, obj, &pbus, &ppath);
3898 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3899 eldbus_message_iter_basic_append(iter_struct, 's', pbus);
3900 eldbus_message_iter_basic_append(iter_struct, 'o', ppath);
3901 eldbus_message_iter_container_close(iter, iter_struct);
3905 _object_desktop_reference_append(Eldbus_Message_Iter *iter)
3907 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3908 EINA_SAFETY_ON_NULL_RETURN(iter);
3910 eldbus_message_iter_basic_append(iter_struct, 's', ATSPI_DBUS_NAME_REGISTRY);
3911 eldbus_message_iter_basic_append(iter_struct, 'o', ATSPI_DBUS_PATH_ROOT);
3912 eldbus_message_iter_container_close(iter, iter_struct);
3916 _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj)
3918 Eldbus_Message_Iter *iter_array;
3919 iter_array = eldbus_message_iter_container_new(iter, 'a', "s");
3920 if (!iter_array) return;
3922 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
3924 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE);
3925 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COLLECTION);
3927 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN))
3928 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACTION);
3929 if (eo_isa(obj, ELM_ATSPI_APP_OBJECT_CLASS))
3930 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_APPLICATION);
3931 if (eo_isa(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN))
3932 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COMPONENT);
3933 if (eo_isa(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE))
3934 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_EDITABLE_TEXT);
3935 if (eo_isa(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN))
3936 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_IMAGE);
3937 if (eo_isa(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
3938 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_SELECTION);
3939 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
3940 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_TEXT);
3941 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
3942 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_VALUE);
3944 eldbus_message_iter_container_close(iter, iter_array);
3948 _cache_item_reference_append_cb(Eo *bridge, Eo *data, Eldbus_Message_Iter *iter_array)
3950 if (!eo_ref_get(data) || eo_destructed_is(data))
3953 Eldbus_Message_Iter *iter_struct, *iter_sub_array;
3954 Elm_Atspi_State_Set states;
3955 Elm_Atspi_Role role;
3956 Eo *root = elm_atspi_bridge_root_get(bridge);
3958 eo_do(data, role = elm_interface_atspi_accessible_role_get());
3960 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
3961 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_struct, EINA_TRUE);
3963 /* Marshall object path */
3964 _bridge_iter_object_reference_append(bridge, iter_struct, data);
3966 /* Marshall application */
3967 _bridge_iter_object_reference_append(bridge, iter_struct, root);
3970 eo_do(data, parent = elm_interface_atspi_accessible_parent_get());
3971 /* Marshall parent */
3972 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
3973 _object_desktop_reference_append(iter_struct);
3975 _bridge_iter_object_reference_append(bridge, iter_struct, parent);
3977 /* Marshall children */
3978 Eina_List *children_list = NULL, *l;
3981 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3982 Elm_Atspi_State_Set ss;
3983 eo_do(data, ss = elm_interface_atspi_accessible_state_set_get());
3985 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
3986 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
3988 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3989 if (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
3991 eo_do(data, children_list = elm_interface_atspi_accessible_children_get());
3993 EINA_LIST_FOREACH(children_list, l, child)
3994 _bridge_iter_object_reference_append(bridge, iter_sub_array, child);
3996 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
3997 eina_list_free(children_list);
4001 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4003 /* Marshall interfaces */
4004 _iter_interfaces_append(iter_struct, data);
4007 const char *name = NULL;
4008 eo_do(data, name = elm_interface_atspi_accessible_name_get());
4012 eldbus_message_iter_basic_append(iter_struct, 's', name);
4015 eldbus_message_iter_basic_append(iter_struct, 'u', role);
4017 /* Marshall description */
4018 const char* descritpion = NULL;
4019 eo_do(data, descritpion = elm_interface_atspi_accessible_description_get());
4022 eldbus_message_iter_basic_append(iter_struct, 's', descritpion);
4024 /* Marshall state set */
4025 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "u");
4026 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
4028 eo_do(data, states = elm_interface_atspi_accessible_state_set_get());
4030 unsigned int s1 = states & 0xFFFFFFFF;
4031 unsigned int s2 = (states >> 32) & 0xFFFFFFFF;
4032 eldbus_message_iter_basic_append(iter_sub_array, 'u', s1);
4033 eldbus_message_iter_basic_append(iter_sub_array, 'u', s2);
4035 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4036 eldbus_message_iter_container_close(iter_array, iter_struct);
4041 if (iter_struct) eldbus_message_iter_del(iter_struct);
4045 static Eldbus_Message *
4046 _cache_get_items(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
4048 Eldbus_Message_Iter *iter, *iter_array;
4049 Eldbus_Message *ret;
4050 Eina_List *to_process;
4053 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4054 if (!bridge) return NULL;
4056 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4058 ret = eldbus_message_method_return_new(msg);
4059 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4061 iter = eldbus_message_iter_get(ret);
4062 iter_array = eldbus_message_iter_container_new(iter, 'a', CACHE_ITEM_SIGNATURE);
4063 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
4065 eo_do(bridge, root = elm_obj_atspi_bridge_root_get());
4066 to_process = eina_list_append(NULL, root);
4070 Eo *obj = eina_list_data_get(to_process);
4071 to_process = eina_list_remove_list(to_process, to_process);
4072 _cache_item_reference_append_cb(bridge, obj, iter_array);
4073 _bridge_object_register(bridge, obj);
4075 Eina_List *children;
4076 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
4077 to_process = eina_list_merge(to_process, children);
4080 eldbus_message_iter_container_close(iter, iter_array);
4084 if (ret) eldbus_message_unref(ret);
4088 static const Eldbus_Method cache_methods[] = {
4089 { "GetItems", NULL, ELDBUS_ARGS({CACHE_ITEM_SIGNATURE, "items"}), _cache_get_items, 0 },
4090 { NULL, NULL, NULL, NULL, 0 }
4093 static const Eldbus_Signal cache_signals[] = {
4094 [ATSPI_OBJECT_CHILD_ADDED] = { "AddAccessible", ELDBUS_ARGS({"((so)(so)a(so)assusau)", "added"}), 0},
4095 [ATSPI_OBJECT_CHILD_REMOVED] = { "RemoveAccessible", ELDBUS_ARGS({ "(so)", "removed" }), 0},
4099 static const Eldbus_Service_Interface_Desc cache_iface_desc = {
4100 ATSPI_DBUS_INTERFACE_CACHE, cache_methods, cache_signals, NULL, NULL, NULL
4103 // Component interface
4104 static Eldbus_Message *
4105 _component_contains(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4107 const char *obj_path = eldbus_message_path_get(msg);
4108 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4109 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4111 Eina_Bool contains = EINA_FALSE;
4112 AtspiCoordType coord_type;
4113 Eldbus_Message *ret;
4115 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4117 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4118 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4120 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4121 eo_do(obj, contains = elm_interface_atspi_component_contains(type, x, y));
4123 ret = eldbus_message_method_return_new(msg);
4124 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4126 eldbus_message_arguments_append(ret, "b", contains);
4131 static Eldbus_Message *
4132 _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4134 const char *obj_path = eldbus_message_path_get(msg);
4135 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4136 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4137 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4139 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4141 Eo *accessible = NULL;
4142 AtspiCoordType coord_type;
4143 Eldbus_Message *ret;
4144 Eldbus_Message_Iter *iter;
4146 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4148 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
4149 const Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
4150 if (ecore_evas_obscured_get(ee))
4151 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
4154 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4155 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4157 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4158 Evas_Object *top = elm_object_top_widget_get(obj);
4161 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
4167 ret = eldbus_message_method_return_new(msg);
4168 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4170 iter = eldbus_message_iter_get(ret);
4171 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4172 eo_do(obj, accessible = elm_interface_atspi_component_accessible_at_point_get(type, x, y));
4173 _bridge_iter_object_reference_append(bridge, iter, accessible);
4174 _bridge_object_register(bridge, accessible);
4179 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
4181 NEIGHBOR_SEARCH_MODE_NORMAL = 0,
4182 NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT = 1,
4183 NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING = 2,
4184 NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE = 3,
4185 } GetNeighborSearchMode;
4187 typedef struct accessibility_navigation_pointer_table {
4188 AtspiRole (*object_get_role)(struct accessibility_navigation_pointer_table *t, void *ptr);
4189 uint64_t (*object_get_state_set)(struct accessibility_navigation_pointer_table *t, void *ptr);
4190 void *(*get_object_in_relation_by_type)(struct accessibility_navigation_pointer_table *t, void *ptr, AtspiRelationType type);
4191 unsigned char (*object_is_zero_size)(struct accessibility_navigation_pointer_table *t, void *ptr);
4192 void *(*get_parent)(struct accessibility_navigation_pointer_table *t, void *ptr);
4193 unsigned char (*object_is_scrollable)(struct accessibility_navigation_pointer_table *t, void *ptr);
4194 void *(*get_object_at_point)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4195 unsigned char (*object_contains)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4196 unsigned char (*object_is_proxy)(struct accessibility_navigation_pointer_table *t, void *ptr);
4197 } accessibility_navigation_pointer_table;
4199 #define CALL(fncname, ...) table->fncname(table, __VA_ARGS__)
4200 static unsigned char _accept_object_check_role(accessibility_navigation_pointer_table *table EINA_UNUSED, void *obj)
4202 return _elm_widget_atspi_role_acceptable_check(obj);
4205 static unsigned char _state_set_is_set(uint64_t state_set, AtspiStateType state)
4207 return (state_set & ((uint64_t)1 << (unsigned int)state)) != 0;
4210 static unsigned char _object_is_defunct(accessibility_navigation_pointer_table *table, void *ptr)
4212 uint64_t states = CALL(object_get_state_set, ptr);
4213 return _state_set_is_set(states, ATSPI_STATE_DEFUNCT);
4216 static unsigned char _object_role_is_acceptable_when_navigating_next_prev(accessibility_navigation_pointer_table *table, void *obj)
4218 AtspiRole role = CALL(object_get_role, obj);
4219 return role != ATSPI_ROLE_POPUP_MENU && role != ATSPI_ROLE_DIALOG;
4222 static void *_get_object_in_relation_flow(accessibility_navigation_pointer_table *table, void *source, unsigned char forward)
4224 return CALL(get_object_in_relation_by_type, source, forward ? ATSPI_RELATION_FLOWS_TO : ATSPI_RELATION_FLOWS_FROM);
4227 static unsigned char _object_is_item(accessibility_navigation_pointer_table *table, void *obj)
4229 AtspiRole role = CALL(object_get_role, obj);
4230 return role == ATSPI_ROLE_LIST_ITEM || role == ATSPI_ROLE_MENU_ITEM;
4233 static unsigned char _object_is_highlightable(accessibility_navigation_pointer_table *table, void *obj)
4235 uint64_t state_set = CALL(object_get_state_set, obj);
4236 return _state_set_is_set(state_set, ATSPI_STATE_HIGHLIGHTABLE);
4239 static unsigned char _object_is_visible(accessibility_navigation_pointer_table *table, void *obj)
4241 uint64_t state_set = CALL(object_get_state_set, obj);
4242 return _state_set_is_set(state_set, ATSPI_STATE_VISIBLE);
4245 static unsigned char _object_is_showing(accessibility_navigation_pointer_table *table, void *obj)
4247 uint64_t state_set = CALL(object_get_state_set, obj);
4248 return _state_set_is_set(state_set, ATSPI_STATE_SHOWING);
4251 static unsigned char _object_is_collapsed(accessibility_navigation_pointer_table *table, void *obj)
4253 uint64_t state_set = CALL(object_get_state_set, obj);
4255 _state_set_is_set(state_set, ATSPI_STATE_EXPANDABLE) &&
4256 !_state_set_is_set(state_set, ATSPI_STATE_EXPANDED);
4259 static unsigned char _object_has_modal_state(accessibility_navigation_pointer_table *table, void *obj)
4261 uint64_t state_set = CALL(object_get_state_set, obj);
4262 return _state_set_is_set(state_set, ATSPI_STATE_MODAL);
4265 static unsigned char _object_is_zero_size(accessibility_navigation_pointer_table *table, void *obj)
4267 return CALL(object_is_zero_size, obj);
4270 static void *_get_scrollable_parent(accessibility_navigation_pointer_table *table, void *obj)
4274 obj = CALL(get_parent, obj);
4275 if (obj && CALL(object_is_scrollable, obj)) return obj;
4279 static unsigned char _accept_object(accessibility_navigation_pointer_table *table, void *obj)
4282 if (!_object_is_visible(table, obj)) return 0;
4283 if (!_accept_object_check_role(table, obj)) return 0;
4284 if (CALL(get_object_in_relation_by_type, obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0;
4285 if (!_object_is_highlightable(table, obj)) return 0;
4287 if (_get_scrollable_parent(table, obj) != NULL)
4289 void *parent = CALL(get_parent, obj);
4293 return !_object_is_item(table, obj) || !_object_is_collapsed(table, parent);
4298 if (_object_is_zero_size(table, obj)) return 0;
4299 if (!_object_is_showing(table, obj)) return 0;
4304 /* The target cannot be a parent of root */
4305 static Eina_Bool _target_validation_check(Eo *target, Eo *root)
4308 eo_do(root, parent = elm_interface_atspi_accessible_parent_get());
4312 if (parent == target) return EINA_FALSE;
4313 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4319 static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigation_pointer_table *table,
4320 void *root, int x, int y, unsigned char coordinates_are_screen_based)
4322 if (!root) return NULL;
4323 void *prev_root = root;
4325 void *return_value = NULL;
4328 void *target = CALL(get_object_at_point, root, x, y, coordinates_are_screen_based);
4330 if (target == root || target == prev_root) break;
4331 if (!_target_validation_check(target, root)) break;
4333 // always return proxy, so atspi lib can call on it again
4334 if (CALL(object_is_proxy, target)) return target;
4337 void *relation_obj = CALL(get_object_in_relation_by_type, root, ATSPI_RELATION_CONTROLLED_BY);
4338 unsigned char contains = 0;
4341 contains = CALL(object_contains, relation_obj, x, y, coordinates_are_screen_based);
4342 if (contains) root = relation_obj;
4345 if (_accept_object(table, root))
4347 return_value = root;
4348 if (contains) break;
4352 if (return_value && _object_has_modal_state(table, return_value)) return_value = NULL;
4353 return return_value;
4356 static void *_find_non_defunct_child(accessibility_navigation_pointer_table *table,
4357 Eina_List *children, unsigned int current_index, unsigned char forward)
4359 unsigned int children_count = eina_list_count(children);
4360 for(; current_index < children_count; forward ? ++current_index : --current_index)
4362 void *n = eina_list_nth(children, current_index);
4363 if (n && !_object_is_defunct(table, n)) return n;
4368 static void *_directional_depth_first_search_try_non_defunct_child(accessibility_navigation_pointer_table *table,
4369 void *node, Eina_List *children, unsigned char forward)
4371 unsigned int children_count = eina_list_count(children);
4372 if (children_count > 0)
4374 unsigned char is_showing = _get_scrollable_parent(table, node) == NULL ? _object_is_showing(table, node) : 1;
4377 return _find_non_defunct_child(table, children, forward ? 0 : children_count - 1, forward);
4383 static Eina_List *_scrollable_parent_list_get(Eo *obj)
4385 Eina_List *ret = NULL;
4390 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
4393 if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4395 ret = eina_list_append(ret, parent);
4397 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4404 static void _viewport_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
4406 eo_do(obj, elm_interface_scrollable_content_viewport_geometry_get(x, y, w, h));
4407 /* widget implements scrollable interface but does not use scoller
4408 in this case, use widget geometry */
4409 if (*w == 0 || *h == 0)
4411 INF("%s is zero sized content viewport", eo_class_name_get(eo_class_get(obj)));
4412 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_FALSE, x, y, w, h));
4417 _new_scrollable_parent_viewport_geometry_get(Eo *node, Eo *start,
4418 int *x, int *y, int *w, int *h)
4420 Eina_Bool ret = EINA_FALSE;
4424 n_spl = _scrollable_parent_list_get(node);
4425 s_spl = _scrollable_parent_list_get(start);
4429 EINA_LIST_FOREACH(s_spl, l, sp)
4431 n_spl = eina_list_remove(n_spl, sp);
4434 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4436 unsigned int count = eina_list_count(n_spl);
4439 sp = eina_list_nth(n_spl, count - 1);
4440 _viewport_geometry_get(sp, &sx, &sy, &sw, &sh);
4452 static Eina_List *_valid_children_get(Eina_List *children, Eo *start, Eo *root)
4454 /* condition to find first(last) object regardless of scrollable parent.
4455 looping navigation does not care scrollable parent.
4456 1. currently highlighted object exists
4457 2. both start and root are same */
4458 Eo *current = _elm_object_accessibility_currently_highlighted_get();
4459 if (current && start == root) return children;
4462 child = eina_list_nth(children, 0);
4466 Evas_Coord x = 0, y = 0, w = 0, h = 0;
4467 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4469 if (_new_scrollable_parent_viewport_geometry_get(child, start,
4470 &sx, &sy, &sw, &sh))
4472 Eina_List *l, *l_next;
4473 EINA_LIST_FOREACH_SAFE(children, l, l_next, child)
4476 elm_interface_atspi_component_extents_get(EINA_FALSE,
4478 if (w == 0 || h == 0 ||
4479 !ELM_RECTS_INTERSECT(x, y, w, h, sx, sy, sw, sh))
4480 children = eina_list_remove_list(children, l);
4487 static void *_get_next_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4488 void *obj, void *start, void *root, unsigned char forward)
4490 if (!obj) return NULL;
4491 void *parent = CALL(get_parent, obj);
4492 if (!parent) return NULL;
4494 Eina_List *children;
4495 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
4496 children = _valid_children_get(children, start, root);
4498 unsigned int children_count = eina_list_count(children);
4499 if (children_count == 0)
4501 eina_list_free(children);
4504 unsigned int current = 0;
4505 for(; current < children_count && eina_list_nth(children, current) != obj; ++current) ;
4506 if (current >= children_count)
4508 eina_list_free(children);
4511 forward ? ++current : --current;
4512 void *ret = _find_non_defunct_child(table, children, current, forward);
4513 eina_list_free(children);
4518 _directional_depth_first_search_try_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4519 unsigned char *all_children_visited_ptr,
4520 void *node, void *start, void *root,
4521 unsigned char forward)
4525 void *sibling = _get_next_non_defunct_sibling(table, node, start, root, forward);
4526 if (sibling != NULL)
4529 *all_children_visited_ptr = 0;
4534 node = CALL(get_parent, node);
4535 if (node == NULL || node == root) return NULL;
4537 // in backward traversing stop the walk up on parent
4538 if (!forward) break;
4545 unsigned int current_search_size;
4546 unsigned int counter;
4547 } cycle_detection_data;
4549 void cycle_detection_initialize(cycle_detection_data *data, const void *key)
4553 data->current_search_size = 1;
4557 unsigned char cycle_detection_check_if_in_cycle(cycle_detection_data *data, const void *key)
4559 if (!data) return 1;
4560 if (data->key == key) return 1;
4561 if (--data->counter == 0)
4563 data->current_search_size <<= 1;
4564 if (data->current_search_size == 0) return 1;
4565 data->counter = data->current_search_size;
4574 if (eo_isa(obj, ELM_ACCESS_CLASS))
4576 Elm_Access_Info *info;
4578 info = _elm_access_info_get(obj);
4579 if (info && eo_isa(info->part_object, ELM_LAYOUT_CLASS))
4581 Eina_List *attrs, *l;
4582 Elm_Atspi_Attribute *attr;
4584 eo_do(info->part_object,
4585 attrs = elm_interface_atspi_accessible_attributes_get());
4586 EINA_LIST_FOREACH(attrs, l, attr)
4588 if (!strcmp(attr->key, "___PlugID"))
4590 elm_atspi_attributes_list_free(attrs);
4594 elm_atspi_attributes_list_free(attrs);
4601 _proxy_in_parent_get(Eo *obj)
4605 Eina_List *children_list = NULL;
4606 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4609 EINA_LIST_FOREACH(children_list, l, child)
4611 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4617 eina_list_free(children_list);
4623 _deputy_of_proxy_in_parent_get(Eo *obj)
4627 Eina_List *children_list = NULL;
4628 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4630 unsigned int index = 0;
4632 EINA_LIST_FOREACH(children_list, l, child)
4634 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4638 WRN("Proxy does not have deputy object");
4642 deputy = eina_list_nth(children_list, index - 1);
4647 eina_list_free(children_list);
4652 static void *_calculate_neighbor_impl(accessibility_navigation_pointer_table *table, void *root, void *start, unsigned char forward, GetNeighborSearchMode search_mode)
4654 if (root && _object_is_defunct(table, root)) return NULL;
4655 if (start && _object_is_defunct(table, start))
4661 if (search_mode == NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE)
4663 /* This only works if we navigate backward, and it is not possible to
4664 find in embedded process. In this case the deputy should be used */
4665 return _deputy_of_proxy_in_parent_get(start);
4668 void *node = start ? start : root;
4669 if (!node) return NULL;
4671 // initialization of all-children-visited flag for start node - we assume
4672 // that when we begin at start node and we navigate backward, then all children
4673 // are visited, so navigation will ignore start's children and go to
4674 // previous sibling available.
4675 /* Regarding condtion (start != root):
4676 The last object can be found only if all_children_visited is false.
4677 The start is same with root, when looking for the last object. */
4678 unsigned char all_children_visited = (start != root) && (search_mode != NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT && !forward);
4680 // true, if starting element should be ignored. this is only used in rare case of
4681 // recursive search failing to find an object.
4682 // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
4683 // element A algorithm has to descend into BUS_B and search element B and its children. this is done
4684 // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
4685 // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
4686 // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
4687 // this flag means, that object A was already checked previously and we should skip it and its children.
4688 unsigned char force_next = (search_mode == NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING);
4690 cycle_detection_data cycle_detection;
4691 cycle_detection_initialize(&cycle_detection, node);
4694 if (_object_is_defunct(table, node)) return NULL;
4696 // always accept proxy object from different world
4697 if (!force_next && CALL(object_is_proxy, node)) return node;
4699 Eina_List *children;
4700 eo_do(node, children = elm_interface_atspi_accessible_children_get());
4701 children = _valid_children_get(children, start, root);
4704 // 1. not start node
4705 // 2. parent after all children in backward traversing
4706 // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
4707 // Objects with those roles shouldnt be reachable, when navigating next / prev.
4708 unsigned char all_children_visited_or_moving_forward = (eina_list_count(children) == 0 || forward || all_children_visited);
4709 if (!force_next && node != start && all_children_visited_or_moving_forward && _accept_object(table, node))
4711 if (start == NULL || _object_role_is_acceptable_when_navigating_next_prev(table, node))
4713 eina_list_free(children);
4718 void *next_related_in_direction = !force_next ? _get_object_in_relation_flow(table, node, forward) : NULL;
4720 /* force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
4721 in this case the node is elm_layout which is parent of proxy object.
4722 There is an access object working for the proxy object, and the access
4723 object could have relation information. This relation information should
4724 be checked first before using the elm_layout as a node. */
4725 if (force_next && forward)
4728 deputy = _deputy_of_proxy_in_parent_get(node);
4729 next_related_in_direction =
4730 _get_object_in_relation_flow(table, deputy, forward);
4733 if (next_related_in_direction && _object_is_defunct(table, next_related_in_direction))
4734 next_related_in_direction = NULL;
4735 unsigned char want_cycle_detection = 0;
4736 if (next_related_in_direction)
4738 /* Check next_related_in_direction is deputy object */
4742 /* If the prev object is deputy, then go to inside of its proxy first */
4743 if (_deputy_is(next_related_in_direction))
4745 parent = elm_widget_parent_get(next_related_in_direction);
4746 next_related_in_direction =
4747 _proxy_in_parent_get(parent);
4752 /* If current object is deputy, and it has relation next object,
4753 then do not use the relation next object, and use proxy first */
4754 if (_deputy_is(node))
4756 parent = elm_widget_parent_get(node);
4757 next_related_in_direction =
4758 _proxy_in_parent_get(parent);
4762 node = next_related_in_direction;
4763 want_cycle_detection = 1;
4766 void *child = !force_next && !all_children_visited ?
4767 _directional_depth_first_search_try_non_defunct_child(table, node, children, forward) : NULL;
4768 if (child != NULL) want_cycle_detection = 1;
4771 if (!force_next && node == root)
4773 eina_list_free(children);
4776 all_children_visited = 1;
4777 child = _directional_depth_first_search_try_non_defunct_sibling(table, &all_children_visited, node, start, root, forward);
4783 if (want_cycle_detection && cycle_detection_check_if_in_cycle(&cycle_detection, node))
4785 eina_list_free(children);
4788 eina_list_free(children);
4793 typedef struct accessibility_navigation_pointer_table_impl {
4794 accessibility_navigation_pointer_table ptrs;
4796 } accessibility_navigation_pointer_table_impl;
4798 static AtspiRole _object_get_role_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4800 Elm_Atspi_Role role;
4802 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
4803 return _elm_role_to_atspi_role(role);
4806 static uint64_t _object_get_state_set_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4808 Elm_Atspi_State_Set states;
4810 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
4811 return _elm_atspi_state_set_to_atspi_state_set(states);
4814 static void *_get_object_in_relation_by_type_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr, AtspiRelationType type)
4818 const Eo *source = ptr;
4819 Elm_Atspi_Relation_Set relations;
4820 Elm_Atspi_Relation_Type expected_relation_type = _atspi_relation_to_elm_relation(type);
4821 eo_do(source, relations = elm_interface_atspi_accessible_relation_set_get());
4822 Elm_Atspi_Relation *rel;
4824 EINA_LIST_FOREACH(relations, l, rel)
4826 if (rel->type == expected_relation_type)
4828 Eina_List *last = eina_list_last(rel->objects);
4829 return eina_list_data_get(last);
4836 static unsigned char _object_is_zero_size_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4840 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_TRUE, &x, &y, &w, &h));
4841 return w == 0 || h == 0;
4844 unsigned char _object_is_scrollable_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4847 return eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
4850 void *_get_parent_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4852 Eo *obj = (Eo*)ptr, *ret_obj;
4853 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
4857 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)
4859 Eo *obj = (Eo*)ptr, *target;
4860 eo_do(obj, target = elm_interface_atspi_component_accessible_at_point_get(coordinates_are_screen_based, x, y));
4864 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)
4867 Eina_Bool return_value;
4868 eo_do(obj, return_value = elm_interface_atspi_component_contains(coordinates_are_screen_based, x, y));
4869 return return_value ? 1 : 0;
4872 unsigned char _object_is_proxy_impl(struct accessibility_navigation_pointer_table *table_, void *obj)
4874 accessibility_navigation_pointer_table_impl *table = (accessibility_navigation_pointer_table_impl*)table_;
4875 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(table->bridge, pd, 0);
4876 const char *our_bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
4877 const char *obj_bus_name;
4878 _object_get_bus_name_and_path(table->bridge, (Eo*)obj, &obj_bus_name, NULL);
4879 return our_bus_name && obj_bus_name && strcmp(our_bus_name, obj_bus_name) != 0;
4882 accessibility_navigation_pointer_table_impl construct_accessibility_navigation_pointer_table(Eo *bridge)
4884 accessibility_navigation_pointer_table_impl table;
4885 #define INIT(n) table.ptrs.n = _## n ## _impl
4886 INIT(object_get_role);
4887 INIT(object_get_state_set);
4888 INIT(get_object_in_relation_by_type);
4889 INIT(object_is_zero_size);
4891 INIT(object_is_scrollable);
4892 INIT(get_object_at_point);
4893 INIT(object_contains);
4894 INIT(object_is_proxy);
4896 table.bridge = bridge;
4901 static Eo *_calculate_navigable_accessible_at_point(Eo *bridge, Eo *root, Eina_Bool coord_type, int x, int y)
4903 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4904 Eo *result = (Eo*)_calculate_navigable_accessible_at_point_impl(&table.ptrs, root, x, y, coord_type ? 1 : 0);
4908 static Eo *_calculate_neighbor(Eo *bridge, Eo *root, Eo *start, Eina_Bool forward, int search_mode)
4910 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4911 Eo *result = (Eo*)_calculate_neighbor_impl(&table.ptrs, root, start, forward ? 1 : 0, (GetNeighborSearchMode)search_mode);
4917 static Eldbus_Message *
4918 _component_get_extents(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4920 const char *obj_path = eldbus_message_path_get(msg);
4921 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4922 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4924 AtspiCoordType coord_type;
4925 Eldbus_Message *ret;
4926 Eldbus_Message_Iter *iter, *iter_struct;
4928 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4930 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4931 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4933 ret = eldbus_message_method_return_new(msg);
4934 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4936 iter = eldbus_message_iter_get(ret);
4938 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4939 eo_do(obj, elm_interface_atspi_component_extents_get(type, &x, &y, &w, &h));
4940 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
4941 EINA_SAFETY_ON_NULL_GOTO(iter_struct, fail);
4943 eldbus_message_iter_basic_append(iter_struct, 'i', x);
4944 eldbus_message_iter_basic_append(iter_struct, 'i', y);
4945 eldbus_message_iter_basic_append(iter_struct, 'i', w);
4946 eldbus_message_iter_basic_append(iter_struct, 'i', h);
4948 eldbus_message_iter_container_close(iter, iter_struct);
4952 if (ret) eldbus_message_unref(ret);
4956 static Eldbus_Message *
4957 _component_get_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4959 const char *obj_path = eldbus_message_path_get(msg);
4960 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4961 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4963 AtspiCoordType coord_type;
4964 Eldbus_Message *ret;
4966 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4968 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4969 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4971 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4972 eo_do(obj, elm_interface_atspi_component_position_get(type, &x, &y));
4974 ret = eldbus_message_method_return_new(msg);
4975 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4977 eldbus_message_arguments_append(ret, "i", x);
4978 eldbus_message_arguments_append(ret, "i", y);
4983 static Eldbus_Message *
4984 _component_get_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4986 const char *obj_path = eldbus_message_path_get(msg);
4987 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4988 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4990 Eldbus_Message *ret;
4992 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4994 eo_do(obj, elm_interface_atspi_component_size_get(&x, &y));
4996 ret = eldbus_message_method_return_new(msg);
4997 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4999 eldbus_message_arguments_append(ret, "i", x);
5000 eldbus_message_arguments_append(ret, "i", y);
5005 static AtspiComponentLayer
5006 _elm_layer_2_atspi_layer(int layer)
5008 if (layer <= ELM_OBJECT_LAYER_BACKGROUND) return ATSPI_LAYER_CANVAS;
5009 if (layer < ELM_OBJECT_LAYER_FOCUS) return ATSPI_LAYER_WIDGET;
5010 if (layer <= ELM_OBJECT_LAYER_TOOLTIP) return ATSPI_LAYER_POPUP;
5012 return ATSPI_LAYER_OVERLAY;
5015 static Eldbus_Message *
5016 _component_get_layer(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5018 const char *obj_path = eldbus_message_path_get(msg);
5019 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5020 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5022 Eldbus_Message *ret;
5023 AtspiComponentLayer atspi_layer;
5025 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5027 eo_do(obj, layer = elm_interface_atspi_component_layer_get());
5029 ret = eldbus_message_method_return_new(msg);
5030 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5032 atspi_layer = _elm_layer_2_atspi_layer(layer);
5033 eldbus_message_arguments_append(ret, "u", atspi_layer);
5038 static Eldbus_Message *
5039 _component_grab_focus(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5041 const char *obj_path = eldbus_message_path_get(msg);
5042 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5043 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5044 Eldbus_Message *ret;
5045 Eina_Bool focus = EINA_FALSE;
5048 return _dbus_invalid_ref_error_new(msg);
5050 eo_do(obj, focus = elm_interface_atspi_component_focus_grab());
5052 ret = eldbus_message_method_return_new(msg);
5053 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5055 eldbus_message_arguments_append(ret, "b", focus);
5060 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5061 static Eldbus_Message *
5062 _component_grab_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5064 const char *obj_path = eldbus_message_path_get(msg);
5065 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5066 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5067 Eldbus_Message *ret;
5068 Eina_Bool highlight = EINA_FALSE;
5070 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5072 eo_do(obj, highlight = elm_interface_atspi_component_highlight_grab());
5074 ret = eldbus_message_method_return_new(msg);
5075 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5077 eldbus_message_arguments_append(ret, "b", highlight);
5082 static Eldbus_Message *
5083 _component_clear_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5085 const char *obj_path = eldbus_message_path_get(msg);
5086 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5087 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5088 Eldbus_Message *ret;
5089 Eina_Bool highlight = EINA_FALSE;
5091 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5093 eo_do(obj, highlight = elm_interface_atspi_component_highlight_clear());
5095 ret = eldbus_message_method_return_new(msg);
5096 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5098 eldbus_message_arguments_append(ret, "b", highlight);
5104 static Eldbus_Message *
5105 _component_get_alpha(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5107 const char *obj_path = eldbus_message_path_get(msg);
5108 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5109 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5110 Eldbus_Message *ret;
5114 return _dbus_invalid_ref_error_new(msg);
5116 eo_do(obj, alpha = elm_interface_atspi_component_alpha_get());
5118 ret = eldbus_message_method_return_new(msg);
5119 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5121 eldbus_message_arguments_append(ret, "d", alpha);
5126 static Eldbus_Message *
5127 _component_set_extends(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5129 const char *obj_path = eldbus_message_path_get(msg);
5130 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5131 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5133 AtspiCoordType coord_type;
5134 Eldbus_Message *ret;
5135 Eina_Bool result = EINA_FALSE;
5137 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5139 if (!eldbus_message_arguments_get(msg, "iiiiu", &x, &y, &w, &h, &coord_type))
5140 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5142 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5143 eo_do(obj, result = elm_interface_atspi_component_extents_set(type, x, y, w, h));
5145 ret = eldbus_message_method_return_new(msg);
5146 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5148 eldbus_message_arguments_append(ret, "b", result);
5153 static Eldbus_Message *
5154 _component_set_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5156 const char *obj_path = eldbus_message_path_get(msg);
5157 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5158 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5160 Eina_Bool result = EINA_FALSE;
5161 AtspiCoordType coord_type;
5162 Eldbus_Message *ret;
5164 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5166 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
5167 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5169 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5170 eo_do(obj, result = elm_interface_atspi_component_position_set(type, x, y));
5172 ret = eldbus_message_method_return_new(msg);
5173 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5175 eldbus_message_arguments_append(ret, "b", result);
5180 static Eldbus_Message *
5181 _component_set_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5183 const char *obj_path = eldbus_message_path_get(msg);
5184 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5185 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5188 Eldbus_Message *ret;
5190 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5192 if (!eldbus_message_arguments_get(msg, "ii", &w, &h))
5193 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5195 eo_do(obj, result = elm_interface_atspi_component_size_set(w, h));
5197 ret = eldbus_message_method_return_new(msg);
5198 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5200 eldbus_message_arguments_append(ret, "b", result);
5205 static const Eldbus_Method component_methods[] = {
5206 { "Contains", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "contains"}), _component_contains, 0 },
5207 { "GetAccessibleAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)", "accessible"}), _component_get_accessible_at_point, 0 },
5208 { "GetExtents", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"(iiii)", "extents"}), _component_get_extents, 0 },
5209 { "GetPosition", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"i", "x"}, {"i","y"}), _component_get_position, 0 },
5210 { "GetSize", NULL, ELDBUS_ARGS({"i", "w"}, {"i", "h"}), _component_get_size, 0 },
5211 { "GetLayer", NULL, ELDBUS_ARGS({"u", "layer"}), _component_get_layer, 0 },
5212 // { "GetMDIZOrder", NULL, ELDBUS_ARGS({"n", "MDIZOrder"}), _component_get_mdizorder, 0 },
5213 { "GrabFocus", NULL, ELDBUS_ARGS({"b", "focus"}), _component_grab_focus, 0 },
5214 { "GetAlpha", NULL, ELDBUS_ARGS({"d", "alpha"}), _component_get_alpha, 0 },
5215 { "SetExtents", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "width"}, {"i", "height"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_extends, 0 },
5216 { "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
5217 { "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
5219 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5220 { "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
5221 { "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
5223 { NULL, NULL, NULL, NULL, 0 }
5226 static const Eldbus_Service_Interface_Desc component_iface_desc = {
5227 ATSPI_DBUS_INTERFACE_COMPONENT, component_methods, NULL, NULL, NULL, NULL
5231 _on_elm_atspi_bridge_app_register(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
5233 const char *errname, *errmsg;
5235 if (eldbus_message_error_get(msg, &errname, &errmsg))
5237 ERR("%s %s", errname, errmsg);
5240 DBG("Application successfuly registered at ATSPI2 bus.");
5244 _elm_atspi_bridge_app_register(Eo *bridge)
5246 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5248 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5249 ATSPI_DBUS_PATH_ROOT,
5250 ATSPI_DBUS_INTERFACE_SOCKET,
5252 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5254 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
5255 eldbus_connection_send(pd->a11y_bus, message, _on_elm_atspi_bridge_app_register, NULL, -1);
5261 _elm_atspi_bridge_app_unregister(Eo *bridge)
5264 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5266 root = elm_atspi_bridge_root_get(bridge);
5268 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5269 ATSPI_DBUS_PATH_ROOT,
5270 ATSPI_DBUS_INTERFACE_SOCKET,
5272 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5274 _bridge_iter_object_reference_append(bridge, iter, root);
5275 eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1);
5281 _cache_register(Eo *obj)
5283 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
5284 pd->cache_interface = eldbus_service_interface_register(pd->a11y_bus, CACHE_INTERFACE_PATH, &cache_iface_desc);
5285 eldbus_service_object_data_set(pd->cache_interface, ELM_ATSPI_BRIDGE_CLASS_NAME, obj);
5289 _set_broadcast_flag(const char *event, Eo *bridge)
5292 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5294 tokens = eina_str_split(event, ":", 3);
5296 if (!tokens) return;
5298 if (!strcmp(tokens[0], "Object"))
5300 if (!tokens[1] || *tokens[1] == '\0') return; // do not handle "Object:*"
5301 else if (!strcmp(tokens[1], "StateChanged"))
5303 if (!tokens[2] || *tokens[2] == '\0')
5304 pd->object_state_broadcast_mask = -1; // broadcast all
5305 eina_str_tolower(&tokens[2]);
5306 struct atspi_state_desc *sd = eina_hash_find(pd->state_hash, tokens[2]);
5308 STATE_TYPE_SET(pd->object_state_broadcast_mask, sd->elm_state);
5310 else if (!strcmp(tokens[1], "PropertyChange"))
5312 if (!tokens[2] || *tokens[2] == '\0')
5313 pd->object_property_broadcast_mask = -1; //broadcast all
5314 else if (!strcmp(tokens[2], "AccessibleValue"))
5315 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_VALUE);
5316 else if (!strcmp(tokens[2], "AccessibleName"))
5317 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_NAME);
5318 else if (!strcmp(tokens[2], "AccessibleDescription"))
5319 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_DESCRIPTION);
5320 else if (!strcmp(tokens[2], "AccessibleParent"))
5321 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_PARENT);
5322 else if (!strcmp(tokens[2], "AccessibleRole"))
5323 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_ROLE);
5325 else if (!strcmp(tokens[1], "ChildrenChanged"))
5327 if (!tokens[2] || *tokens[2] == '\0')
5328 pd->object_children_broadcast_mask = -1; // broadcast all
5329 else if (!strcmp(tokens[2], "add"))
5330 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_ADDED);
5331 else if (!strcmp(tokens[2], "remove"))
5332 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_REMOVED);
5334 else if (!strcmp(tokens[1], "TextChanged"))
5335 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED);
5336 else if (!strcmp(tokens[1], "TextCaretMoved"))
5337 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED);
5338 else if (!strcmp(tokens[1], "TextBoundsChanged"))
5339 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED);
5340 else if (!strcmp(tokens[1], "TextSelectionChanged"))
5341 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED);
5342 else if (!strcmp(tokens[1], "TextAttributesChanged"))
5343 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED);
5344 else if (!strcmp(tokens[1], "VisibleDataChanged"))
5345 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED);
5346 else if (!strcmp(tokens[1], "ActiveDescendantChanged"))
5347 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED);
5348 else if (!strcmp(tokens[1], "BoundsChanged"))
5349 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_BOUNDS_CHANGED);
5350 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5351 else if (!strcmp(tokens[1], "MoveOuted"))
5352 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED);
5355 else if (!strcmp(tokens[0], "Window"))
5357 if (!tokens[1] || *tokens[1] == '\0')
5358 pd->window_signal_broadcast_mask = -1; // broadcast all
5359 else if (!strcmp(tokens[1], "Create"))
5360 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_CREATE);
5361 else if (!strcmp(tokens[1], "Destroy"))
5362 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DESTROY);
5363 else if (!strcmp(tokens[1], "Activate"))
5364 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_ACTIVATE);
5365 else if (!strcmp(tokens[1], "Deactivate"))
5366 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DEACTIVATE);
5367 else if (!strcmp(tokens[1], "Maximize"))
5368 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MAXIMIZE);
5369 else if (!strcmp(tokens[1], "Minimize"))
5370 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MINIMIZE);
5371 else if (!strcmp(tokens[1], "Resize"))
5372 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESIZE);
5373 else if (!strcmp(tokens[1], "Restore"))
5374 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESTORE);
5382 _registered_listeners_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
5384 const char *event, *bus;
5386 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
5387 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
5389 DBG("Updating registered ATSPI signals list.");
5390 pd->object_broadcast_mask = 0;
5391 pd->object_children_broadcast_mask = 0;
5392 pd->object_property_broadcast_mask = 0;
5393 pd->object_state_broadcast_mask = 0;
5394 pd->window_signal_broadcast_mask = 0;
5396 if (eldbus_message_error_get(msg, &event, &bus))
5398 WRN("%s %s", event, bus);
5401 Eldbus_Message_Iter *iter, *siter;
5402 if (!eldbus_message_arguments_get(msg, "a(ss)", &iter))
5404 ERR("Invalid answer type from GetRegisteredEvents method call!");
5407 while (eldbus_message_iter_get_and_next(iter, 'r', &siter))
5409 eldbus_message_iter_arguments_get(siter, "ss", &bus, &event);
5410 _set_broadcast_flag(event, data);
5415 //TIZEN_ONLY(20170910) atspi: emit signal after atspi bridge is connected
5416 pd->connected = EINA_TRUE;
5417 eo_do(data, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_CONNECTED, NULL));
5418 _elm_win_atspi(EINA_TRUE);
5422 eo_do(data, root = elm_obj_atspi_bridge_root_get());
5423 _bridge_cache_build(data, root);
5425 // initialize pending proxy
5426 EINA_LIST_FREE(pd->socket_queue, pr)
5427 _socket_ifc_create(pd->a11y_bus, pr);
5428 EINA_LIST_FREE(pd->plug_queue, pr)
5429 _plug_connect(pd->a11y_bus, pr);
5431 pd->socket_queue = pd->plug_queue = NULL;
5436 _registered_events_list_update(Eo *bridge)
5438 Eldbus_Message *msg;
5439 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5442 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "GetRegisteredEvents");
5443 p = eldbus_connection_send(pd->a11y_bus, msg, _registered_listeners_get, bridge, -1);
5444 pd->pending_requests = eina_list_append(pd->pending_requests, p);
5448 _handle_listener_change(void *data, const Eldbus_Message *msg EINA_UNUSED)
5450 _registered_events_list_update(data);
5453 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5455 _scroll_gesture_required_is(Eo *obj)
5457 Eina_Bool ret = EINA_FALSE;
5458 Eina_List *l, *attr_list = NULL;
5459 Elm_Atspi_Attribute *attr = NULL;
5461 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5462 EINA_LIST_FOREACH(attr_list, l, attr)
5464 if (!strcmp(attr->key, "gesture_required") && !strcmp(attr->value, "scroll"))
5471 elm_atspi_attributes_list_free(attr_list);
5478 _state_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5480 Elm_Atspi_Event_State_Changed_Data *state_data = event_info;
5481 const char *type_desc;
5482 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5484 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
5485 if ((state_data->type == ELM_ATSPI_STATE_ACTIVE) && eo_isa(obj, ELM_WIN_CLASS))
5487 pd->window_activated = state_data->new_value;
5490 // TIZEN_ONLY(20161209): reduce IPC of object:state-changed:showing
5491 if ((state_data->type == ELM_ATSPI_STATE_SHOWING) ||
5492 (state_data->type == ELM_ATSPI_STATE_VISIBLE))
5494 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5495 Elm_Atspi_State_Set ss;
5497 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5498 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
5499 if (state_data->new_value) /* Showing */
5501 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5502 (role != ELM_ATSPI_ROLE_PAGE_TAB) &&
5503 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)))
5506 else /* Not Showing */
5508 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5509 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)) &&
5510 (_elm_object_accessibility_currently_highlighted_get() != (void *)obj))
5516 if (!STATE_TYPE_GET(pd->object_state_broadcast_mask, state_data->type))
5519 if ((state_data->type > ELM_ATSPI_STATE_LAST_DEFINED) ||
5520 (int)state_data->type < 0)
5523 type_desc = elm_states_to_atspi_state[state_data->type].name;
5525 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5526 unsigned int det2 = 0;
5527 if ((state_data->type == ELM_ATSPI_STATE_HIGHLIGHTED) &&
5528 (_scroll_gesture_required_is(obj)))
5531 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5532 &_event_obj_signals[ATSPI_OBJECT_EVENT_STATE_CHANGED], type_desc, state_data->new_value, det2, NULL);
5538 _bounds_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5540 Elm_Atspi_Event_Geometry_Changed_Data *geo_data = event_info;
5542 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5543 &_event_obj_signals[ATSPI_OBJECT_EVENT_BOUNDS_CHANGED], "", 0, 0, "(iiii)",
5544 geo_data->x, geo_data->y, geo_data->width, geo_data->height);
5549 _property_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5551 const char *property = event_info;
5553 enum _Atspi_Object_Property prop = ATSPI_OBJECT_PROPERTY_LAST;
5555 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5557 if (!strcmp(property, "parent"))
5559 prop = ATSPI_OBJECT_PROPERTY_PARENT;
5560 atspi_desc = "accessible-parent";
5562 else if (!strcmp(property, "name"))
5564 prop = ATSPI_OBJECT_PROPERTY_NAME;
5565 atspi_desc = "accessible-name";
5567 else if (!strcmp(property, "description"))
5569 prop = ATSPI_OBJECT_PROPERTY_DESCRIPTION;
5570 atspi_desc = "accessible-description";
5572 else if (!strcmp(property, "role"))
5574 prop = ATSPI_OBJECT_PROPERTY_ROLE;
5575 atspi_desc = "accessible-role";
5577 else if (!strcmp(property, "value"))
5579 prop = ATSPI_OBJECT_PROPERTY_VALUE;
5580 atspi_desc = "accessible-value";
5582 if (prop == ATSPI_OBJECT_PROPERTY_LAST)
5584 ERR("Unrecognized property name!");
5587 if (!STATE_TYPE_GET(pd->object_property_broadcast_mask, prop))
5589 DBG("Masking property %s changed event.", property);
5593 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5594 &_event_obj_signals[ATSPI_OBJECT_EVENT_PROPERTY_CHANGED], atspi_desc, 0, 0, NULL, NULL);
5599 _visible_data_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5601 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5603 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED))
5606 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5607 &_event_obj_signals[ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED], "",
5614 _active_descendant_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5616 Eo *child = event_info;
5619 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5621 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED))
5624 eo_do(child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5626 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5627 &_event_obj_signals[ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED], "",
5628 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), child);
5633 _children_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5635 const char *atspi_desc = NULL;
5636 Elm_Atspi_Event_Children_Changed_Data *ev_data = event_info;
5638 enum _Atspi_Object_Child_Event_Type type;
5640 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5642 type = ev_data->is_added ? ATSPI_OBJECT_CHILD_ADDED : ATSPI_OBJECT_CHILD_REMOVED;
5644 // update cached objects
5645 if (ev_data->is_added)
5646 _bridge_cache_build(data, ev_data->child);
5648 if (!STATE_TYPE_GET(pd->object_children_broadcast_mask, type))
5653 case ATSPI_OBJECT_CHILD_ADDED:
5655 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5657 case ATSPI_OBJECT_CHILD_REMOVED:
5658 atspi_desc = "remove";
5659 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5663 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5664 &_event_obj_signals[ATSPI_OBJECT_EVENT_CHILDREN_CHANGED], atspi_desc,
5665 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), ev_data->child);
5670 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5672 _move_outed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5674 const Elm_Atspi_Move_Outed_Type *type = event_info;
5676 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5678 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED))
5680 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5681 &_event_obj_signals[ATSPI_OBJECT_EVENT_MOVE_OUTED], "", *type, 0, NULL, NULL);
5687 _window_activated_detail_value_add(Eo *obj)
5689 unsigned int ret = ELM_ACCESSIBLE_DEFAULT_LABEL_ENABLED;
5690 Eina_List *l, *attr_list = NULL;
5691 Elm_Atspi_Attribute *attr = NULL;
5693 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5694 EINA_LIST_FOREACH(attr_list, l, attr)
5696 if (!strcmp(attr->key, "default_label") && !strcmp(attr->value, "disabled"))
5698 ret |= ELM_ACCESSIBLE_DEFAULT_LABEL_DISABLED;
5703 elm_atspi_attributes_list_free(attr_list);
5709 _window_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info EINA_UNUSED)
5711 enum _Atspi_Window_Signals type;
5713 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5715 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED)
5716 type = ATSPI_WINDOW_EVENT_CREATE;
5717 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED)
5718 type = ATSPI_WINDOW_EVENT_DESTROY;
5719 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DEACTIVATED)
5720 type = ATSPI_WINDOW_EVENT_DEACTIVATE;
5721 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5722 type = ATSPI_WINDOW_EVENT_ACTIVATE;
5723 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MAXIMIZED)
5724 type = ATSPI_WINDOW_EVENT_MAXIMIZE;
5725 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MINIMIZED)
5726 type = ATSPI_WINDOW_EVENT_MINIMIZE;
5727 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_RESTORED)
5728 type = ATSPI_WINDOW_EVENT_RESTORE;
5732 if (!STATE_TYPE_GET(pd->window_signal_broadcast_mask, type))
5737 ERR("A11Y connection closed. Unable to send ATSPI event.");
5741 unsigned int det1 = 0;
5742 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5743 det1 = _window_activated_detail_value_add(obj);
5745 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_WINDOW,
5746 &_window_obj_signals[type], "", det1, 0, "i", 0);
5751 _selection_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5753 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5755 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_SELECTION_CHANGED))
5758 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5759 &_event_obj_signals[ATSPI_OBJECT_EVENT_SELECTION_CHANGED], "", 0, 0, "i", 0);
5763 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, ...)
5765 Eldbus_Message *msg;
5766 Eldbus_Message_Iter *iter , *iter_stack[64], *iter_struct;
5772 EINA_SAFETY_ON_NULL_RETURN(infc);
5773 EINA_SAFETY_ON_NULL_RETURN(signal);
5774 EINA_SAFETY_ON_NULL_RETURN(minor);
5775 EINA_SAFETY_ON_NULL_RETURN(obj);
5776 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5778 path = _bridge_path_from_object(bridge, obj);
5780 msg = eldbus_message_signal_new(path, infc, signal->name);
5783 va_start(va, variant_sig);
5785 iter = eldbus_message_iter_get(msg);
5786 eldbus_message_iter_arguments_append(iter, "sii", minor, det1, det2);
5790 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', variant_sig);
5792 const char *tmp = variant_sig;
5798 iter_stack[top + 1] = eldbus_message_iter_container_new(iter_stack[top], 'r', NULL);
5802 eldbus_message_iter_basic_append(iter_stack[top], 's', va_arg(va, char*));
5805 eldbus_message_iter_basic_append(iter_stack[top], 'i', va_arg(va, int));
5808 atspi_obj = va_arg(va, Eo*);
5809 path = _bridge_path_from_object(bridge, atspi_obj);
5810 eldbus_message_iter_basic_append(iter_stack[top], 'o', path);
5813 eldbus_message_iter_container_close(iter_stack[top - 1], iter_stack[top]);
5817 ERR("Not supported d-bus type: %c.", *tmp);
5823 else // AT-SPI implementation forces checks on variant in signature even if not used.
5825 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', "i");
5826 eldbus_message_iter_basic_append(iter_stack[top], 'i', 0);
5831 ERR("Invalid d-bus signature: () do not match.");
5833 eldbus_message_iter_container_close(iter, iter_stack[0]);
5835 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
5836 path = _bridge_path_from_object(bridge, elm_atspi_bridge_root_get(bridge));
5837 eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
5838 eldbus_message_iter_basic_append(iter_struct, 'o', path);
5839 eldbus_message_iter_container_close(iter, iter_struct);
5841 eldbus_connection_send(pd->a11y_bus, msg, NULL, NULL, -1);
5842 DBG("Send %s.%s[%s,%d,%d]", infc, signal->name, minor, det1, det2);
5846 _text_caret_moved_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5850 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5852 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED))
5855 eo_do(obj, cursor_pos = elm_interface_atspi_text_caret_offset_get());
5857 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5858 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED], "", cursor_pos, 0, NULL, NULL);
5864 _text_text_inserted_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5866 Elm_Atspi_Text_Change_Info *info = event_info;
5868 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5870 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5875 WRN("Try to send signal with NULL value");
5879 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5880 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "insert", info->pos, info->len, "s", info->content);
5886 _text_text_removed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5888 Elm_Atspi_Text_Change_Info *info = event_info;
5890 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5892 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5897 WRN("Try to send signal with NULL value");
5901 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5902 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "delete", info->pos, info->len, "s", info->content);
5908 _text_selection_changed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5910 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5912 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED))
5915 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5916 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED], "", 0, 0, NULL, NULL);
5921 //TIZEN_ONLY(20160527) - Add direct reading feature
5923 _on_reading_state_changed(void *data EINA_UNUSED, const Eldbus_Message *msg)
5926 const char *say_signal_name = "";
5927 Elm_Atspi_Say_Info *say_info;
5929 if (eldbus_message_arguments_get(msg, "is", &i, &say_signal_name))
5930 { if (read_command_id)
5932 say_info = eina_hash_find(read_command_id, &i);
5935 if (say_info->func && say_signal_name)
5936 say_info->func(say_info->data, say_signal_name);
5937 eina_hash_del(read_command_id, &i, NULL);
5946 _event_handlers_register(Eo *bridge)
5948 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5950 _registered_events_list_update(bridge);
5952 // register signal handlers in order to update list of registered listeners of ATSPI-Clients
5953 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);
5954 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);
5955 //TIZEN_ONLY(20160527) - Add direct reading feature
5956 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);
5958 pd->key_flr = ecore_event_filter_add(NULL, _elm_atspi_bridge_key_filter, NULL, bridge);
5962 _bridge_object_unregister(Eo *bridge, Eo *obj)
5964 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5966 eina_hash_del(pd->cache, &obj, obj);
5970 _on_object_add(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
5972 Eldbus_Message *sig;
5973 Eldbus_Message_Iter *iter;
5975 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5977 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_ADDED);
5978 iter = eldbus_message_iter_get(sig);
5979 _cache_item_reference_append_cb(data, obj, iter);
5981 eldbus_service_signal_send(pd->cache_interface, sig);
5987 _on_object_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
5989 Eldbus_Message *sig;
5991 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5993 _bridge_object_unregister(data, obj);
5995 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_REMOVED);
5996 Eldbus_Message_Iter *iter = eldbus_message_iter_get(sig);
5997 _bridge_iter_object_reference_append(data, iter, obj);
5998 eldbus_service_signal_send(pd->cache_interface, sig);
6004 _bridge_cache_build(Eo *bridge, void *obj)
6006 Eina_List *children;
6007 Elm_Atspi_State_Set ss;
6010 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6012 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6015 if (!eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
6016 _bridge_object_register(bridge, obj);
6018 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
6019 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
6021 if (eo_isa(obj, ELM_INTERFACE_ATSPI_WINDOW_INTERFACE))
6023 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_ACTIVE))
6025 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6026 pd->window_activated = EINA_TRUE;
6031 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6032 pd->window_activated = EINA_FALSE;
6036 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
6037 EINA_LIST_FREE(children, child)
6038 _bridge_cache_build(bridge, child);
6042 _interfaces_unregister(Eo *bridge)
6044 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6046 #define INTERFACE_SAFE_FREE(ifc) \
6048 eldbus_service_interface_unregister(ifc); \
6051 INTERFACE_SAFE_FREE(pd->interfaces.accessible);
6052 INTERFACE_SAFE_FREE(pd->interfaces.application);
6053 INTERFACE_SAFE_FREE(pd->interfaces.action);
6054 INTERFACE_SAFE_FREE(pd->interfaces.component);
6055 INTERFACE_SAFE_FREE(pd->interfaces.collection);
6056 INTERFACE_SAFE_FREE(pd->interfaces.editable_text);
6057 INTERFACE_SAFE_FREE(pd->interfaces.image);
6058 INTERFACE_SAFE_FREE(pd->interfaces.selection);
6059 INTERFACE_SAFE_FREE(pd->interfaces.text);
6060 INTERFACE_SAFE_FREE(pd->interfaces.value);
6064 _a11y_connection_shutdown(Eo *bridge)
6066 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6067 Eldbus_Pending *pending;
6070 _elm_atspi_bridge_app_unregister(bridge);
6073 eina_hash_free(pd->cache);
6076 if (pd->cache_interface)
6077 eldbus_service_object_unregister(pd->cache_interface);
6078 pd->cache_interface = NULL;
6080 _interfaces_unregister(bridge);
6082 if (pd->key_flr) ecore_event_filter_del(pd->key_flr);
6085 if (pd->register_hdl) eldbus_signal_handler_del(pd->register_hdl);
6086 pd->register_hdl = NULL;
6088 if (pd->unregister_hdl) eldbus_signal_handler_del(pd->unregister_hdl);
6089 pd->unregister_hdl = NULL;
6091 //TIZEN_ONLY(20160527) - Add direct reading feature
6092 if (pd->reading_state_changed_hdl) eldbus_signal_handler_del(pd->reading_state_changed_hdl);
6093 pd->reading_state_changed_hdl = NULL;
6096 EINA_LIST_FREE(pd->pending_requests, pending)
6097 eldbus_pending_cancel(pending);
6098 pd->pending_requests = NULL;
6100 if (pd->a11y_bus) eldbus_connection_unref(pd->a11y_bus);
6101 pd->a11y_bus = NULL;
6103 if (pd->state_hash) eina_hash_free(pd->state_hash);
6104 pd->state_hash = NULL;
6106 if (pd->event_hash) eina_hash_free(pd->event_hash);
6107 pd->event_hash = NULL;
6109 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, elm_interface_atspi_accessible_event_handler_del(pd->event_hdlr));
6110 pd->event_hdlr = NULL;
6112 eo_do(bridge, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, NULL));
6113 pd->connected = EINA_FALSE;
6116 static void _disconnect_cb(void *data, Eldbus_Connection *conn EINA_UNUSED, void *event_info EINA_UNUSED)
6118 _a11y_connection_shutdown(data);
6122 _interfaces_register(Eo *bridge)
6124 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6126 pd->interfaces.accessible =
6127 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &accessible_iface_desc);
6128 eldbus_service_object_data_set(pd->interfaces.accessible, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6130 pd->interfaces.application =
6131 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &application_iface_desc);
6132 eldbus_service_object_data_set(pd->interfaces.application, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6134 pd->interfaces.action =
6135 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &action_iface_desc);
6136 eldbus_service_object_data_set(pd->interfaces.action, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6138 pd->interfaces.component =
6139 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &component_iface_desc);
6140 eldbus_service_object_data_set(pd->interfaces.component, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6142 pd->interfaces.collection =
6143 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &collection_iface_desc);
6144 eldbus_service_object_data_set(pd->interfaces.collection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6146 pd->interfaces.editable_text =
6147 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &editable_text_iface_desc);
6148 eldbus_service_object_data_set(pd->interfaces.editable_text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6150 pd->interfaces.image =
6151 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &image_iface_desc);
6152 eldbus_service_object_data_set(pd->interfaces.image, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6154 pd->interfaces.selection =
6155 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &selection_iface_desc);
6156 eldbus_service_object_data_set(pd->interfaces.selection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6158 pd->interfaces.text =
6159 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &text_iface_desc);
6160 eldbus_service_object_data_set(pd->interfaces.text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6162 pd->interfaces.value =
6163 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &value_iface_desc);
6164 eldbus_service_object_data_set(pd->interfaces.value, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6168 _bridge_accessible_event_dispatch(void *data, Eo *accessible, const Eo_Event_Description *desc, void *event_info)
6170 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6172 _bridge_object_register(data, accessible);
6174 Eo_Event_Cb cb = eina_hash_find(pd->event_hash, &desc);
6175 return cb ? cb(data, accessible, desc, event_info) : EINA_TRUE;
6179 _a11y_bus_initialize(Eo *obj, const char *socket_addr)
6181 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
6182 pd->a11y_bus = eldbus_private_address_connection_get(socket_addr);
6186 eldbus_connection_event_callback_add(pd->a11y_bus, ELDBUS_CONNECTION_EVENT_DISCONNECTED, _disconnect_cb, obj);
6188 // init data structures
6189 pd->cache = eina_hash_pointer_new(NULL);
6190 pd->state_hash = _elm_atspi_state_hash_build();
6191 pd->event_hash = _elm_atspi_event_hash_build();
6194 _cache_register(obj);
6195 _interfaces_register(obj);
6196 _event_handlers_register(obj);
6197 if (!getenv("ELM_ATSPI_NO_EMBED"))
6198 _elm_atspi_bridge_app_register(obj);
6200 // register accesible object event listener
6201 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, pd->event_hdlr = elm_interface_atspi_accessible_event_handler_add(_bridge_accessible_event_dispatch, obj));
6206 _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6208 const char *errname, *errmsg, *sock_addr = NULL;
6209 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6211 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6213 if (eldbus_message_error_get(msg, &errname, &errmsg))
6215 ERR("%s %s", errname, errmsg);
6219 if (!eldbus_message_arguments_get(msg, "s", &sock_addr) || !sock_addr)
6221 ERR("Could not get A11Y Bus socket address.");
6225 _a11y_socket_address = eina_stringshare_add(sock_addr);
6226 _a11y_bus_initialize((Eo*)data, sock_addr);
6229 static void _a11y_connection_init(Eo *bridge)
6231 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6232 Eina_Bool is_connected;
6234 eo_do(bridge, is_connected = elm_obj_atspi_bridge_connected_get());
6236 if (is_connected) return;
6238 // TIZEN_ONLY(20170512): send window activated event to at_spi2 only once per session
6239 pd->window_activated_broadcast_needed = EINA_TRUE;
6241 Eldbus_Message *m = eldbus_object_method_call_new(pd->bus_obj, A11Y_DBUS_INTERFACE, "GetAddress");
6242 Eldbus_Pending *p = eldbus_object_send(pd->bus_obj, m, _a11y_bus_address_get, bridge, 100);
6245 pd->pending_requests = eina_list_append(pd->pending_requests, p);
6249 _screen_reader_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6251 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6252 const char *errname, *errmsg;
6253 Eina_Bool is_enabled;
6254 Eldbus_Message_Iter *variant;
6256 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6258 if (eldbus_message_error_get(msg, &errname, &errmsg))
6260 WRN("%s %s", errname, errmsg);
6263 if (!eldbus_message_arguments_get(msg, "v", &variant))
6265 ERR("'ScreenReaderEnabled' not packed into variant.");
6268 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6270 ERR("Could not get 'ScreenReaderEnabled' boolean property");
6273 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6274 pd->screen_reader_enabled = !!is_enabled;
6276 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6277 //register/unregister access objects accordingly.
6278 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6279 _elm_win_screen_reader(is_enabled);
6284 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6286 _at_spi_client_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6288 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6289 const char *errname, *errmsg;
6290 Eina_Bool is_enabled;
6291 Eldbus_Message_Iter *variant;
6293 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6295 if (eldbus_message_error_get(msg, &errname, &errmsg))
6297 WRN("%s %s", errname, errmsg);
6300 if (!eldbus_message_arguments_get(msg, "v", &variant))
6302 ERR("'" A11Y_DBUS_ENABLED_PROPERTY "' not packed into variant.");
6305 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6307 ERR("Could not get '" A11Y_DBUS_ENABLED_PROPERTY "' boolean property");
6311 _a11y_connection_init(data);
6314 _elm_win_atspi(EINA_FALSE);
6315 DBG("AT-SPI2 stack not enabled.");
6321 static void _bridge_object_register(Eo *bridge, Eo *obj)
6323 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6325 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6327 WRN("Unable to register class w/o Elm_Interface_Atspi_Accessible!");
6331 if (eina_hash_find(pd->cache, &obj))
6334 eina_hash_add(pd->cache, &obj, obj);
6338 _elm_atspi_bridge_init(void)
6342 _instance = eo_add(ELM_ATSPI_BRIDGE_CLASS, NULL);
6348 _elm_atspi_bridge_get(void)
6354 _elm_atspi_bridge_shutdown(void)
6361 if (_a11y_socket_address)
6362 eina_stringshare_del(_a11y_socket_address);
6363 _a11y_socket_address = NULL;
6366 static Key_Event_Info*
6367 _key_event_info_new(int event_type, const Ecore_Event_Key *data, Eo *bridge)
6369 Key_Event_Info *ret;
6370 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
6372 ret = calloc(sizeof(Key_Event_Info), 1);
6374 ret->type = event_type;
6376 ret->bridge = bridge;
6378 ret->event.keyname = eina_stringshare_add(data->keyname);
6379 ret->event.key = eina_stringshare_add(data->key);
6380 ret->event.string = eina_stringshare_add(data->string);
6381 ret->event.compose = eina_stringshare_add(data->compose);
6383 // not sure why it is here, but explicite keep it NULLed.
6384 ret->event.data = NULL;
6390 _key_event_info_free(Key_Event_Info *data)
6392 EINA_SAFETY_ON_NULL_RETURN(data);
6394 eina_stringshare_del(data->event.keyname);
6395 eina_stringshare_del(data->event.key);
6396 eina_stringshare_del(data->event.string);
6397 eina_stringshare_del(data->event.compose);
6403 _iter_marshall_key_event(Eldbus_Message_Iter *iter, Key_Event_Info *data)
6405 Eldbus_Message_Iter *struct_iter;
6406 EINA_SAFETY_ON_NULL_RETURN(data);
6408 struct_iter = eldbus_message_iter_container_new(iter, 'r', NULL);
6410 const char *str = data->event.keyname ? data->event.keyname : "";
6411 int is_text = data->event.keyname ? 1 : 0;
6413 if (data->type == ECORE_EVENT_KEY_DOWN)
6414 type = ATSPI_KEY_PRESSED_EVENT;
6416 type = ATSPI_KEY_RELEASED_EVENT;
6418 eldbus_message_iter_arguments_append(struct_iter, "uiiiisb", type, 0, data->event.keycode, 0, data->event.timestamp, str, is_text);
6419 eldbus_message_iter_container_close(iter, struct_iter);
6423 _on_event_del(void *user_data, void *func_data EINA_UNUSED)
6425 Key_Event_Info *info = user_data;
6426 _key_event_info_free(info);
6430 _on_listener_answer(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6432 Key_Event_Info *info = data;
6433 const char *errname, *errmsg;
6434 Eina_Bool ret = EINA_TRUE;
6436 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(info->bridge, pd);
6438 if (eldbus_message_error_get(msg, &errname, &errmsg))
6440 ERR("%s %s", errname, errmsg);
6443 if (!eldbus_message_arguments_get(msg, "b", &ret))
6445 ERR("Return message doen not contian return value");
6450 _key_event_info_free(info);
6454 ecore_event_add(info->type, &info->event, _on_event_del, info);
6455 pd->reemited_events = eina_list_append(pd->reemited_events, &info->event);
6459 _elm_atspi_bridge_key_filter(void *data, void *loop EINA_UNUSED, int type, void *event)
6461 Eldbus_Message *msg;
6462 Eldbus_Message_Iter *iter;
6463 Ecore_Event_Key *key_event = event;
6467 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_TRUE);
6469 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6470 if (!pd->window_activated) return EINA_TRUE;
6473 if ((type != ECORE_EVENT_KEY_DOWN) && (type != ECORE_EVENT_KEY_UP)) return EINA_TRUE;
6475 // check if reemited
6476 if (eina_list_data_find(pd->reemited_events, event))
6478 pd->reemited_events = eina_list_remove(pd->reemited_events, event);
6482 // TIZEN_ONLY(20170118): Not handle events if keyboard is on
6485 Eina_List *children, *l;
6487 eo_do(pd->root, children = elm_interface_atspi_accessible_children_get());
6489 EINA_LIST_FOREACH(children, l, child)
6491 if (elm_widget_focus_get(child)) break;
6493 eina_list_free(children);
6495 Elm_Win_Keyboard_Mode mode;
6496 mode = elm_win_keyboard_mode_get(child);
6497 if (mode == ELM_WIN_KEYBOARD_ON) return EINA_TRUE;
6501 ke = _key_event_info_new(type, key_event, bridge);
6502 if (!ke) return EINA_TRUE;
6504 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_DEC,
6505 ATSPI_DBUS_INTERFACE_DEC, "NotifyListenersSync");
6506 iter = eldbus_message_iter_get(msg);
6507 _iter_marshall_key_event(iter, ke);
6509 // timeout should be kept reasonaby low to avoid delays
6510 if (!eldbus_connection_send(pd->a11y_bus, msg, _on_listener_answer, ke, 100))
6517 _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6519 return pd->connected;
6523 _elm_atspi_bridge_root_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6527 pd->root = eo_add(ELM_ATSPI_APP_OBJECT_CLASS, NULL);
6528 elm_interface_atspi_accessible_added(pd->root);
6535 _properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
6537 Eldbus_Proxy_Event_Property_Changed *ev = event;
6540 const char *ifc = eldbus_proxy_interface_get(ev->proxy);
6541 if (ev->name && !strcmp(ev->name, "ScreenReaderEnabled" ) &&
6542 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6544 if (!eina_value_get(ev->value, &val))
6546 ERR("Unable to get ScreenReaderEnabled property value");
6549 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6550 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6551 pd->screen_reader_enabled = !!val;
6553 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6554 //register/unregister access objects accordingly.
6555 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6556 _elm_win_screen_reader(val);
6560 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6561 if (ev->name && !strcmp(ev->name, A11Y_DBUS_ENABLED_PROPERTY) &&
6562 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6564 if (!eina_value_get(ev->value, &val))
6566 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6567 ERR("Unable to get " A11Y_DBUS_ENABLED_PROPERTY " property value");
6573 _a11y_connection_init(bridge);
6576 _elm_win_atspi(EINA_FALSE);
6577 _a11y_connection_shutdown(bridge);
6584 _elm_atspi_bridge_eo_base_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6586 Eldbus_Proxy *proxy;
6587 Eldbus_Pending *req;
6589 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_constructor());
6593 if (!(pd->session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION)))
6595 ERR("Unable to connect to Session Bus");
6598 if (!(pd->bus_obj = eldbus_object_get(pd->session_bus, A11Y_DBUS_NAME, A11Y_DBUS_PATH)))
6600 ERR("Could not get /org/a11y/bus object");
6603 if (!(proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE)))
6605 ERR("Could not get proxy object for %s interface", A11Y_DBUS_STATUS_INTERFACE);
6608 if (!(req = eldbus_proxy_property_get(proxy, "ScreenReaderEnabled", _screen_reader_enabled_get, obj)))
6610 ERR("Could not send PropertyGet request");
6613 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6615 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6616 if (!(req = eldbus_proxy_property_get(proxy, A11Y_DBUS_ENABLED_PROPERTY, _at_spi_client_enabled_get, obj)))
6618 ERR("Could not send PropertyGet request");
6622 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6625 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
6626 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
6627 _properties_changed_cb, obj);
6632 eldbus_object_unref(pd->bus_obj);
6635 eldbus_connection_unref(pd->session_bus);
6636 pd->session_bus = NULL;
6641 _elm_atspi_bridge_eo_base_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6643 _a11y_connection_shutdown(obj);
6645 if (pd->bus_obj) eldbus_object_unref(pd->bus_obj);
6646 if (pd->session_bus) eldbus_connection_unref(pd->session_bus);
6647 if (pd->root) eo_del(pd->root);
6649 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_destructor());
6653 elm_atspi_bridge_object_address_get(Eo *obj, char **bus, char **path)
6655 Eo *bridge = _elm_atspi_bridge_get();
6658 ERR("Connection with accessibility bus not established.");
6661 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
6662 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6664 ERR("Connection with accessibility bus not established.");
6667 if (bus) *bus = strdup(eldbus_connection_unique_name_get(pd->a11y_bus));
6668 if (path) *path = strdup(_bridge_path_from_object(bridge, obj));
6674 _proxy_property_get(const Eldbus_Service_Interface *interface, const char *property,
6675 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED,
6676 Eldbus_Message **error EINA_UNUSED)
6679 Eo *obj = eldbus_service_object_data_get(interface, "_atspi_obj");
6680 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6682 if (!strcmp(property, "Object"))
6685 eo_do(obj, parent = eo_parent_get());
6686 if (!elm_atspi_bridge_object_address_get(parent, &bus, &path))
6689 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
6692 eldbus_message_iter_basic_append(iter_struct, 's', bus);
6693 eldbus_message_iter_basic_append(iter_struct, 'o', path);
6694 eldbus_message_iter_container_close(iter, iter_struct);
6703 static const Eldbus_Property proxy_properties[] = {
6704 { "Object", "(so)", _proxy_property_get, NULL, 0 },
6705 { NULL, NULL, NULL, NULL, 0 }
6708 static const Eldbus_Service_Interface_Desc _proxy_iface_desc = {
6709 ELM_ATSPI_DBUS_INTERFACE_PROXY, socket_methods, NULL, proxy_properties, NULL, NULL
6712 static void _embedded_reply_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6714 Eo *parent, *proxy = data;
6715 const char *err, *txt;
6717 if (eldbus_message_error_get(msg, &err, &txt))
6719 ERR("AT-SPI: Embedded method call failed: %s %s", err, txt);
6720 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6723 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_CONNECTED, NULL));
6725 eo_do(proxy, parent = eo_parent_get());
6727 elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, proxy);
6731 _plug_embedded_send(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6733 char *obj_path = NULL;
6735 Eldbus_Message *msg = NULL;
6737 eo_do(proxy, parent = eo_parent_get());
6738 if (!parent) goto fail;
6740 msg = eldbus_message_method_call_new(bus, path, ATSPI_DBUS_INTERFACE_SOCKET, "Embedded");
6741 if (!msg) goto fail;
6743 if (!elm_atspi_bridge_object_address_get(parent, NULL, &obj_path))
6746 if (!eldbus_message_arguments_append(msg, "s", obj_path))
6749 if (!eldbus_connection_send(conn, msg, _embedded_reply_cb, proxy, 100))
6752 ELM_SAFE_FREE(obj_path, free);
6756 ERR("AT-SPI: Unable to send Embedded request.");
6757 if (msg) eldbus_message_unref(msg);
6758 ELM_SAFE_FREE(obj_path, free);
6759 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6762 static void _socket_addr_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6765 const char *bus, *path, *err, *txt;
6766 Eldbus_Message_Iter *iter, *iter_variant, *iter_struct;
6768 Eo *bridge = _elm_atspi_bridge_get();
6771 ERR("AT-SPI: Atspi bridge is not enabled.");
6774 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6776 if (eldbus_message_error_get(msg, &err, &txt))
6778 ERR("Unable to connect to socket: %s %s", err, txt);
6782 iter = eldbus_message_iter_get(msg);
6783 if (!eldbus_message_iter_arguments_get(iter, "v", &iter_variant))
6785 ERR("Unable to get variant parameter");
6789 if (!eldbus_message_iter_arguments_get(iter_variant, "(so)", &iter_struct))
6791 ERR("Unable to get so parameters");
6795 if (!eldbus_message_iter_arguments_get(iter_struct, "so", &bus, &path))
6797 ERR("Unable to get so parameters");
6801 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
6803 _plug_embedded_send(pd->a11y_bus, proxy, bus, path);
6808 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6812 eo_do(proxy, elm_obj_atspi_proxy_address_get_retry_timer_add());
6816 _plug_address_discover(Eldbus_Connection *conn, Eo *proxy, const char *svc_bus, const char *svc_path)
6818 Eldbus_Object *dobj;
6819 dobj = eldbus_object_get(conn, svc_bus, svc_path);
6822 ERR("Unable to get eldbus object from: %s %s", svc_bus, svc_path);
6826 Eldbus_Message *msg = eldbus_object_method_call_new(dobj, ELDBUS_FDO_INTERFACE_PROPERTIES, "Get");
6827 eldbus_message_arguments_append(msg, "ss", ELM_ATSPI_DBUS_INTERFACE_PROXY, "Object");
6828 eldbus_object_send(dobj, msg, _socket_addr_get_cb, proxy, 100);
6831 static void _plug_connect(Eldbus_Connection *conn, Eo *proxy)
6833 const char *bus, *path;
6835 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
6836 eo_do(proxy, path = eo_key_data_get("__svc_path"));
6840 _plug_address_discover(conn, proxy, bus, path);
6845 eo_do(proxy, elm_obj_atspi_proxy_address_get(&bus, &path));
6848 ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set. Unable to connect");
6849 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6852 _plug_embedded_send(conn, proxy, bus, path);
6857 static Eina_Bool _from_list_remove(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6859 Eina_List **list = data;
6860 *list = eina_list_remove(*list, obj);
6864 EAPI void elm_atspi_bridge_utils_proxy_connect(Eo *proxy)
6866 Eo *bridge = _elm_atspi_bridge_get();
6870 ERR("AT-SPI: Atspi bridge is not enabled.");
6871 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6874 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6878 if (!eina_list_data_find(pd->plug_queue, proxy))
6880 pd->plug_queue = eina_list_append(pd->plug_queue, proxy);
6881 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->plug_queue));
6885 _plug_connect(pd->a11y_bus, proxy);
6889 * @brief Service name sanitizer according to specs:
6890 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
6891 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
6893 char *_sanitize_service_name(const char *name)
6895 char ret[256] = "\0";
6897 if (!name) return NULL;
6899 const char *tmp = name;
6902 // name element should not begin with digit. Swallow non-charater prefix
6903 while ((*tmp != '\0') && !isalpha(*tmp)) tmp++;
6905 // append rest of character valid charactes [A-Z][a-z][0-9]_
6906 while ((*tmp != '\0') && (dst < &ret[sizeof(ret) - 1]))
6908 if (isalpha(*tmp) || isdigit(*tmp) || (*tmp == '_'))
6917 Eo* _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type)
6920 char bus[256], path[256], *name;
6923 name = _sanitize_service_name(svcname);
6924 if (!name) return NULL;
6926 res = snprintf(bus, sizeof(bus), "elm.atspi.proxy.socket.%s-%d", name, svcnum);
6927 if (res < 0 || (res >= (int)sizeof(bus)))
6933 res = snprintf(path, sizeof(path), "/elm/atspi/proxy/socket/%s/%d", name, svcnum);
6934 if (res < 0 || (res >= (int)sizeof(path)))
6942 ret = eo_add(ELM_ATSPI_PROXY_CLASS, parent, elm_obj_atspi_proxy_constructor(type));
6943 if (!ret) return NULL;
6945 eo_do(ret, eo_key_data_set("__svc_bus", eina_stringshare_add(bus)));
6946 eo_do(ret, eo_key_data_set("__svc_path", eina_stringshare_add(path)));
6952 _on_socket_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6954 Eldbus_Service_Interface *ifc = data;
6956 Eldbus_Connection *conn = eldbus_service_connection_get(ifc);
6957 eo_do(obj, bus = eo_key_data_get("__svc_bus"));
6958 eldbus_name_release(conn, bus, NULL, NULL);
6959 eldbus_service_interface_unregister(ifc);
6964 _proxy_interface_register(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6966 Eldbus_Service_Interface *proxy_infc;
6967 Eo *bridge = _elm_atspi_bridge_get();
6970 ERR("AT-SPI: Atspi bridge is not enabled.");
6973 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6975 eldbus_name_request(conn, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, NULL, NULL);
6976 proxy_infc = eldbus_service_interface_register(pd->a11y_bus, path, &_proxy_iface_desc);
6978 ERR("AT-SPI: Proxy interface registration failed");
6979 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _on_socket_del, proxy_infc));
6980 eldbus_service_object_data_set(proxy_infc, "_atspi_obj", proxy);
6983 static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy)
6985 const char *bus, *path;
6986 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6987 Eo *bridge = _elm_atspi_bridge_get();
6988 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6991 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
6992 eo_do(proxy, path = eo_key_data_get("__svc_path"));
6995 _proxy_interface_register(conn, proxy, bus, path);
6997 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6998 pd->interfaces.socket =
6999 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &socket_iface_desc);
7003 EAPI void elm_atspi_bridge_utils_proxy_listen(Eo *proxy)
7005 Eo *bridge = _elm_atspi_bridge_get();
7008 ERR("AT-SPI: Atspi bridge is not enabled.");
7011 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7014 if (!eina_list_data_find(pd->socket_queue, proxy))
7016 pd->socket_queue = eina_list_append(pd->socket_queue, proxy);
7017 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->socket_queue));
7021 _socket_ifc_create(pd->a11y_bus, proxy);
7024 //TIZEN_ONLY(20160527) - Add direct reading feature
7026 _on_read_command_call(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7028 const char *errname, *errmsg;
7032 Elm_Atspi_Say_Info *say_info = data;
7034 if (eldbus_message_error_get(msg, &errname, &errmsg))
7036 ERR("%s %s", errname, errmsg);
7042 // get read command id and map it to obj
7043 if (eldbus_message_arguments_get(msg, "sbi", &s, &b, &i))
7045 if (!read_command_id)
7046 read_command_id = eina_hash_int32_new(NULL);
7048 if (!read_command_id) {
7049 ERR("eina_hash_int32_new() failed to create new map to store callbacks for direct reading commands");
7053 eina_hash_add(read_command_id, &i, say_info);
7059 elm_atspi_bridge_utils_say(const char* text,
7060 Eina_Bool discardable,
7061 const Elm_Atspi_Say_Signal_Cb func,
7064 Eldbus_Message *msg;
7065 Eldbus_Message_Iter *iter;
7066 Elm_Atspi_Say_Info *say_info = NULL;
7067 Eo *bridge = _elm_atspi_bridge_get();
7070 ERR("AT-SPI: Atspi bridge is not enabled.");
7073 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7076 ERR("AT-SPI: a11y bus is not set.");
7080 msg = eldbus_message_method_call_new(ELM_ATSPI_DIRECT_READ_BUS,
7081 ELM_ATSPI_DIRECT_READ_PATH,
7082 ELM_ATSPI_DIRECT_READ_INTERFACE,
7084 iter = eldbus_message_iter_get(msg);
7085 eldbus_message_iter_arguments_append(iter, "sb", text, discardable);
7087 say_info = calloc(1, sizeof(Elm_Atspi_Say_Info));
7089 say_info->func = func;
7090 say_info->data = (void *)data;
7093 eldbus_connection_send(pd->a11y_bus, msg, _on_read_command_call, say_info, -1);
7097 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7099 _offset_set_reply_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7101 const char *err, *txt;
7103 if (eldbus_message_error_get(msg, &err, &txt))
7105 ERR("AT-SPI: SetOffset method call failed: %s %s", err, txt);
7110 void elm_atspi_bridge_utils_proxy_offset_set(Eo *proxy, int x, int y)
7112 const char *bus, *path;
7113 Eo *bridge = _elm_atspi_bridge_get();
7114 if (!bridge) return;
7116 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7118 if (!pd->a11y_bus) return;
7120 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7121 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7123 Eldbus_Message *msg = NULL;
7125 msg = eldbus_message_method_call_new(bus, path, ELM_ATSPI_DBUS_INTERFACE_PROXY, "SetOffset");
7126 if (!msg) goto fail;
7128 if (!eldbus_message_arguments_append(msg, "i", x))
7131 if (!eldbus_message_arguments_append(msg, "i", y))
7134 if (!eldbus_connection_send(pd->a11y_bus, msg, _offset_set_reply_cb, NULL, 100))
7140 ERR("AT-SPI: Unable to send SetOffset request.");
7141 if (msg) eldbus_message_unref(msg);
7144 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
7145 EAPI Eina_Bool elm_atspi_bridge_utils_is_screen_reader_enabled(void)
7147 Eo *bridge = _elm_atspi_bridge_get();
7150 ERR("AT-SPI: Atspi bridge is not enabled.");
7153 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
7154 return pd->screen_reader_enabled;
7157 #include "elm_atspi_bridge.eo.c"