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) || eo_destructed_is(obj)) \
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) || eo_destructed_is(obj)) \
73 return _dbus_invalid_ref_error_new(msg);
75 typedef struct Key_Event_Info {
76 Ecore_Event_Key event;
81 typedef struct _Elm_Atspi_Bridge_Data
83 Eldbus_Connection *session_bus;
84 Eldbus_Connection *a11y_bus;
85 Eina_List *reemited_events;
88 Eldbus_Service_Interface *cache_interface;
89 Eldbus_Signal_Handler *register_hdl;
90 Eldbus_Signal_Handler *unregister_hdl;
91 //TIZEN_ONLY(20160614):apply callbacks on direct reading stop/cancel/skipp
92 Eldbus_Signal_Handler *reading_state_changed_hdl;
94 unsigned long object_broadcast_mask;
95 unsigned long object_property_broadcast_mask;
96 unsigned long object_children_broadcast_mask;
97 unsigned long long object_state_broadcast_mask;
98 unsigned long long window_signal_broadcast_mask;
99 Ecore_Event_Filter *key_flr;
100 Eldbus_Object *bus_obj;
101 Eina_List *pending_requests;
103 Eina_Hash *state_hash;
105 Eldbus_Service_Interface *accessible;
106 Eldbus_Service_Interface *application;
107 Eldbus_Service_Interface *action;
108 Eldbus_Service_Interface *component;
109 Eldbus_Service_Interface *collection;
110 Eldbus_Service_Interface *editable_text;
111 Eldbus_Service_Interface *image;
112 Eldbus_Service_Interface *selection;
113 Eldbus_Service_Interface *text;
114 Eldbus_Service_Interface *value;
115 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
116 Eldbus_Service_Interface *socket;
119 Elm_Atspi_Event_Handler *event_hdlr;
120 Eina_Hash *event_hash;
121 Eina_List *socket_queue;
122 Eina_List *plug_queue;
123 Eina_Bool connected : 1;
124 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
125 Eina_Bool window_activated : 1;
126 // TIZEN_ONLY(20170512): send window activated event to at_spi2 only once per session
127 Eina_Bool window_activated_broadcast_needed : 1;
128 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
129 Eina_Bool screen_reader_enabled : 1;
131 } Elm_Atspi_Bridge_Data;
134 struct collection_match_rule {
135 Elm_Atspi_State_Set states;
136 AtspiCollectionMatchType statematchtype;
137 Eina_List *attributes;
138 AtspiCollectionMatchType attributematchtype;
140 AtspiCollectionMatchType rolematchtype;
142 AtspiCollectionMatchType interfacematchtype;
143 Eina_Bool reverse : 1;
146 static Eo *_instance;
147 static int _init_count = 0;
148 static const char *_a11y_socket_address;
150 // Object Event handlers
151 static Eina_Bool _state_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
152 static Eina_Bool _property_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
153 static Eina_Bool _bounds_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
154 static Eina_Bool _children_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
155 static Eina_Bool _window_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
156 static Eina_Bool _visible_data_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
157 static Eina_Bool _active_descendant_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
158 static Eina_Bool _selection_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
159 static Eina_Bool _text_text_inserted_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
160 static Eina_Bool _text_text_removed_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
161 static Eina_Bool _text_caret_moved_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
162 static Eina_Bool _text_selection_changed_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info EINA_UNUSED);
163 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
164 static Eina_Bool _move_outed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info);
167 // bridge private methods
168 static void _bridge_cache_build(Eo *bridge, void *obj);
169 static void _bridge_object_register(Eo *bridge, Eo *obj);
170 static void _bridge_object_unregister(Eo *bridge, Eo *obj);
171 static const char * _bridge_path_from_object(Eo *bridge, const Eo *eo);
172 static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *ifc, const Eldbus_Signal *signal, const char *minor, unsigned int det1, unsigned int det2, const char *variant_sig, ...);
173 static Eo * _bridge_object_from_path(Eo *bridge, const char *path);
174 static void _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj);
177 static void _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj);
178 static Eina_Bool _elm_atspi_bridge_key_filter(void *data, void *loop, int type, void *event);
179 static void _object_desktop_reference_append(Eldbus_Message_Iter *iter);
180 static Eina_Bool _on_object_add(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED);
181 static Eina_Bool _on_object_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED);
182 static void _plug_connect(Eldbus_Connection *conn, Eo *proxy);
183 static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy);
184 static void _object_get_bus_name_and_path(Eo *bridge, const Eo *obj, const char **bus_name, const char **path);
185 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
186 static Eo *_calculate_navigable_accessible_at_point(Eo *bridge, Eo *root, Eina_Bool coord_type, int x, int y);
187 static Eo *_calculate_neighbor(Eo *bridge, Eo *root, Eo *current, Eina_Bool forward, int search_mode);
191 const Eo_Event_Description *desc;
192 const Eo_Event_Cb callback;
193 } Elm_Atspi_Bridge_Event_Handler;
195 static const Elm_Atspi_Bridge_Event_Handler event_handlers[] = {
196 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_CHILDREN_CHANGED, _children_changed_signal_send},
197 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_PROPERTY_CHANGED, _property_changed_signal_send},
198 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_BOUNDS_CHANGED, _bounds_changed_signal_send},
199 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_STATE_CHANGED, _state_changed_signal_send},
200 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_VISIBLE_DATA_CHANGED, _visible_data_changed_signal_send},
201 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_ACTIVE_DESCENDANT_CHANGED, _active_descendant_changed_signal_send},
202 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_ADDED, _on_object_add},
203 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_REMOVED, _on_object_del},
204 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED, _window_signal_send},
205 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED, _window_signal_send},
206 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED, _window_signal_send},
207 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DEACTIVATED, _window_signal_send},
208 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MAXIMIZED, _window_signal_send},
209 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MINIMIZED, _window_signal_send},
210 { ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_RESTORED, _window_signal_send},
211 { ELM_INTERFACE_ATSPI_SELECTION_EVENT_SELECTION_CHANGED, _selection_signal_send},
212 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_CARET_MOVED, _text_caret_moved_send },
213 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_INSERTED, _text_text_inserted_send },
214 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_REMOVED, _text_text_removed_send },
215 { ELM_INTERFACE_ATSPI_TEXT_EVENT_ACCESS_TEXT_SELECTION_CHANGED, _text_selection_changed_send },
216 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
217 { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_MOVE_OUTED, _move_outed_signal_send}
221 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
224 ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED = 0,
225 ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED_WITHOUT_WINDOW = 1 << 0,
226 ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_DISABLED = 1 << 1,
227 ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_KEYBOARD = 1 << 2,
231 enum _Atspi_Object_Child_Event_Type
233 ATSPI_OBJECT_CHILD_ADDED = 0,
234 ATSPI_OBJECT_CHILD_REMOVED
237 enum _Atspi_Object_Property
239 ATSPI_OBJECT_PROPERTY_NAME = 0,
240 ATSPI_OBJECT_PROPERTY_DESCRIPTION,
241 ATSPI_OBJECT_PROPERTY_VALUE,
242 ATSPI_OBJECT_PROPERTY_ROLE,
243 ATSPI_OBJECT_PROPERTY_PARENT,
244 ATSPI_OBJECT_PROPERTY_LAST
247 enum _Atspi_Object_Signals {
248 ATSPI_OBJECT_EVENT_PROPERTY_CHANGED = 0,
249 ATSPI_OBJECT_EVENT_BOUNDS_CHANGED,
250 ATSPI_OBJECT_EVENT_LINK_SELECTED,
251 ATSPI_OBJECT_EVENT_STATE_CHANGED,
252 ATSPI_OBJECT_EVENT_CHILDREN_CHANGED,
253 ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED,
254 ATSPI_OBJECT_EVENT_SELECTION_CHANGED,
255 ATSPI_OBJECT_EVENT_MODEL_CHANGED,
256 ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED,
257 ATSPI_OBJECT_EVENT_ROW_INSERTED,
258 ATSPI_OBJECT_EVENT_ROW_REORDERED,
259 ATSPI_OBJECT_EVENT_ROW_DELETED,
260 ATSPI_OBJECT_EVENT_COLUMN_INSERTED,
261 ATSPI_OBJECT_EVENT_COLUMN_REORDERED,
262 ATSPI_OBJECT_EVENT_COLUMN_DELETED,
263 ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED,
264 ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED,
265 ATSPI_OBJECT_EVENT_TEXT_CHANGED,
266 ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED,
267 ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED,
268 ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED,
269 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
270 ATSPI_OBJECT_EVENT_MOVE_OUTED
274 enum _Atspi_Window_Signals
276 ATSPI_WINDOW_EVENT_PROPERTY_CHANGE = 0,
277 ATSPI_WINDOW_EVENT_MINIMIZE,
278 ATSPI_WINDOW_EVENT_MAXIMIZE,
279 ATSPI_WINDOW_EVENT_RESTORE,
280 ATSPI_WINDOW_EVENT_CLOSE,
281 ATSPI_WINDOW_EVENT_CREATE,
282 ATSPI_WINDOW_EVENT_REPARENT,
283 ATSPI_WINDOW_EVENT_DESKTOPCREATE,
284 ATSPI_WINDOW_EVENT_DESKTOPDESTROY,
285 ATSPI_WINDOW_EVENT_DESTROY,
286 ATSPI_WINDOW_EVENT_ACTIVATE,
287 ATSPI_WINDOW_EVENT_DEACTIVATE,
288 ATSPI_WINDOW_EVENT_RAISE,
289 ATSPI_WINDOW_EVENT_LOWER,
290 ATSPI_WINDOW_EVENT_MOVE,
291 ATSPI_WINDOW_EVENT_RESIZE,
292 ATSPI_WINDOW_EVENT_SHADE,
293 ATSPI_WINDOW_EVENT_UUSHADE,
294 ATSPI_WINDOW_EVENT_RESTYLE,
297 static const Eldbus_Signal _event_obj_signals[] = {
298 [ATSPI_OBJECT_EVENT_PROPERTY_CHANGED] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
299 [ATSPI_OBJECT_EVENT_BOUNDS_CHANGED] = {"BoundsChanged", ELDBUS_ARGS({"siiv(iiii)", NULL}), 0},
300 [ATSPI_OBJECT_EVENT_LINK_SELECTED] = {"LinkSelected", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
301 [ATSPI_OBJECT_EVENT_STATE_CHANGED] = {"StateChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
302 [ATSPI_OBJECT_EVENT_CHILDREN_CHANGED] = {"ChildrenChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
303 [ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED] = {"VisibleDataChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
304 [ATSPI_OBJECT_EVENT_SELECTION_CHANGED] = {"SelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
305 [ATSPI_OBJECT_EVENT_MODEL_CHANGED] = {"ModelChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
306 [ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED] = {"ActiveDescendantChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
307 [ATSPI_OBJECT_EVENT_ROW_INSERTED] = {"RowInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
308 [ATSPI_OBJECT_EVENT_ROW_REORDERED] = {"RowReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
309 [ATSPI_OBJECT_EVENT_ROW_DELETED] = {"RowDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
310 [ATSPI_OBJECT_EVENT_COLUMN_INSERTED] = {"ColumnInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
311 [ATSPI_OBJECT_EVENT_COLUMN_REORDERED] = {"ColumnReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
312 [ATSPI_OBJECT_EVENT_COLUMN_DELETED] = {"ColumnDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
313 [ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED] = {"TextBoundsChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
314 [ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED] = {"TextSelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
315 [ATSPI_OBJECT_EVENT_TEXT_CHANGED] = {"TextChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
316 [ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED] = {"TextAttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
317 [ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED] = {"TextCaretMoved", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
318 [ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED] = {"AttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
319 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
320 [ATSPI_OBJECT_EVENT_MOVE_OUTED] = {"MoveOuted", ELDBUS_ARGS({"siiv(i)", NULL}), 0},
322 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
325 static const Eldbus_Signal _window_obj_signals[] = {
326 [ATSPI_WINDOW_EVENT_PROPERTY_CHANGE] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
327 [ATSPI_WINDOW_EVENT_MINIMIZE] = {"Minimize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
328 [ATSPI_WINDOW_EVENT_MAXIMIZE] = {"Maximize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
329 [ATSPI_WINDOW_EVENT_RESTORE] = {"Restore", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
330 [ATSPI_WINDOW_EVENT_CLOSE] = {"Close", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
331 [ATSPI_WINDOW_EVENT_CREATE] = {"Create", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
332 [ATSPI_WINDOW_EVENT_REPARENT] = {"Reparent", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
333 [ATSPI_WINDOW_EVENT_DESKTOPCREATE] = {"DesktopCreate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
334 [ATSPI_WINDOW_EVENT_DESKTOPDESTROY] = {"DesktopDestroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
335 [ATSPI_WINDOW_EVENT_DESTROY] = {"Destroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
336 [ATSPI_WINDOW_EVENT_ACTIVATE] = {"Activate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
337 [ATSPI_WINDOW_EVENT_DEACTIVATE] = {"Deactivate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
338 [ATSPI_WINDOW_EVENT_RAISE] = {"Raise", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
339 [ATSPI_WINDOW_EVENT_LOWER] = {"Lower", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
340 [ATSPI_WINDOW_EVENT_MOVE] = {"Move", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
341 [ATSPI_WINDOW_EVENT_RESIZE] = {"Resize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
342 [ATSPI_WINDOW_EVENT_SHADE] = {"Shade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
343 [ATSPI_WINDOW_EVENT_UUSHADE] = {"uUshade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
344 [ATSPI_WINDOW_EVENT_RESTYLE] = {"Restyle", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
345 {NULL, ELDBUS_ARGS({NULL, NULL}), 0}
348 const int elm_roles_to_atspi_roles[][2] = {
349 { ELM_ATSPI_ROLE_INVALID, ATSPI_ROLE_INVALID },
350 { ELM_ATSPI_ROLE_ACCELERATOR_LABEL, ATSPI_ROLE_ACCELERATOR_LABEL },
351 { ELM_ATSPI_ROLE_ALERT, ATSPI_ROLE_ALERT },
352 { ELM_ATSPI_ROLE_ANIMATION, ATSPI_ROLE_ANIMATION },
353 { ELM_ATSPI_ROLE_ARROW, ATSPI_ROLE_ARROW },
354 { ELM_ATSPI_ROLE_CALENDAR, ATSPI_ROLE_CALENDAR },
355 { ELM_ATSPI_ROLE_CANVAS, ATSPI_ROLE_CANVAS },
356 { ELM_ATSPI_ROLE_CHECK_BOX, ATSPI_ROLE_CHECK_BOX },
357 { ELM_ATSPI_ROLE_CHECK_MENU_ITEM, ATSPI_ROLE_CHECK_MENU_ITEM },
358 { ELM_ATSPI_ROLE_COLOR_CHOOSER, ATSPI_ROLE_COLOR_CHOOSER },
359 { ELM_ATSPI_ROLE_COLUMN_HEADER, ATSPI_ROLE_COLUMN_HEADER },
360 { ELM_ATSPI_ROLE_COMBO_BOX, ATSPI_ROLE_COMBO_BOX },
361 { ELM_ATSPI_ROLE_DATE_EDITOR, ATSPI_ROLE_DATE_EDITOR },
362 { ELM_ATSPI_ROLE_DESKTOP_ICON, ATSPI_ROLE_DESKTOP_ICON },
363 { ELM_ATSPI_ROLE_DESKTOP_FRAME, ATSPI_ROLE_DESKTOP_FRAME },
364 { ELM_ATSPI_ROLE_DIAL, ATSPI_ROLE_DIAL },
365 { ELM_ATSPI_ROLE_DIALOG, ATSPI_ROLE_DIALOG },
366 { ELM_ATSPI_ROLE_DIRECTORY_PANE, ATSPI_ROLE_DIRECTORY_PANE },
367 { ELM_ATSPI_ROLE_DRAWING_AREA, ATSPI_ROLE_DRAWING_AREA },
368 { ELM_ATSPI_ROLE_FILE_CHOOSER, ATSPI_ROLE_FILE_CHOOSER },
369 { ELM_ATSPI_ROLE_FILLER, ATSPI_ROLE_FILLER },
370 { ELM_ATSPI_ROLE_FOCUS_TRAVERSABLE, ATSPI_ROLE_FOCUS_TRAVERSABLE },
371 { ELM_ATSPI_ROLE_FONT_CHOOSER, ATSPI_ROLE_FONT_CHOOSER },
372 { ELM_ATSPI_ROLE_FRAME, ATSPI_ROLE_FRAME },
373 { ELM_ATSPI_ROLE_GLASS_PANE, ATSPI_ROLE_GLASS_PANE },
374 { ELM_ATSPI_ROLE_HTML_CONTAINER, ATSPI_ROLE_HTML_CONTAINER },
375 { ELM_ATSPI_ROLE_ICON, ATSPI_ROLE_ICON },
376 { ELM_ATSPI_ROLE_IMAGE, ATSPI_ROLE_IMAGE },
377 { ELM_ATSPI_ROLE_INTERNAL_FRAME, ATSPI_ROLE_INTERNAL_FRAME },
378 { ELM_ATSPI_ROLE_LABEL, ATSPI_ROLE_LABEL },
379 { ELM_ATSPI_ROLE_LAYERED_PANE, ATSPI_ROLE_LAYERED_PANE },
380 { ELM_ATSPI_ROLE_LIST, ATSPI_ROLE_LIST },
381 { ELM_ATSPI_ROLE_LIST_ITEM, ATSPI_ROLE_LIST_ITEM },
382 { ELM_ATSPI_ROLE_MENU, ATSPI_ROLE_MENU },
383 { ELM_ATSPI_ROLE_MENU_BAR, ATSPI_ROLE_MENU_BAR },
384 { ELM_ATSPI_ROLE_MENU_ITEM, ATSPI_ROLE_MENU_ITEM },
385 { ELM_ATSPI_ROLE_OPTION_PANE, ATSPI_ROLE_OPTION_PANE },
386 { ELM_ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_PAGE_TAB },
387 { ELM_ATSPI_ROLE_PAGE_TAB_LIST, ATSPI_ROLE_PAGE_TAB_LIST },
388 { ELM_ATSPI_ROLE_PANEL, ATSPI_ROLE_PANEL },
389 { ELM_ATSPI_ROLE_PASSWORD_TEXT, ATSPI_ROLE_PASSWORD_TEXT },
390 { ELM_ATSPI_ROLE_POPUP_MENU, ATSPI_ROLE_POPUP_MENU },
391 { ELM_ATSPI_ROLE_PROGRESS_BAR, ATSPI_ROLE_PROGRESS_BAR },
392 { ELM_ATSPI_ROLE_PUSH_BUTTON, ATSPI_ROLE_PUSH_BUTTON },
393 { ELM_ATSPI_ROLE_RADIO_BUTTON, ATSPI_ROLE_RADIO_BUTTON },
394 { ELM_ATSPI_ROLE_RADIO_MENU_ITEM, ATSPI_ROLE_RADIO_MENU_ITEM },
395 { ELM_ATSPI_ROLE_ROOT_PANE, ATSPI_ROLE_ROOT_PANE },
396 { ELM_ATSPI_ROLE_ROW_HEADER, ATSPI_ROLE_ROW_HEADER },
397 { ELM_ATSPI_ROLE_SCROLL_BAR, ATSPI_ROLE_SCROLL_BAR },
398 { ELM_ATSPI_ROLE_SCROLL_PANE, ATSPI_ROLE_SCROLL_PANE },
399 { ELM_ATSPI_ROLE_SEPARATOR, ATSPI_ROLE_SEPARATOR },
400 { ELM_ATSPI_ROLE_SLIDER, ATSPI_ROLE_SLIDER },
401 { ELM_ATSPI_ROLE_SPIN_BUTTON, ATSPI_ROLE_SPIN_BUTTON },
402 { ELM_ATSPI_ROLE_SPLIT_PANE, ATSPI_ROLE_SPLIT_PANE },
403 { ELM_ATSPI_ROLE_STATUS_BAR, ATSPI_ROLE_STATUS_BAR },
404 { ELM_ATSPI_ROLE_TABLE, ATSPI_ROLE_TABLE },
405 { ELM_ATSPI_ROLE_TABLE_CELL, ATSPI_ROLE_TABLE_CELL },
406 { ELM_ATSPI_ROLE_TABLE_COLUMN_HEADER, ATSPI_ROLE_TABLE_COLUMN_HEADER },
407 { ELM_ATSPI_ROLE_TABLE_ROW_HEADER, ATSPI_ROLE_TABLE_ROW_HEADER },
408 { ELM_ATSPI_ROLE_TEAROFF_MENU_ITEM, ATSPI_ROLE_TEAROFF_MENU_ITEM },
409 { ELM_ATSPI_ROLE_TERMINAL, ATSPI_ROLE_TERMINAL },
410 { ELM_ATSPI_ROLE_TEXT, ATSPI_ROLE_TEXT },
411 { ELM_ATSPI_ROLE_TOGGLE_BUTTON, ATSPI_ROLE_TOGGLE_BUTTON },
412 { ELM_ATSPI_ROLE_TOOL_BAR, ATSPI_ROLE_TOOL_BAR },
413 { ELM_ATSPI_ROLE_TOOL_TIP, ATSPI_ROLE_TOOL_TIP },
414 { ELM_ATSPI_ROLE_TREE, ATSPI_ROLE_TREE },
415 { ELM_ATSPI_ROLE_TREE_TABLE, ATSPI_ROLE_TREE_TABLE },
416 { ELM_ATSPI_ROLE_UNKNOWN, ATSPI_ROLE_UNKNOWN },
417 { ELM_ATSPI_ROLE_VIEWPORT, ATSPI_ROLE_VIEWPORT },
418 { ELM_ATSPI_ROLE_WINDOW, ATSPI_ROLE_WINDOW },
419 { ELM_ATSPI_ROLE_EXTENDED, ATSPI_ROLE_EXTENDED },
420 { ELM_ATSPI_ROLE_HEADER, ATSPI_ROLE_HEADER },
421 { ELM_ATSPI_ROLE_FOOTER, ATSPI_ROLE_FOOTER },
422 { ELM_ATSPI_ROLE_PARAGRAPH, ATSPI_ROLE_PARAGRAPH },
423 { ELM_ATSPI_ROLE_RULER, ATSPI_ROLE_RULER },
424 { ELM_ATSPI_ROLE_APPLICATION, ATSPI_ROLE_APPLICATION },
425 { ELM_ATSPI_ROLE_AUTOCOMPLETE, ATSPI_ROLE_AUTOCOMPLETE },
426 { ELM_ATSPI_ROLE_EDITBAR, ATSPI_ROLE_EDITBAR },
427 { ELM_ATSPI_ROLE_EMBEDDED, ATSPI_ROLE_EMBEDDED },
428 { ELM_ATSPI_ROLE_ENTRY, ATSPI_ROLE_ENTRY },
429 { ELM_ATSPI_ROLE_CHART, ATSPI_ROLE_CHART },
430 { ELM_ATSPI_ROLE_CAPTION, ATSPI_ROLE_CAPTION },
431 { ELM_ATSPI_ROLE_DOCUMENT_FRAME, ATSPI_ROLE_DOCUMENT_FRAME },
432 { ELM_ATSPI_ROLE_HEADING, ATSPI_ROLE_HEADING },
433 { ELM_ATSPI_ROLE_PAGE, ATSPI_ROLE_PAGE },
434 { ELM_ATSPI_ROLE_SECTION, ATSPI_ROLE_SECTION },
435 { ELM_ATSPI_ROLE_REDUNDANT_OBJECT, ATSPI_ROLE_REDUNDANT_OBJECT },
436 { ELM_ATSPI_ROLE_FORM, ATSPI_ROLE_FORM },
437 { ELM_ATSPI_ROLE_LINK, ATSPI_ROLE_LINK },
438 { ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW, ATSPI_ROLE_INPUT_METHOD_WINDOW },
439 { ELM_ATSPI_ROLE_TABLE_ROW, ATSPI_ROLE_TABLE_ROW },
440 { ELM_ATSPI_ROLE_TREE_ITEM, ATSPI_ROLE_TREE_ITEM },
441 { ELM_ATSPI_ROLE_DOCUMENT_SPREADSHEET, ATSPI_ROLE_DOCUMENT_SPREADSHEET },
442 { ELM_ATSPI_ROLE_DOCUMENT_PRESENTATION, ATSPI_ROLE_DOCUMENT_PRESENTATION },
443 { ELM_ATSPI_ROLE_DOCUMENT_TEXT, ATSPI_ROLE_DOCUMENT_TEXT },
444 { ELM_ATSPI_ROLE_DOCUMENT_WEB, ATSPI_ROLE_DOCUMENT_WEB },
445 { ELM_ATSPI_ROLE_DOCUMENT_EMAIL, ATSPI_ROLE_DOCUMENT_EMAIL },
446 { ELM_ATSPI_ROLE_COMMENT, ATSPI_ROLE_COMMENT },
447 { ELM_ATSPI_ROLE_LIST_BOX, ATSPI_ROLE_LIST_BOX },
448 { ELM_ATSPI_ROLE_GROUPING, ATSPI_ROLE_GROUPING },
449 { ELM_ATSPI_ROLE_IMAGE_MAP, ATSPI_ROLE_IMAGE_MAP },
450 { ELM_ATSPI_ROLE_NOTIFICATION, ATSPI_ROLE_NOTIFICATION },
451 { ELM_ATSPI_ROLE_INFO_BAR, ATSPI_ROLE_INFO_BAR },
452 { ELM_ATSPI_ROLE_LAST_DEFINED, ATSPI_ROLE_LAST_DEFINED },
455 struct atspi_state_desc
457 Elm_Atspi_State_Type elm_state;
458 AtspiStateType atspi_state;
462 const struct atspi_state_desc elm_states_to_atspi_state[] = {
463 { ELM_ATSPI_STATE_INVALID, ATSPI_STATE_INVALID, "invalid" },
464 { ELM_ATSPI_STATE_ACTIVE, ATSPI_STATE_ACTIVE, "active" },
465 { ELM_ATSPI_STATE_ARMED, ATSPI_STATE_ARMED, "armed" },
466 { ELM_ATSPI_STATE_BUSY, ATSPI_STATE_BUSY, "busy" },
467 { ELM_ATSPI_STATE_CHECKED, ATSPI_STATE_CHECKED, "checked" },
468 { ELM_ATSPI_STATE_COLLAPSED, ATSPI_STATE_COLLAPSED, "collapsed" },
469 { ELM_ATSPI_STATE_DEFUNCT, ATSPI_STATE_DEFUNCT, "defunct" },
470 { ELM_ATSPI_STATE_EDITABLE, ATSPI_STATE_EDITABLE, "editable" },
471 { ELM_ATSPI_STATE_ENABLED, ATSPI_STATE_ENABLED, "enabled" },
472 { ELM_ATSPI_STATE_EXPANDABLE, ATSPI_STATE_EXPANDABLE, "expandable" },
473 { ELM_ATSPI_STATE_EXPANDED, ATSPI_STATE_EXPANDED, "expanded" },
474 { ELM_ATSPI_STATE_FOCUSABLE, ATSPI_STATE_FOCUSABLE, "focusable" },
475 { ELM_ATSPI_STATE_FOCUSED, ATSPI_STATE_FOCUSED, "focused" },
476 { ELM_ATSPI_STATE_HAS_TOOLTIP, ATSPI_STATE_HAS_TOOLTIP, "has-tooltip" },
477 { ELM_ATSPI_STATE_HORIZONTAL, ATSPI_STATE_HORIZONTAL, "horizontal" },
478 { ELM_ATSPI_STATE_ICONIFIED, ATSPI_STATE_ICONIFIED, "iconified" },
479 { ELM_ATSPI_STATE_MODAL, ATSPI_STATE_MODAL, "modal" },
480 { ELM_ATSPI_STATE_MULTI_LINE, ATSPI_STATE_MULTI_LINE, "multi-line" },
481 { ELM_ATSPI_STATE_MULTISELECTABLE, ATSPI_STATE_MULTISELECTABLE, "multiselectable" },
482 { ELM_ATSPI_STATE_OPAQUE, ATSPI_STATE_OPAQUE, "opaque" },
483 { ELM_ATSPI_STATE_PRESSED, ATSPI_STATE_PRESSED, "pressed" },
484 { ELM_ATSPI_STATE_RESIZABLE, ATSPI_STATE_RESIZABLE, "resizable" },
485 { ELM_ATSPI_STATE_SELECTABLE, ATSPI_STATE_SELECTABLE, "selectable" },
486 { ELM_ATSPI_STATE_SELECTED, ATSPI_STATE_SELECTED, "selected" },
487 { ELM_ATSPI_STATE_SENSITIVE, ATSPI_STATE_SENSITIVE, "sensitive" },
488 { ELM_ATSPI_STATE_SHOWING, ATSPI_STATE_SHOWING, "showing" },
489 { ELM_ATSPI_STATE_SINGLE_LINE, ATSPI_STATE_SINGLE_LINE, "single-line" },
490 { ELM_ATSPI_STATE_STALE, ATSPI_STATE_STALE, "stale" },
491 { ELM_ATSPI_STATE_TRANSIENT, ATSPI_STATE_TRANSIENT, "transient" },
492 { ELM_ATSPI_STATE_VERTICAL, ATSPI_STATE_VERTICAL, "vertical" },
493 { ELM_ATSPI_STATE_VISIBLE, ATSPI_STATE_VISIBLE, "visible" },
494 { ELM_ATSPI_STATE_MANAGES_DESCENDANTS, ATSPI_STATE_MANAGES_DESCENDANTS, "manages-descendants" },
495 { ELM_ATSPI_STATE_INDETERMINATE, ATSPI_STATE_INDETERMINATE, "indeterminate" },
496 { ELM_ATSPI_STATE_REQUIRED, ATSPI_STATE_REQUIRED, "required" },
497 { ELM_ATSPI_STATE_TRUNCATED, ATSPI_STATE_TRUNCATED, "truncated" },
498 { ELM_ATSPI_STATE_ANIMATED, ATSPI_STATE_ANIMATED, "animated" },
499 { ELM_ATSPI_STATE_INVALID_ENTRY, ATSPI_STATE_INVALID_ENTRY, "invalid-entry" },
500 { ELM_ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, "supports-autocompletion" },
501 { ELM_ATSPI_STATE_SELECTABLE_TEXT, ATSPI_STATE_SELECTABLE_TEXT, "selectable-text" },
502 { ELM_ATSPI_STATE_IS_DEFAULT, ATSPI_STATE_IS_DEFAULT, "is-default" },
503 { ELM_ATSPI_STATE_VISITED, ATSPI_STATE_VISITED, "visited" },
504 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
505 { ELM_ATSPI_STATE_CHECKABLE, ATSPI_STATE_CHECKABLE, "checkable" },
506 { ELM_ATSPI_STATE_HAS_POPUP, ATSPI_STATE_HAS_POPUP, "has-popup" },
507 { ELM_ATSPI_STATE_READ_ONLY, ATSPI_STATE_READ_ONLY, "read-only" },
508 { ELM_ATSPI_STATE_HIGHLIGHTED, ATSPI_STATE_HIGHLIGHTED, "highlighted" },
509 { ELM_ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_HIGHLIGHTABLE, "highlightable" },
511 { ELM_ATSPI_STATE_LAST_DEFINED, ATSPI_STATE_LAST_DEFINED, "last-defined" }
514 const int elm_relation_to_atspi_relation_mapping[] = {
515 [ELM_ATSPI_RELATION_NULL] = ATSPI_RELATION_NULL,
516 [ELM_ATSPI_RELATION_LABEL_FOR] = ATSPI_RELATION_LABEL_FOR,
517 [ELM_ATSPI_RELATION_LABELLED_BY] = ATSPI_RELATION_LABELLED_BY,
518 [ELM_ATSPI_RELATION_CONTROLLER_FOR] = ATSPI_RELATION_CONTROLLER_FOR,
519 [ELM_ATSPI_RELATION_CONTROLLED_BY] = ATSPI_RELATION_CONTROLLED_BY,
520 [ELM_ATSPI_RELATION_MEMBER_OF] = ATSPI_RELATION_MEMBER_OF,
521 [ELM_ATSPI_RELATION_TOOLTIP_FOR] = ATSPI_RELATION_TOOLTIP_FOR,
522 [ELM_ATSPI_RELATION_NODE_CHILD_OF] = ATSPI_RELATION_NODE_CHILD_OF,
523 [ELM_ATSPI_RELATION_NODE_PARENT_OF] = ATSPI_RELATION_NODE_PARENT_OF,
524 [ELM_ATSPI_RELATION_EXTENDED] = ATSPI_RELATION_EXTENDED,
525 [ELM_ATSPI_RELATION_FLOWS_TO] = ATSPI_RELATION_FLOWS_TO,
526 [ELM_ATSPI_RELATION_FLOWS_FROM] = ATSPI_RELATION_FLOWS_FROM,
527 [ELM_ATSPI_RELATION_SUBWINDOW_OF] = ATSPI_RELATION_SUBWINDOW_OF,
528 [ELM_ATSPI_RELATION_EMBEDS] = ATSPI_RELATION_EMBEDS,
529 [ELM_ATSPI_RELATION_EMBEDDED_BY] = ATSPI_RELATION_EMBEDDED_BY,
530 [ELM_ATSPI_RELATION_POPUP_FOR] = ATSPI_RELATION_POPUP_FOR,
531 [ELM_ATSPI_RELATION_PARENT_WINDOW_OF] = ATSPI_RELATION_PARENT_WINDOW_OF,
532 [ELM_ATSPI_RELATION_DESCRIPTION_FOR] = ATSPI_RELATION_DESCRIPTION_FOR,
533 [ELM_ATSPI_RELATION_DESCRIBED_BY] = ATSPI_RELATION_DESCRIBED_BY,
534 [ELM_ATSPI_RELATION_LAST_DEFINED] = ATSPI_RELATION_LAST_DEFINED,
537 static inline Eldbus_Message *_dbus_invalid_ref_error_new(const Eldbus_Message *msg)
539 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.UnknownObject", "Path is not valid accessible object reference.");
542 static AtspiRelationType _elm_relation_to_atspi_relation(Elm_Atspi_Relation_Type type)
544 if ((type < ELM_ATSPI_RELATION_LAST_DEFINED) && (type > ELM_ATSPI_RELATION_NULL))
545 return elm_relation_to_atspi_relation_mapping[type];
546 return ATSPI_RELATION_NULL;
549 static Elm_Atspi_Relation_Type _atspi_relation_to_elm_relation(AtspiRelationType type)
552 for(i = 0; i < sizeof(elm_relation_to_atspi_relation_mapping) / sizeof(elm_relation_to_atspi_relation_mapping[0]); ++i)
554 if (elm_relation_to_atspi_relation_mapping[i] == (int)type) return (Elm_Atspi_Relation_Type)i;
556 return ELM_ATSPI_RELATION_NULL;
559 static AtspiRole _elm_role_to_atspi_role(Elm_Atspi_Role role)
561 return role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
564 static Eldbus_Message *
565 _accessible_get_role(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
567 const char *obj_path = eldbus_message_path_get(msg);
568 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
569 Eo *obj = _bridge_object_from_path(bridge, obj_path);
572 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
574 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
576 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
577 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
579 AtspiRole atspi_role = _elm_role_to_atspi_role(role);
580 eldbus_message_arguments_append(ret, "u", atspi_role);
584 static Eldbus_Message *
585 _accessible_get_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
587 const char *role_name = NULL, *obj_path = eldbus_message_path_get(msg);
588 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
589 Eo *obj = _bridge_object_from_path(bridge, obj_path);
591 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
593 eo_do(obj, role_name = elm_interface_atspi_accessible_role_name_get());
595 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
596 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
597 eldbus_message_arguments_append(ret, "s", role_name);
602 static Eldbus_Message *
603 _accessible_get_localized_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
605 const char *l_role_name = NULL, *obj_path = eldbus_message_path_get(msg);
606 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
607 Eo *obj = _bridge_object_from_path(bridge, obj_path);
609 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
611 eo_do(obj, l_role_name = elm_interface_atspi_accessible_localized_role_name_get());
612 EINA_SAFETY_ON_NULL_RETURN_VAL(l_role_name, NULL);
614 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
615 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
616 eldbus_message_arguments_append(ret, "s", l_role_name);
621 static Eldbus_Message *
622 _accessible_get_children(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
624 const char *obj_path = eldbus_message_path_get(msg);
625 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
626 Eo *obj = _bridge_object_from_path(bridge, obj_path);
627 Eina_List *children_list = NULL, *l;
629 Eldbus_Message_Iter *iter, *iter_array;
632 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
634 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
636 ret = eldbus_message_method_return_new(msg);
637 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
639 iter = eldbus_message_iter_get(ret);
640 iter_array = eldbus_message_iter_container_new(iter, 'a', "(so)");
641 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
643 EINA_LIST_FOREACH(children_list, l, children)
645 _bridge_iter_object_reference_append(bridge, iter_array, children);
646 _bridge_object_register(bridge, children);
649 eldbus_message_iter_container_close(iter, iter_array);
650 eina_list_free(children_list);
655 if (ret) eldbus_message_unref(ret);
659 static Eldbus_Message *
660 _accessible_get_application(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
663 const char *obj_path = eldbus_message_path_get(msg);
664 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
665 Eo *obj = _bridge_object_from_path(bridge, obj_path);
667 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
669 ret = eldbus_message_method_return_new(msg);
670 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
672 Eldbus_Message_Iter *iter = eldbus_message_iter_get(ret);
673 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
678 static Eldbus_Message *
679 _accessible_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
681 Eina_List *attrs, *l;
682 Elm_Atspi_Attribute *attr;
683 Eldbus_Message_Iter *iter, *iter_dict, *iter_entry;
686 const char *obj_path = eldbus_message_path_get(msg);
687 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
688 Eo *obj = _bridge_object_from_path(bridge, obj_path);
690 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
692 ret = eldbus_message_method_return_new(msg);
693 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
695 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
697 iter = eldbus_message_iter_get(ret);
698 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
699 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
701 EINA_LIST_FOREACH(attrs, l, attr)
703 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
704 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
705 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
706 eldbus_message_iter_container_close(iter_dict, iter_entry);
709 eldbus_message_iter_container_close(iter, iter_dict);
710 elm_atspi_attributes_list_free(attrs);
715 static Eldbus_Message *
716 _accessible_interfaces_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
719 Eldbus_Message_Iter *iter;
720 const char *obj_path = eldbus_message_path_get(msg);
721 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
722 Eo *obj = _bridge_object_from_path(bridge, obj_path);
724 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
726 ret = eldbus_message_method_return_new(msg);
727 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
729 iter = eldbus_message_iter_get(ret);
730 _iter_interfaces_append(iter, obj);
736 _elm_atspi_state_set_to_atspi_state_set(Elm_Atspi_State_Set states)
741 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
743 if (STATE_TYPE_GET(states, elm_states_to_atspi_state[i].elm_state))
744 STATE_TYPE_SET(ret, elm_states_to_atspi_state[i].atspi_state);
749 static Elm_Atspi_State_Set
750 _atspi_state_set_to_elm_atspi_state_set(uint64_t states)
752 //Currently Elm_Atspi_State and Atspi_State_Set are binary compatible,
753 //implement proper coversion when it will be needed.
754 Elm_Atspi_State_Set ret = states;
759 _elm_atspi_state_hash_build(void)
761 Eina_Hash *ret = eina_hash_string_superfast_new(NULL);
764 for (i = 0; i < SIZE(elm_states_to_atspi_state); i++)
765 eina_hash_add(ret, elm_states_to_atspi_state[i].name, &elm_states_to_atspi_state[i]);
771 _elm_atspi_event_hash_build(void)
773 Eina_Hash *ret = eina_hash_pointer_new(NULL);
776 for (i = 0; i < SIZE(event_handlers); i++)
777 eina_hash_add(ret, &(event_handlers[i].desc), event_handlers[i].callback);
782 static Eldbus_Message *
783 _accessible_get_state(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
786 Eldbus_Message_Iter *iter, *iter_array;
787 Elm_Atspi_State_Set states;
788 uint64_t atspi_states = 0;
790 const char *obj_path = eldbus_message_path_get(msg);
791 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
792 Eo *obj = _bridge_object_from_path(bridge, obj_path);
794 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
796 ret = eldbus_message_method_return_new(msg);
797 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
799 iter = eldbus_message_iter_get(ret);
800 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
801 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
803 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
805 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
807 unsigned int s1 = atspi_states & 0xFFFFFFFF;
808 unsigned int s2 = (atspi_states >> 32) & 0xFFFFFFFF;
810 eldbus_message_iter_basic_append(iter_array, 'u', s1);
811 eldbus_message_iter_basic_append(iter_array, 'u', s2);
812 eldbus_message_iter_container_close(iter, iter_array);
817 if (ret) eldbus_message_unref(ret);
821 static Eldbus_Message *
822 _accessible_get_index_in_parent(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
824 const char *obj_path = eldbus_message_path_get(msg);
825 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
826 Eo *obj = _bridge_object_from_path(bridge, obj_path);
830 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
832 ret = eldbus_message_method_return_new(msg);
833 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
835 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
837 eldbus_message_arguments_append(ret, "i", idx);
842 static Eldbus_Message *
843 _accessible_child_at_index(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
845 const char *obj_path = eldbus_message_path_get(msg);
846 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
847 Eo *obj = _bridge_object_from_path(bridge, obj_path);
849 Eina_List *children = NULL;
852 Eldbus_Message_Iter *iter;
854 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
856 if (!eldbus_message_arguments_get(msg, "i", &idx))
857 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
859 ret = eldbus_message_method_return_new(msg);
860 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
862 iter = eldbus_message_iter_get(ret);
863 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
865 child = eina_list_nth(children, idx);
866 _bridge_iter_object_reference_append(bridge, iter, child);
867 _bridge_object_register(bridge, child);
868 eina_list_free(children);
873 static Eldbus_Message *
874 _accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
876 const char *obj_path = eldbus_message_path_get(msg);
877 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
878 Eo *rel_obj, *obj = _bridge_object_from_path(bridge, obj_path);
879 Eldbus_Message *ret = NULL;
880 Eldbus_Message_Iter *iter = NULL, *iter_array = NULL, *iter_array2 = NULL, *iter_struct;
881 Elm_Atspi_Relation *rel;
883 Elm_Atspi_Relation_Set rels;
885 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
887 ret = eldbus_message_method_return_new(msg);
888 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
890 iter = eldbus_message_iter_get(ret);
891 iter_array = eldbus_message_iter_container_new(iter, 'a', "(ua(so))");
892 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
894 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
896 EINA_LIST_FOREACH(rels, l, rel)
898 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
899 eldbus_message_iter_basic_append(iter_struct, 'u', _elm_relation_to_atspi_relation(rel->type));
900 iter_array2 = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
901 EINA_SAFETY_ON_NULL_GOTO(iter_array2, fail);
902 EINA_LIST_FOREACH(rel->objects, l2, rel_obj)
904 _bridge_iter_object_reference_append(bridge, iter_array2, rel_obj);
905 _bridge_object_register(bridge, rel_obj);
907 eldbus_message_iter_container_close(iter_struct, iter_array2);
908 eldbus_message_iter_container_close(iter_array, iter_struct);
910 elm_atspi_relation_set_free(&rels);
911 eldbus_message_iter_container_close(iter, iter_array);
916 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get relation set.");
919 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
920 static Eldbus_Message *
921 _accessible_gesture_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
923 const char *obj_path = eldbus_message_path_get(msg);
924 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
925 Eo *obj = _bridge_object_from_path(bridge, obj_path);
926 int type, x_beg, y_beg, x_end, y_end, state;
927 unsigned int event_time;
929 Eina_Bool result = EINA_FALSE;
931 if (!eldbus_message_arguments_get(msg, "iiiiiiu", &type, &x_beg, &y_beg,
932 &x_end, &y_end, &state, &event_time))
933 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
935 ret = eldbus_message_method_return_new(msg);
936 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
938 Elm_Atspi_Gesture_Info gesture_info;
939 gesture_info.type = (Elm_Atspi_Gesture_Type)type;
940 gesture_info.x_beg = x_beg;
941 gesture_info.y_beg = y_beg;
942 gesture_info.x_end = x_end;
943 gesture_info.y_end = y_end;
944 gesture_info.state = (Elm_Atspi_Gesture_State)state;
945 gesture_info.event_time = event_time;
946 eo_do(obj, result = elm_interface_atspi_accessible_gesture_do(gesture_info));
947 eldbus_message_arguments_append(ret, "b", result);
953 _ee_obscured_get(Eo *obj)
955 const Ecore_Evas *ee;
956 if (eo_isa(obj, ELM_WIDGET_ITEM_CLASS))
958 Elm_Widget_Item_Data *id = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
959 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(id->view));
963 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
966 return ecore_evas_obscured_get(ee);
969 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
970 static Eldbus_Message *
971 _accessible_get_neighbor(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
973 const char *start_path = eldbus_message_path_get(msg);
974 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
975 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
976 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
978 Eo *start = _bridge_object_from_path(bridge, start_path);
980 Eldbus_Message_Iter *iter;
981 int direction, search_mode;
983 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(start, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
985 char *root_path = "";
986 if (!eldbus_message_arguments_get(msg, "sii", &root_path, &direction, &search_mode))
987 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
989 Eo *root = _bridge_object_from_path(bridge, root_path);
991 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
994 if (_ee_obscured_get(root))
995 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
999 ret = eldbus_message_method_return_new(msg);
1000 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1002 iter = eldbus_message_iter_get(ret);
1004 Eo *accessible = _calculate_neighbor(bridge, root, start, direction == 1, search_mode);
1005 _bridge_iter_object_reference_append(bridge, iter, accessible);
1006 _bridge_object_register(bridge, accessible);
1008 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
1009 _object_get_bus_name_and_path(bridge, start, &obj_bus_name, NULL);
1010 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
1012 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
1013 eldbus_message_iter_basic_append(iter, 'y', recurse);
1017 static Eldbus_Message *
1018 _accessible_get_navigable_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1020 const char *obj_path = eldbus_message_path_get(msg);
1021 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1022 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
1023 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
1025 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1027 Eldbus_Message *ret;
1028 AtspiCoordType coord_type;
1029 Eldbus_Message_Iter *iter;
1031 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1033 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
1034 if (_ee_obscured_get(obj))
1035 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
1038 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
1039 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1041 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
1042 Evas_Object *top = elm_object_top_widget_get(obj);
1045 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
1050 ret = eldbus_message_method_return_new(msg);
1051 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1053 iter = eldbus_message_iter_get(ret);
1055 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1056 Eo *accessible = _calculate_navigable_accessible_at_point(bridge, obj, type, x, y);
1060 if (accessible && eo_isa(accessible, ELM_ACCESS_CLASS))
1062 Evas_Object *parent = elm_widget_parent_get(accessible);
1064 Elm_Widget_Smart_Data *wd;
1065 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
1069 Evas_Object *widget;
1071 EINA_LIST_FOREACH(wd->subobjs, l, widget)
1075 proxy = evas_object_data_get(widget, "__widget_proxy");
1079 evas_object_geometry_get(widget, &px, &py, &pw, &ph);
1080 if (x >= px && x <= px + pw && y >= py && y <= py +ph)
1082 /* proxy is also selectable */
1083 deputy = accessible;
1092 _bridge_iter_object_reference_append(bridge, iter, accessible);
1093 _bridge_object_register(bridge, accessible);
1095 const char *obj_bus_name = NULL, *ret_bus_name = NULL;
1096 _object_get_bus_name_and_path(bridge, obj, &obj_bus_name, NULL);
1097 if (accessible) _object_get_bus_name_and_path(bridge, accessible, &ret_bus_name, NULL);
1098 unsigned char recurse = obj_bus_name && ret_bus_name && strcmp(obj_bus_name, ret_bus_name) != 0;
1099 eldbus_message_iter_basic_append(iter, 'y', recurse);
1102 _bridge_iter_object_reference_append(bridge, iter, deputy);
1103 if (deputy) _bridge_object_register(bridge, deputy);
1109 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1111 _list_children_count_check(Eo *obj)
1115 Eina_List *children;
1117 Elm_Atspi_Role role;
1122 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1123 if (role == ELM_ATSPI_ROLE_LIST)
1125 int children_count = 0;
1126 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1127 children_count = eina_list_count(children);
1129 for (i = 0; i < children_count; i++)
1131 child = eina_list_nth(children, i);
1132 eo_do(child, role = elm_interface_atspi_accessible_role_get());
1133 if (role == ELM_ATSPI_ROLE_LIST_ITEM)
1136 eina_list_free(children);
1143 _list_children_count(Eo *obj)
1145 Eina_List *children;
1146 int list_items_count = 0;
1147 int children_count = 0;
1149 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1150 children_count = eina_list_count(children);
1155 list_items_count = _list_children_count_check(obj);
1156 if (list_items_count > 0)
1158 eina_list_free(children);
1159 return list_items_count;
1162 for (i = 0; i < children_count; i++)
1164 child = eina_list_nth(children, i);
1165 list_items_count = _list_children_count(child);
1166 if (list_items_count > 0)
1168 eina_list_free(children);
1169 return list_items_count;
1176 static Eldbus_Message *
1177 _accessible_reading_material_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1179 Eldbus_Message *ret;
1180 Eldbus_Message_Iter *iter, *iter_array, *iter_dict, *iter_entry;
1181 Eina_List *attrs, *l, *children;
1182 const char *name = NULL;
1183 unsigned int s1, s2;
1185 double increment = 0;
1186 double max_value = 0;
1187 double min_value = 0;
1189 int child_count = 0;
1190 int selected_child_count = 0;
1191 uint64_t atspi_states = 0;
1192 Elm_Atspi_Role role;
1193 Elm_Atspi_Attribute *attr;
1194 Elm_Atspi_State_Set states;
1195 Elm_Atspi_Relation_Set rels = NULL;
1196 Elm_Atspi_Relation *rel;
1197 Eo *relation_obj = NULL;
1200 Eina_Bool is_selected = EINA_FALSE;
1201 AtspiRole atspi_role = ATSPI_ROLE_INVALID;
1203 const char *obj_path = eldbus_message_path_get(msg);
1204 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1205 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1207 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1209 ret = eldbus_message_method_return_new(msg);
1210 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1212 iter = eldbus_message_iter_get(ret);
1214 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
1215 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
1216 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
1217 EINA_LIST_FOREACH(attrs, l, attr)
1219 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
1220 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
1221 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
1222 eldbus_message_iter_container_close(iter_dict, iter_entry);
1225 eldbus_message_iter_container_close(iter, iter_dict);
1226 elm_atspi_attributes_list_free(attrs);
1229 eo_do(obj, name = elm_interface_atspi_accessible_name_get());
1232 eldbus_message_iter_basic_append(iter, 's', name);
1234 /* name - LABELED_BY relation */
1235 eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get());
1236 EINA_LIST_FOREACH(rels, l, rel)
1238 if (rel->type == ELM_ATSPI_RELATION_LABELLED_BY)
1240 int last_index = eina_list_count(rel->objects) - 1;
1241 relation_obj = eina_list_nth(rel->objects, last_index);
1245 eo_do(relation_obj, name = elm_interface_atspi_accessible_name_get());
1248 eldbus_message_iter_basic_append(iter, 's', name);
1250 /* name - text interface */
1252 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
1255 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
1256 eo_do(obj, name = elm_interface_atspi_text_get(0, val));
1260 eldbus_message_iter_basic_append(iter, 's', name);
1263 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1264 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1265 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1268 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1269 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1270 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1271 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1272 s1 = atspi_states & 0xFFFFFFFF;
1273 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1274 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1275 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1276 eldbus_message_iter_container_close(iter, iter_array);
1278 /* localized role name */
1279 eo_do(obj, name = elm_interface_atspi_accessible_localized_role_name_get());
1282 eldbus_message_iter_basic_append(iter, 's', name);
1285 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
1286 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1289 /* current value, increment, max, min */
1294 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
1296 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
1297 eo_do(obj, increment = elm_interface_atspi_value_increment_get());
1298 eo_do(obj, elm_interface_atspi_value_range_get(&min_value, &max_value, NULL));
1300 eldbus_message_iter_basic_append(iter, 'd', value);
1301 eldbus_message_iter_basic_append(iter, 'd', increment);
1302 eldbus_message_iter_basic_append(iter, 'd', max_value);
1303 eldbus_message_iter_basic_append(iter, 'd', min_value);
1306 eo_do(obj, name = elm_interface_atspi_accessible_description_get());
1309 eldbus_message_iter_basic_append(iter, 's', name);
1311 /* index in parent */
1312 eo_do(obj, idx = elm_interface_atspi_accessible_index_in_parent_get());
1313 eldbus_message_iter_basic_append(iter, 'i', idx);
1315 /* is selected in parent */
1316 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
1317 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1319 eo_do(parent, is_selected = elm_interface_atspi_selection_is_child_selected(idx));
1321 eldbus_message_arguments_append(ret, "b", is_selected);
1323 /* has checkbox child */
1324 is_selected = EINA_FALSE;
1325 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1326 EINA_LIST_FOREACH(children, l, child)
1328 if (eo_isa(child, ELM_CHECK_CLASS))
1330 is_selected = EINA_TRUE;
1334 eldbus_message_iter_basic_append(iter, 'b', is_selected);
1335 eina_list_free(children);
1337 /* list children count */
1339 if (role == ELM_ATSPI_ROLE_DIALOG)
1341 child_count = _list_children_count(obj);
1343 eldbus_message_iter_basic_append(iter, 'i', child_count);
1345 /* first selected child index */
1347 if (eo_isa(obj, ELM_INDEX_CLASS))
1349 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
1350 EINA_LIST_FOREACH(children, l, child)
1352 eo_do(child, states = elm_interface_atspi_accessible_state_set_get());
1353 if (STATE_TYPE_GET(states, ELM_ATSPI_STATE_SELECTED))
1357 eina_list_free(children);
1359 eldbus_message_iter_basic_append(iter, 'i', idx);
1362 role = ELM_ATSPI_ROLE_INVALID;
1363 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
1364 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
1365 _object_desktop_reference_append(iter);
1367 _bridge_iter_object_reference_append(bridge, iter, parent);
1369 /* parent - states */
1370 iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
1371 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
1372 eo_do(parent, states = elm_interface_atspi_accessible_state_set_get());
1373 atspi_states = _elm_atspi_state_set_to_atspi_state_set(states);
1374 s1 = atspi_states & 0xFFFFFFFF;
1375 s2 = (atspi_states >> 32) & 0xFFFFFFFF;
1376 eldbus_message_iter_basic_append(iter_array, 'u', s1);
1377 eldbus_message_iter_basic_append(iter_array, 'u', s2);
1378 eldbus_message_iter_container_close(iter, iter_array);
1380 /* parent - child count */
1381 eo_do(parent, l = elm_interface_atspi_accessible_children_get());
1382 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
1386 eo_do(parent, role = elm_interface_atspi_accessible_role_get());
1387 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1388 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1390 /* parent - child count */
1391 if (eo_isa(parent, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
1393 eo_do(parent, selected_child_count = elm_interface_atspi_selection_selected_children_count_get());
1395 eldbus_message_iter_basic_append(iter, 'i', selected_child_count);
1397 /* relation object - DESCRIBED_BY */
1398 relation_obj = NULL;
1399 EINA_LIST_FOREACH(rels, l, rel)
1401 if (rel->type == ELM_ATSPI_RELATION_DESCRIBED_BY)
1403 int last_index = eina_list_count(rel->objects) - 1;
1404 relation_obj = eina_list_nth(rel->objects, last_index);
1408 _bridge_iter_object_reference_append(bridge, iter, relation_obj);
1409 elm_atspi_relation_set_free(&rels);
1414 if (rels) elm_atspi_relation_set_free(&rels);
1415 if (ret) eldbus_message_unref(ret);
1419 //TIZEN_ONLY(20170919): Handle default label object
1420 static Eldbus_Message *
1421 _accessible_default_label_info_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1423 Eldbus_Message *ret;
1424 Eldbus_Message_Iter *iter, *iter_dict, *iter_entry;
1425 const char *obj_path = eldbus_message_path_get(msg);
1426 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1427 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1428 Eo *default_label_obj;
1429 Elm_Atspi_Role role;
1430 AtspiRole atspi_role = ATSPI_ROLE_INVALID;
1431 Eina_List *attrs, *l;
1432 Elm_Atspi_Attribute *attr;
1434 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
1436 ret = eldbus_message_method_return_new(msg);
1437 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1439 iter = eldbus_message_iter_get(ret);
1441 default_label_obj = _elm_win_default_label_obj_get(obj);
1442 if (!default_label_obj) default_label_obj = obj;
1443 _bridge_iter_object_reference_append(bridge, iter, default_label_obj);
1444 _bridge_object_register(bridge, default_label_obj);
1446 eo_do(default_label_obj, role = elm_interface_atspi_accessible_role_get());
1447 atspi_role = role > ELM_ATSPI_ROLE_LAST_DEFINED ? ATSPI_ROLE_LAST_DEFINED : elm_roles_to_atspi_roles[role][1];
1448 eldbus_message_iter_basic_append(iter, 'u', atspi_role);
1450 eo_do(default_label_obj, attrs = elm_interface_atspi_accessible_attributes_get());
1451 iter_dict = eldbus_message_iter_container_new(iter, 'a', "{ss}");
1452 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_dict, NULL);
1454 EINA_LIST_FOREACH(attrs, l, attr)
1456 iter_entry = eldbus_message_iter_container_new(iter_dict, 'e', NULL);
1457 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_entry, NULL);
1458 eldbus_message_iter_arguments_append(iter_entry, "ss", attr->key, attr->value);
1459 eldbus_message_iter_container_close(iter_dict, iter_entry);
1462 eldbus_message_iter_container_close(iter, iter_dict);
1463 elm_atspi_attributes_list_free(attrs);
1469 static const Eldbus_Method accessible_methods[] = {
1470 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
1471 { "GetNavigableAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)y", "accessible"}, {"(so)", "deputy"}), _accessible_get_navigable_at_point, 0 },
1472 { "GetNeighbor", ELDBUS_ARGS({"s", "current"}, {"i", "direction"}, {"i", "force_next"}), ELDBUS_ARGS({"(so)y", "accessible"}), _accessible_get_neighbor, 0 },
1474 { "GetChildAtIndex", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"(so)", "Accessible"}), _accessible_child_at_index, 0 },
1475 { "GetChildren", NULL, ELDBUS_ARGS({"a(so)", "children"}), _accessible_get_children, 0 },
1476 { "GetIndexInParent", NULL, ELDBUS_ARGS({"i", "index"}), _accessible_get_index_in_parent, 0 },
1477 { "GetRelationSet", NULL, ELDBUS_ARGS({"a(ua(so))", NULL}), _accessible_get_relation_set, 0 },
1478 { "GetRole", NULL, ELDBUS_ARGS({"u", "Role"}), _accessible_get_role, 0 },
1479 { "GetRoleName", NULL, ELDBUS_ARGS({"s", "Name"}), _accessible_get_role_name, 0 },
1480 { "GetLocalizedRoleName", NULL, ELDBUS_ARGS({"s", "LocalizedName"}), _accessible_get_localized_role_name, 0},
1481 { "GetState", NULL, ELDBUS_ARGS({"au", NULL}), _accessible_get_state, 0},
1482 { "GetApplication", NULL, ELDBUS_ARGS({"(so)", NULL}), _accessible_get_application, 0},
1483 { "GetAttributes", NULL, ELDBUS_ARGS({"a{ss}", NULL}), _accessible_attributes_get, 0},
1484 { "GetInterfaces", NULL, ELDBUS_ARGS({"as", NULL}), _accessible_interfaces_get, 0},
1485 //TIZEN_ONLY(20170405) Add gesture method to accessible interface
1487 ELDBUS_ARGS({"i", "type"}, {"i", "x_beg"}, {"i", "y_beg"},
1488 {"i", "x_end"}, {"i", "y_end"}, {"i", "state"},
1489 {"u", "event_time"}),
1490 ELDBUS_ARGS({"b", "result"}), _accessible_gesture_do, 0},
1492 //TIZEN_ONLY(20170531): add "GetReadingMaterial" interface method
1493 { "GetReadingMaterial",
1495 ELDBUS_ARGS({"a{ss}", "attributes"}, {"s", "name"},
1496 {"s", "labledByName"},{"s", "textIfceName"},
1497 {"u", "role"}, {"au", "stateSet"},
1498 {"s", "localizedName"}, {"i", "childCount"},
1499 {"d", "currentValue"},{"d", "minimumIncrement"},
1500 {"d", "maximumValue"},{"d", "minimumValue"},
1501 {"s", "description"}, {"i", "indexInParent"},
1502 {"b", "isSelectedInParent"}, {"b", "hasCheckboxChild"},
1503 {"i", "listChildrenCount"},
1504 {"i", "firstSelectedChildIndex"},
1505 {"(so)", "parent"}, {"au", "parentStateSet"},
1506 {"i", "parentChildCount"}, {"u", "parentRole"},
1507 {"i", "selectedChildCount"},
1508 {"(so)", "describecByObject"}),
1509 _accessible_reading_material_get, 0},
1511 //TIZEN_ONLY(20170919): Handle default label object
1512 { "GetDefaultLabelInfo",
1513 NULL, ELDBUS_ARGS({"(so)", "defaultLabelObject"}, {"u", "defaultLabelRole"},{"a{ss}", "attributes"}),
1514 _accessible_default_label_info_get, 0},
1516 { NULL, NULL, NULL, NULL, 0 }
1520 _is_operation_permitted(Eo *obj)
1522 Elm_Atspi_State_Set states;
1523 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
1525 if (!STATE_TYPE_GET(states, ELM_ATSPI_STATE_SHOWING)) return EINA_FALSE;
1530 if (evas_object_freeze_events_get(parent)) return EINA_FALSE;
1531 parent = evas_object_smart_parent_get(parent);
1536 static Eldbus_Message *
1537 _selection_selected_child_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1539 const char *obj_path = eldbus_message_path_get(msg);
1540 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1541 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1545 Eldbus_Message *ret;
1546 Eldbus_Message_Iter *iter;
1548 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1550 if (!eldbus_message_arguments_get(msg, "i", &idx))
1551 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1553 ret = eldbus_message_method_return_new(msg);
1554 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1556 iter = eldbus_message_iter_get(ret);
1557 eo_do(obj, child = elm_interface_atspi_selection_selected_child_get(idx));
1559 _bridge_iter_object_reference_append(bridge, iter, child);
1560 _bridge_object_register(bridge, child);
1565 static Eldbus_Message *
1566 _selection_child_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1568 const char *obj_path = eldbus_message_path_get(msg);
1569 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1570 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1572 Eldbus_Message *ret;
1573 Eina_Bool result = EINA_FALSE;
1575 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1577 if (!eldbus_message_arguments_get(msg, "i", &idx))
1578 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1580 ret = eldbus_message_method_return_new(msg);
1581 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1583 if (_is_operation_permitted(obj))
1584 eo_do(obj, result = elm_interface_atspi_selection_child_select(idx));
1585 eldbus_message_arguments_append(ret, "b", result);
1590 static Eldbus_Message *
1591 _selection_selected_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1593 const char *obj_path = eldbus_message_path_get(msg);
1594 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1595 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1597 Eldbus_Message *ret;
1598 Eina_Bool result = EINA_FALSE;
1600 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1602 if (!eldbus_message_arguments_get(msg, "i", &idx))
1603 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1605 ret = eldbus_message_method_return_new(msg);
1606 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1608 if (_is_operation_permitted(obj))
1609 eo_do(obj, result = elm_interface_atspi_selection_selected_child_deselect(idx));
1610 eldbus_message_arguments_append(ret, "b", result);
1615 static Eldbus_Message *
1616 _selection_is_child_selected(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1618 const char *obj_path = eldbus_message_path_get(msg);
1619 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1620 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1622 Eldbus_Message *ret;
1625 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1627 if (!eldbus_message_arguments_get(msg, "i", &idx))
1628 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1630 ret = eldbus_message_method_return_new(msg);
1631 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1633 eo_do(obj, result = elm_interface_atspi_selection_is_child_selected(idx));
1634 eldbus_message_arguments_append(ret, "b", result);
1639 static Eldbus_Message *
1640 _selection_all_children_select(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1642 const char *obj_path = eldbus_message_path_get(msg);
1643 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1644 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1645 Eldbus_Message *ret;
1646 Eina_Bool result = EINA_FALSE;
1648 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1650 ret = eldbus_message_method_return_new(msg);
1651 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1653 if (_is_operation_permitted(obj))
1654 eo_do(obj, result = elm_interface_atspi_selection_all_children_select());
1655 eldbus_message_arguments_append(ret, "b", result);
1660 static Eldbus_Message *
1661 _selection_clear(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1663 const char *obj_path = eldbus_message_path_get(msg);
1664 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1665 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1666 Eldbus_Message *ret;
1667 Eina_Bool result = EINA_FALSE;
1669 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1671 ret = eldbus_message_method_return_new(msg);
1672 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1674 if (_is_operation_permitted(obj))
1675 eo_do(obj, result = elm_interface_atspi_selection_clear());
1676 eldbus_message_arguments_append(ret, "b", result);
1681 static Eldbus_Message *
1682 _selection_child_deselect(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1684 const char *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;
1689 Eina_Bool result = EINA_FALSE;
1691 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, msg);
1693 if (!eldbus_message_arguments_get(msg, "i", &idx))
1694 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1696 ret = eldbus_message_method_return_new(msg);
1697 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1699 if (_is_operation_permitted(obj))
1700 eo_do(obj, result = elm_interface_atspi_selection_child_deselect(idx));
1701 eldbus_message_arguments_append(ret, "b", result);
1706 static const Eldbus_Method selection_methods[] = {
1707 { "GetSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"(so)", "Accessible"}), _selection_selected_child_get, 0 },
1708 { "SelectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_select, 0 },
1709 { "DeselectSelectedChild", ELDBUS_ARGS({"i", "selectedChildIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_selected_child_deselect, 0 },
1710 { "IsChildSelected", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_is_child_selected, 0 },
1711 { "SelectAll", NULL, ELDBUS_ARGS({"b", "result"}), _selection_all_children_select, 0},
1712 { "ClearSelection", NULL, ELDBUS_ARGS({"b", "result"}), _selection_clear, 0},
1713 { "DeselectChild", ELDBUS_ARGS({"i", "childIndex"}), ELDBUS_ARGS({"b", "result"}), _selection_child_deselect, 0 },
1714 { NULL, NULL, NULL, NULL, 0 }
1717 static Eldbus_Message *
1718 _action_description_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1720 const char *description, *obj_path = eldbus_message_path_get(msg);
1721 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1722 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1724 Eldbus_Message *ret;
1726 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1728 if (!eldbus_message_arguments_get(msg, "i", &idx))
1729 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1731 ret = eldbus_message_method_return_new(msg);
1732 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1734 eo_do(obj, description = elm_interface_atspi_action_description_get(idx));
1735 description = description ? description : "";
1736 eldbus_message_arguments_append(ret, "s", description);
1741 static Eldbus_Message *
1742 _action_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1744 const char *name, *obj_path = eldbus_message_path_get(msg);
1745 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1746 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1748 Eldbus_Message *ret;
1750 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1752 if (!eldbus_message_arguments_get(msg, "i", &idx))
1753 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1755 ret = eldbus_message_method_return_new(msg);
1756 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1758 eo_do(obj, name = elm_interface_atspi_action_name_get(idx));
1759 name = name ? name : "";
1760 eldbus_message_arguments_append(ret, "s", name);
1765 static Eldbus_Message *
1766 _action_localized_name_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1768 const char *name, *obj_path = eldbus_message_path_get(msg);
1769 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1770 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1772 Eldbus_Message *ret;
1774 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1776 if (!eldbus_message_arguments_get(msg, "i", &idx))
1777 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1779 ret = eldbus_message_method_return_new(msg);
1780 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1782 eo_do(obj, name = elm_interface_atspi_action_localized_name_get(idx));
1783 name = name ? name : "";
1784 eldbus_message_arguments_append(ret, "s", name);
1789 static Eldbus_Message *
1790 _action_key_binding_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1792 const char *obj_path = eldbus_message_path_get(msg);
1794 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1795 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1797 Eldbus_Message *ret;
1799 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1801 if (!eldbus_message_arguments_get(msg, "i", &idx))
1802 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1804 ret = eldbus_message_method_return_new(msg);
1805 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1807 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(idx));
1808 eldbus_message_arguments_append(ret, "s", key ? key : "");
1814 static Eldbus_Message *
1815 _action_actions_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1817 const char *action, *obj_path = eldbus_message_path_get(msg);
1818 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1819 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1821 Eldbus_Message *ret;
1822 Eldbus_Message_Iter *iter, *iter_array;
1824 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1826 ret = eldbus_message_method_return_new(msg);
1827 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1829 iter = eldbus_message_iter_get(ret);
1830 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
1832 iter_array = eldbus_message_iter_container_new(iter, 'a', "sss");
1833 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_array, NULL);
1835 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1838 EINA_LIST_FREE(actions, action)
1842 eo_do(obj, key = elm_interface_atspi_action_keybinding_get(id));
1843 eo_do(obj, descr = elm_interface_atspi_action_description_get(id));
1844 descr = descr ? descr : "";
1845 eldbus_message_iter_arguments_append(iter_array, "sss", action, descr, key ? key : "");
1850 eldbus_message_iter_container_close(iter, iter_array);
1855 static Eldbus_Message *
1856 _action_action_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1858 const char *obj_path = eldbus_message_path_get(msg);
1859 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1860 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1862 Eldbus_Message *ret;
1863 Eina_Bool result = EINA_FALSE;
1865 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1867 if (!eldbus_message_arguments_get(msg, "i", &idx))
1868 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1870 ret = eldbus_message_method_return_new(msg);
1871 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1873 if (_is_operation_permitted(obj))
1874 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1876 eldbus_message_arguments_append(ret, "b", result);
1881 static Eldbus_Message *
1882 _action_action_name_do(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1884 const char *obj_path = eldbus_message_path_get(msg);
1885 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1886 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1891 Eldbus_Message *ret;
1892 Eina_Bool result = EINA_FALSE;
1894 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, msg);
1896 if (!eldbus_message_arguments_get(msg, "s", &action_name))
1897 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1899 ret = eldbus_message_method_return_new(msg);
1900 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1902 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
1903 EINA_LIST_FREE(actions, action)
1905 if (!result && action && !strcmp(action, action_name))
1913 eo_do(obj, result = elm_interface_atspi_action_do(idx));
1915 eldbus_message_arguments_append(ret, "b", result);
1920 static const Eldbus_Method action_methods[] = {
1921 { "GetDescription", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "description"}), _action_description_get, 0 },
1922 { "GetName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_name_get, 0 },
1923 { "GetLocalizedName", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "name"}), _action_localized_name_get, 0 },
1924 { "GetKeyBinding", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"s", "key"}), _action_key_binding_get, 0 },
1925 { "GetActions", NULL, ELDBUS_ARGS({"a(sss)", "actions"}), _action_actions_get, 0 },
1926 { "DoAction", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"b", "result"}), _action_action_do, 0 },
1927 { "DoActionName", ELDBUS_ARGS({"s", "name"}), ELDBUS_ARGS({"b", "result"}), _action_action_name_do, 0 },
1928 { NULL, NULL, NULL, NULL, 0 }
1931 static Eldbus_Message *
1932 _image_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1934 AtspiCoordType type;
1935 Eldbus_Message *ret;
1936 const char *obj_path = eldbus_message_path_get(msg);
1938 Eina_Bool screen_coords;
1939 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1940 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1944 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1946 if (!eldbus_message_arguments_get(msg, "u", &type))
1947 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1949 ret = eldbus_message_method_return_new(msg);
1950 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1952 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1953 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, &w, &h));
1954 eldbus_message_arguments_append(ret, "iiii", x, y, w, h);
1959 static Eldbus_Message *
1960 _image_position_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1962 AtspiCoordType type;
1963 Eldbus_Message *ret;
1964 const char *obj_path = eldbus_message_path_get(msg);
1965 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1966 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1968 Eina_Bool screen_coords;
1970 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1972 if (!eldbus_message_arguments_get(msg, "u", &type))
1973 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
1975 ret = eldbus_message_method_return_new(msg);
1976 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
1978 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
1979 eo_do(obj, elm_interface_atspi_image_extents_get(screen_coords, &x, &y, NULL, NULL));
1980 eldbus_message_arguments_append(ret, "i", x);
1981 eldbus_message_arguments_append(ret, "i", y);
1986 static Eldbus_Message *
1987 _image_size_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
1989 Eldbus_Message *ret;
1990 const char *obj_path = eldbus_message_path_get(msg);
1991 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
1992 Eo *obj = _bridge_object_from_path(bridge, obj_path);
1995 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, msg);
1997 ret = eldbus_message_method_return_new(msg);
1998 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2000 eo_do(obj, elm_interface_atspi_image_extents_get(EINA_FALSE, NULL, NULL, &w, &h));
2001 eldbus_message_arguments_append(ret, "i", w);
2002 eldbus_message_arguments_append(ret, "i", h);
2007 static const Eldbus_Method image_methods[] = {
2008 { "GetImageExtents", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"iiii", "extents"}), _image_extents_get, 0 },
2009 { "GetImagePosition", ELDBUS_ARGS({"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}), _image_position_get, 0 },
2010 { "GetImageSize", NULL, ELDBUS_ARGS({"i", "width"}, {"i", "height"}), _image_size_get, 0 },
2011 { NULL, NULL, NULL, NULL, 0 }
2014 static Eldbus_Message *
2015 _text_string_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2017 const char *obj_path = eldbus_message_path_get(msg);
2019 Elm_Atspi_Text_Granularity gran;
2021 Eldbus_Message *ret;
2022 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2023 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2025 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2027 if (!eldbus_message_arguments_get(msg, "iu", &start, &gran))
2028 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
2030 ret = eldbus_message_method_return_new(msg);
2031 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2033 eo_do(obj, str = elm_interface_atspi_text_string_get(gran, &start, &end));
2034 str = str ? str : strdup("");
2036 eldbus_message_arguments_append(ret, "sii", str, start, end);
2042 static Eldbus_Message *
2043 _text_text_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2045 const char *obj_path = eldbus_message_path_get(msg);
2047 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2048 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2051 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2053 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2054 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and granularity expected.");
2056 Eldbus_Message *ret = eldbus_message_method_return_new(msg);
2057 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2059 eo_do(obj, str = elm_interface_atspi_text_get(start, end));
2060 str = str ? str : strdup("");
2062 eldbus_message_arguments_append(ret, "s", str);
2068 static Eldbus_Message *
2069 _text_caret_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2071 const char *obj_path = eldbus_message_path_get(msg);
2072 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2073 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2075 Eldbus_Message *ret;
2078 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2080 if (!eldbus_message_arguments_get(msg, "i", &offset))
2081 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2083 ret = eldbus_message_method_return_new(msg);
2084 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2086 eo_do(obj, res = elm_interface_atspi_text_caret_offset_set(offset));
2088 eldbus_message_arguments_append(ret, "b", res);
2093 static Eldbus_Message *
2094 _text_character_at_offset_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2096 const char *obj_path = eldbus_message_path_get(msg);
2097 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2098 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2100 Eldbus_Message *ret;
2103 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2105 if (!eldbus_message_arguments_get(msg, "i", &offset))
2106 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2108 ret = eldbus_message_method_return_new(msg);
2109 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2111 eo_do(obj, res = elm_interface_atspi_text_character_get(offset));
2113 eldbus_message_arguments_append(ret, "i", res);
2118 static Eldbus_Message *
2119 _text_attribute_value_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2121 const char *name, *obj_path = eldbus_message_path_get(msg);
2123 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2124 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2126 Eldbus_Message *ret;
2129 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2131 if (!eldbus_message_arguments_get(msg, "is", &start, &name))
2132 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and attribute name expected.");
2134 ret = eldbus_message_method_return_new(msg);
2135 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2137 eo_do(obj, res = elm_interface_atspi_text_attribute_get(name, &start, &end, &value));
2138 eldbus_message_arguments_append(ret, "siib", value ? value : "", start, end, res);
2140 if (value) free(value);
2144 static Eldbus_Message *
2145 _text_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2147 const char *obj_path = eldbus_message_path_get(msg);
2148 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2149 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2151 Eldbus_Message *ret;
2152 Eldbus_Message_Iter *iter, *iter_array;
2154 Elm_Atspi_Text_Attribute *attr;
2156 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2158 if (!eldbus_message_arguments_get(msg, "i", &start))
2159 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset expected.");
2161 ret = eldbus_message_method_return_new(msg);
2162 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2164 iter = eldbus_message_iter_get(ret);
2165 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2166 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2168 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2170 EINA_LIST_FREE(attrs, attr)
2172 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2173 elm_atspi_text_text_attribute_free(attr);
2176 eldbus_message_iter_container_close(iter, iter_array);
2177 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2182 if (ret) eldbus_message_unref(ret);
2186 static Eldbus_Message *
2187 _text_default_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2189 const char *obj_path = eldbus_message_path_get(msg);
2190 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2191 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2192 int start = -1, end;
2193 Eldbus_Message *ret;
2194 Eldbus_Message_Iter *iter, *iter_array;
2196 Elm_Atspi_Text_Attribute *attr;
2198 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2200 ret = eldbus_message_method_return_new(msg);
2201 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2203 iter = eldbus_message_iter_get(ret);
2204 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2205 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2207 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2209 EINA_LIST_FREE(attrs, attr)
2211 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2212 elm_atspi_text_text_attribute_free(attr);
2215 eldbus_message_iter_container_close(iter, iter_array);
2216 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2221 if (ret) eldbus_message_unref(ret);
2225 static Eldbus_Message *
2226 _text_character_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2228 const char *obj_path = eldbus_message_path_get(msg);
2229 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2230 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2232 Eina_Rectangle rect;
2233 AtspiCoordType type;
2234 Eina_Bool screen_coords, res;
2235 Eldbus_Message *ret;
2237 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2239 if (!eldbus_message_arguments_get(msg, "iu", &offset, &type))
2240 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2242 ret = eldbus_message_method_return_new(msg);
2243 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2245 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2247 eo_do(obj, res = elm_interface_atspi_text_character_extents_get(offset, screen_coords, &rect));
2251 eldbus_message_unref(ret);
2252 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get character extents.");
2254 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2259 static Eldbus_Message *
2260 _text_offset_at_point_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2262 const char *obj_path = eldbus_message_path_get(msg);
2263 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2264 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2266 AtspiCoordType type;
2267 Eina_Bool screen_coords;
2268 Eldbus_Message *ret;
2270 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2272 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &type))
2273 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and coordinates type expected.");
2275 ret = eldbus_message_method_return_new(msg);
2276 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2279 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2281 eo_do(obj, offset = elm_interface_atspi_text_offset_at_point_get(screen_coords, x, y));
2283 eldbus_message_arguments_append(ret, "i", offset);
2288 static Eldbus_Message *
2289 _text_n_selections_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2291 const char *obj_path = eldbus_message_path_get(msg);
2292 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2293 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2295 Eldbus_Message *ret;
2297 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2299 ret = eldbus_message_method_return_new(msg);
2300 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2302 eo_do(obj, n = elm_interface_atspi_text_selections_count_get());
2304 eldbus_message_arguments_append(ret, "i", n);
2309 static Eldbus_Message *
2310 _text_selection_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2312 const char *obj_path = eldbus_message_path_get(msg);
2313 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2314 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2315 int sel_num, start, end;
2316 Eldbus_Message *ret;
2318 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2320 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2321 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2323 ret = eldbus_message_method_return_new(msg);
2324 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2326 eo_do(obj, elm_interface_atspi_text_selection_get(sel_num, &start, &end));
2328 eldbus_message_arguments_append(ret, "ii", start, end);
2333 static Eldbus_Message *
2334 _text_selection_add(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2336 const char *obj_path = eldbus_message_path_get(msg);
2337 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2338 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2341 Eldbus_Message *ret;
2343 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2345 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2346 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end text offset expected.");
2348 ret = eldbus_message_method_return_new(msg);
2349 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2351 eo_do(obj, res = elm_interface_atspi_text_selection_add(start, end));
2353 eldbus_message_arguments_append(ret, "b", res);
2358 static Eldbus_Message *
2359 _text_selection_remove(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2361 const char *obj_path = eldbus_message_path_get(msg);
2362 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2363 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2366 Eldbus_Message *ret;
2368 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2370 if (!eldbus_message_arguments_get(msg, "i", &sel_num))
2371 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2373 ret = eldbus_message_method_return_new(msg);
2374 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2376 eo_do(obj, res = elm_interface_atspi_text_selection_remove(sel_num));
2378 eldbus_message_arguments_append(ret, "b", res);
2383 static Eldbus_Message *
2384 _text_selection_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2386 const char *obj_path = eldbus_message_path_get(msg);
2387 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2388 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2389 int sel_num, start, end;
2391 Eldbus_Message *ret;
2393 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2395 if (!eldbus_message_arguments_get(msg, "iii", &sel_num, &start, &end))
2396 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2398 ret = eldbus_message_method_return_new(msg);
2399 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2401 eo_do(obj, res = elm_interface_atspi_text_selection_set(sel_num, start, end));
2403 eldbus_message_arguments_append(ret, "b", res);
2408 static Eldbus_Message *
2409 _text_range_extents_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2411 const char *obj_path = eldbus_message_path_get(msg);
2412 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2413 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2415 Eina_Rectangle rect;
2416 Eina_Bool screen_coords, res;
2417 AtspiCoordType type;
2418 Eldbus_Message *ret;
2420 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2422 if (!eldbus_message_arguments_get(msg, "iiu", &start, &end, &type))
2423 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Selection number expected.");
2425 ret = eldbus_message_method_return_new(msg);
2426 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2428 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2429 eo_do(obj, res = elm_interface_atspi_text_range_extents_get(screen_coords, start, end, &rect));
2432 eldbus_message_unref(ret);
2433 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Can't get range extents.");
2436 eldbus_message_arguments_append(ret, "iiii", rect.x, rect.y, rect.w, rect.h);
2441 static Eldbus_Message *
2442 _text_bounded_ranges_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2444 const char *obj_path = eldbus_message_path_get(msg);
2445 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2446 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2447 Eina_Rectangle rect;
2448 Eina_Bool screen_coords;
2449 AtspiCoordType type;
2450 Elm_Atspi_Text_Clip_Type xclip, yclip;
2452 Eldbus_Message *ret;
2453 Elm_Atspi_Text_Range *range;
2454 Eldbus_Message_Iter *iter, *iter_array, *iter_struct, *iter_var;
2456 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2458 if (!eldbus_message_arguments_get(msg, "iiiiuuu", &rect.x, &rect.y, &rect.w, &rect.h, &type, &xclip, &yclip))
2459 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.");
2461 ret = eldbus_message_method_return_new(msg);
2462 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2464 iter = eldbus_message_iter_get(ret);
2465 iter_array = eldbus_message_iter_container_new(iter, 'a', "(iisv)");
2466 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2468 screen_coords = type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
2469 eo_do(obj, ranges = elm_interface_atspi_text_bounded_ranges_get(screen_coords, rect, xclip, yclip));
2471 EINA_LIST_FREE(ranges, range)
2473 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
2476 eldbus_message_iter_basic_append(iter_struct, 'i', range->start_offset);
2477 eldbus_message_iter_basic_append(iter_struct, 'i', range->end_offset);
2478 range->content = range->content ? range->content : strdup("");
2479 eldbus_message_iter_basic_append(iter_struct, 's', range->content);
2480 /* AT-SPI specification requires variant type in return, however
2481 * ATK or other implementations as well as AT Clients don't use it .
2482 * To cover spec a dummy value will be returned */
2483 iter_var = eldbus_message_iter_container_new(iter_struct, 'v', "i");
2486 eldbus_message_iter_basic_append(iter_var, 'i', 0);
2487 eldbus_message_iter_container_close(iter_struct, iter_var);
2489 eldbus_message_iter_container_close(iter_array, iter_struct);
2491 if (range->content) free(range->content);
2495 eldbus_message_iter_container_close(iter, iter_array);
2500 if (ret) eldbus_message_unref(ret);
2504 static Eldbus_Message *
2505 _text_run_attributes_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2507 const char *obj_path = eldbus_message_path_get(msg);
2508 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2509 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2511 Eldbus_Message *ret;
2512 Eldbus_Message_Iter *iter, *iter_array;
2513 Eina_List *attrs, *defaults;
2514 Elm_Atspi_Text_Attribute *attr;
2517 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, msg);
2519 if (!eldbus_message_arguments_get(msg, "ib", &start, &incl_def))
2520 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Offset and include defaults flag expected.");
2522 ret = eldbus_message_method_return_new(msg);
2523 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2525 iter = eldbus_message_iter_get(ret);
2526 iter_array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
2527 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
2529 eo_do(obj, attrs = elm_interface_atspi_text_attributes_get(&start, &end));
2533 eo_do(obj, defaults = elm_interface_atspi_text_default_attributes_get());
2534 attrs = eina_list_merge(attrs, defaults);
2537 EINA_LIST_FREE(attrs, attr)
2539 eldbus_message_iter_arguments_append(iter_array, "ss", attr->name, attr->value);
2540 elm_atspi_text_text_attribute_free(attr);
2543 eldbus_message_iter_container_close(iter, iter_array);
2544 eldbus_message_iter_arguments_append(iter, "ii", start, end);
2549 if (ret) eldbus_message_unref(ret);
2553 static const Eldbus_Method text_methods[] = {
2554 { "GetTextAtOffset", ELDBUS_ARGS({"i", "offset"}, {"u", "granularity"}), ELDBUS_ARGS({"s", "string"}, {"i", "startOffset"}, {"i", "endOffset"}), _text_string_at_offset_get, 0 },
2555 { "GetText", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"s", "string"}), _text_text_get, 0 },
2556 { "SetCaretOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"b", NULL}), _text_caret_offset_set, 0 },
2557 { "GetCharacterAtOffset", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"i", NULL}), _text_character_at_offset_get, 0 },
2558 { "GetAttributeValue", ELDBUS_ARGS({"i", "offset"}, {"s", "attributeName"}), ELDBUS_ARGS({"s", NULL}, {"i", "startOffset"}, {"i", "endOffset"}, {"b", "defined"}), _text_attribute_value_get, 0 },
2559 { "GetAttributes", ELDBUS_ARGS({"i", "offset"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_attributes_get, 0 },
2560 { "GetDefaultAttributes", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2561 { "GetCharacterExtents", ELDBUS_ARGS({"i", "offset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_character_extents_get, 0 },
2562 { "GetOffsetAtPoint", ELDBUS_ARGS({"i", "x"}, {"i","y"}, {"u", "coordType"}), ELDBUS_ARGS({"i", NULL}), _text_offset_at_point_get, 0 },
2563 { "GetNSelections", NULL, ELDBUS_ARGS({"i", NULL}), _text_n_selections_get, 0 },
2564 { "GetSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), _text_selection_get, 0 },
2565 { "AddSelection", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_add, 0 },
2566 { "RemoveSelection", ELDBUS_ARGS({"i", "selectionNum"}), ELDBUS_ARGS({"b", NULL}), _text_selection_remove, 0 },
2567 { "SetSelection", ELDBUS_ARGS({"i", "selectionNum"}, {"i", "startOffset"}, {"i", "endOffset"}), ELDBUS_ARGS({"b", NULL}), _text_selection_set, 0 },
2568 { "GetRangeExtents", ELDBUS_ARGS({"i", "startOffset"}, {"i", "endOffset"}, {"u", "coordType"}), ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i","w"}, {"i","h"}), _text_range_extents_get, 0 },
2569 { "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 },
2570 { "GetAttributeRun", ELDBUS_ARGS({"i", "offset"}, {"b", "includeDefaults"}), ELDBUS_ARGS({"a(ss)", NULL}, {"i", "startOffset"}, {"i", "endOffset"}), _text_run_attributes_get, 0 },
2571 { "GetDefaultAttributeSet", NULL, ELDBUS_ARGS({"a(ss)", NULL}), _text_default_attributes_get, 0 },
2572 { NULL, NULL, NULL, NULL, 0 }
2575 static Eldbus_Message *
2576 _editable_text_text_content_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2578 const char *obj_path = eldbus_message_path_get(msg);
2579 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2580 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2581 const char *content;
2582 Eldbus_Message *ret;
2585 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2587 if (!eldbus_message_arguments_get(msg, "s", &content))
2588 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "String expected.");
2590 ret = eldbus_message_method_return_new(msg);
2591 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2593 eo_do(obj, res = elm_interface_atspi_editable_text_content_set(content));
2595 eldbus_message_arguments_append(ret, "b", res);
2600 static Eldbus_Message *
2601 _editable_text_text_insert(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2603 const char *obj_path = eldbus_message_path_get(msg);
2604 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2605 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2607 Eldbus_Message *ret;
2611 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2613 if (!eldbus_message_arguments_get(msg, "isi", &pos, &text, &len))
2614 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Postion, string, length expected.");
2616 ret = eldbus_message_method_return_new(msg);
2617 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2619 eo_do(obj, res = elm_interface_atspi_editable_text_insert(text, pos));
2621 eldbus_message_arguments_append(ret, "b", res);
2626 static Eldbus_Message *
2627 _editable_text_text_copy(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2629 const char *obj_path = eldbus_message_path_get(msg);
2630 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2631 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2632 Eldbus_Message *ret;
2636 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2638 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2639 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2641 ret = eldbus_message_method_return_new(msg);
2642 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2644 eo_do(obj, res = elm_interface_atspi_editable_text_copy(start, end));
2646 eldbus_message_arguments_append(ret, "b", res);
2651 static Eldbus_Message *
2652 _editable_text_text_cut(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2654 const char *obj_path = eldbus_message_path_get(msg);
2655 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2656 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2657 Eldbus_Message *ret;
2661 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2663 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2664 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2666 ret = eldbus_message_method_return_new(msg);
2667 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2669 eo_do(obj, res = elm_interface_atspi_editable_text_cut(start, end));
2671 eldbus_message_arguments_append(ret, "b", res);
2676 static Eldbus_Message *
2677 _editable_text_text_delete(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2679 const char *obj_path = eldbus_message_path_get(msg);
2680 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2681 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2682 Eldbus_Message *ret;
2686 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2688 if (!eldbus_message_arguments_get(msg, "ii", &start, &end))
2689 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2691 ret = eldbus_message_method_return_new(msg);
2692 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2694 eo_do(obj, res = elm_interface_atspi_editable_text_delete(start, end));
2696 eldbus_message_arguments_append(ret, "b", res);
2701 static Eldbus_Message *
2702 _editable_text_text_paste(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2704 const char *obj_path = eldbus_message_path_get(msg);
2705 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2706 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2707 Eldbus_Message *ret;
2711 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE, msg);
2713 if (!eldbus_message_arguments_get(msg, "i", &pos))
2714 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Start and end index expected.");
2716 ret = eldbus_message_method_return_new(msg);
2717 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
2719 eo_do(obj, res = elm_interface_atspi_editable_text_paste(pos));
2721 eldbus_message_arguments_append(ret, "b", res);
2727 _elm_atspi_bridge_plug_id_split(const char *plug_id, char **bus, char **path)
2729 if (!plug_id || !strcmp(plug_id, "")) return EINA_FALSE;
2730 unsigned int tokens = 0;
2731 char **split = eina_str_split_full(plug_id, ":", 0, &tokens);
2732 Eina_Bool ret = EINA_FALSE;
2735 if (!split[0] || !split[1])
2739 if (bus) *bus = strdup(split[0]);
2740 if (path) *path = strdup(split[1]);
2744 else if (tokens == 3)
2746 if (!split[0] || !split[1] || !split[2])
2751 snprintf(buf, sizeof(buf), "%s:%s",split[0], split[1]);
2752 if (bus) *bus = strdup(buf);
2753 if (path) *path = strdup(split[2]);
2765 static Eldbus_Message *
2766 _socket_embedded(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
2769 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2770 const char *obj_path = eldbus_message_path_get(msg);
2772 const char *bus, *path;
2773 Eo *bridge = _elm_atspi_bridge_get();
2774 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2775 eo_do(obj, proxy = elm_interface_atspi_accessible_parent_get());
2777 if (!eo_isa(proxy, ELM_ATSPI_PROXY_CLASS))
2778 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to embed object.");
2780 if (!eldbus_message_arguments_get(msg, "s", &path))
2781 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Plug id expected.");
2783 bus = eldbus_message_sender_get(msg);
2785 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
2787 _bridge_cache_build(bridge, proxy);
2789 return eldbus_message_method_return_new(msg);
2792 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2793 static Eldbus_Message *
2794 _socket_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2798 Eo *obj = eldbus_service_object_data_get(iface, "_atspi_obj");
2799 eo_do(obj, parent = eo_parent_get());
2800 Evas_Object *top = elm_object_top_widget_get(parent);
2802 if (!eldbus_message_arguments_get(msg, "ii", &x, &y))
2803 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
2805 eo_do(top, elm_interface_atspi_component_socket_offset_set(x, y));
2807 return eldbus_message_method_return_new(msg);
2811 static const Eldbus_Method editable_text_methods[] = {
2812 { "SetTextContents", ELDBUS_ARGS({"s", "newcontents"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_content_set, 0 },
2813 { "InsertText", ELDBUS_ARGS({"i", "position"}, {"s", "text"}, {"i", "length"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_insert, 0 },
2814 { "CopyText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), NULL, _editable_text_text_copy, 0 },
2815 { "CutText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_cut, 0 },
2816 { "DeleteText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_delete, 0 },
2817 { "PasteText", ELDBUS_ARGS({"i", "position"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_paste, 0 },
2818 { NULL, NULL, NULL, NULL, 0 }
2821 static const Eldbus_Method socket_methods[] = {
2822 { "Embedded", ELDBUS_ARGS({"s", "id"}), ELDBUS_ARGS({NULL, NULL}), _socket_embedded, 0 },
2823 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2824 { "SetOffset", ELDBUS_ARGS({"i", "x"}, {"i", "y"}), ELDBUS_ARGS({NULL, NULL}), _socket_offset_set, 0 },
2826 { NULL, NULL, NULL, NULL, 0 }
2829 static const Eldbus_Service_Interface_Desc socket_iface_desc = {
2830 ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL
2834 _bridge_object_from_path(Eo *bridge, const char *path)
2836 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2837 unsigned long long eo_ptr = 0;
2839 const char *tmp = path;
2842 int len = strlen(ELM_ACCESS_OBJECT_PATH_PREFIX);
2843 if (strncmp(path, ELM_ACCESS_OBJECT_PATH_PREFIX, len))
2846 tmp = path + len; /* Skip over the prefix */
2847 if (!strcmp(ELM_ACCESS_OBJECT_PATH_ROOT, tmp))
2848 return elm_atspi_bridge_root_get(bridge);
2850 sscanf(tmp, "%llu", &eo_ptr);
2851 eo = (Eo *) (uintptr_t) eo_ptr;
2853 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
2854 if (!eina_hash_find(pd->cache, &eo))
2856 WRN("Request for non-registered object: %s", path);
2860 ret = eo_isa(eo, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN) ? eo : NULL;
2866 _bridge_path_from_object(Eo *bridge, const Eo *eo)
2868 static char path[64];
2871 return ATSPI_DBUS_PATH_NULL;
2873 if (eo == elm_atspi_bridge_root_get(bridge))
2874 snprintf(path, sizeof(path), "%s%s", ELM_ACCESS_OBJECT_PATH_PREFIX, ELM_ACCESS_OBJECT_PATH_ROOT);
2876 snprintf(path, sizeof(path), ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE, (unsigned long long)(uintptr_t)eo);
2881 _accessible_property_get(const Eldbus_Service_Interface *interface, const char *property,
2882 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2883 Eldbus_Message **error)
2885 const char *ret = NULL, *obj_path = eldbus_message_path_get(request_msg);
2886 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2887 Eo *ret_obj = NULL, *obj = _bridge_object_from_path(bridge, obj_path);
2889 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, request_msg, error);
2891 if (!strcmp(property, "Name"))
2893 eo_do(obj, ret = elm_interface_atspi_accessible_name_get());
2896 eldbus_message_iter_basic_append(iter, 's', ret);
2899 else if (!strcmp(property, "Description"))
2901 eo_do(obj, ret = elm_interface_atspi_accessible_description_get());
2904 eldbus_message_iter_basic_append(iter, 's', ret);
2907 else if (!strcmp(property, "Parent"))
2909 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
2910 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
2911 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
2912 if ((!ret_obj) && (ELM_ATSPI_ROLE_APPLICATION == role))
2913 _object_desktop_reference_append(iter);
2915 _bridge_iter_object_reference_append(bridge, iter, ret_obj);
2918 else if (!strcmp(property, "ChildCount"))
2920 Eina_List *l = NULL;
2921 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
2922 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
2930 _selection_property_get(const Eldbus_Service_Interface *interface, const char *property,
2931 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2932 Eldbus_Message **error)
2935 const char *obj_path = eldbus_message_path_get(request_msg);
2936 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2937 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2939 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, request_msg, error);
2941 if (!strcmp(property, "NSelectedChildren"))
2943 eo_do(obj, n = elm_interface_atspi_selection_selected_children_count_get());
2944 eldbus_message_iter_basic_append(iter, 'i', n);
2951 _action_property_get(const Eldbus_Service_Interface *interface, const char *property,
2952 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2953 Eldbus_Message **error)
2956 const char *obj_path = eldbus_message_path_get(request_msg);
2957 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2958 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2960 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, request_msg, error);
2962 if (!strcmp(property, "NActions"))
2964 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
2965 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(actions));
2966 eina_list_free(actions);
2972 static Eldbus_Message*
2973 _value_properties_set(const Eldbus_Service_Interface *interface, const char *property,
2974 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg)
2978 const char *obj_path = eldbus_message_path_get(request_msg);
2979 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2980 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2982 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg);
2984 if (!eldbus_message_iter_arguments_get(iter, "d", &value))
2986 return eldbus_message_error_new(request_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: double.");
2989 if (!strcmp(property, "CurrentValue"))
2991 eo_do(obj, ret = elm_interface_atspi_value_and_text_set(value, NULL));
2992 Eldbus_Message *answer = eldbus_message_method_return_new(request_msg);
2993 eldbus_message_arguments_append(answer, "b", ret);
3001 _value_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3002 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3003 Eldbus_Message **error)
3006 const char *obj_path = eldbus_message_path_get(request_msg);
3007 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3008 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3010 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg, error);
3012 if (!strcmp(property, "CurrentValue"))
3014 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
3015 eldbus_message_iter_basic_append(iter, 'd', value);
3018 if (!strcmp(property, "MinimumValue"))
3020 eo_do(obj, elm_interface_atspi_value_range_get(&value, NULL, NULL));
3021 eldbus_message_iter_basic_append(iter, 'd', value);
3024 if (!strcmp(property, "MaximumValue"))
3026 eo_do(obj, elm_interface_atspi_value_range_get(NULL, &value, NULL));
3027 eldbus_message_iter_basic_append(iter, 'd', value);
3030 if (!strcmp(property, "MinimumIncrement"))
3032 eo_do(obj, value = elm_interface_atspi_value_increment_get());
3033 eldbus_message_iter_basic_append(iter, 'd', value);
3040 _image_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3041 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3042 Eldbus_Message **error)
3045 const char *obj_path = eldbus_message_path_get(request_msg);
3046 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3047 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3049 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, request_msg, error);
3051 if (!strcmp(property, "ImageDescription"))
3053 eo_do(obj, value = elm_interface_atspi_image_description_get());
3054 value = value ? value : "";
3055 eldbus_message_iter_basic_append(iter, 's', value);
3058 if (!strcmp(property, "ImageLocale"))
3060 eo_do(obj, value = elm_interface_atspi_image_locale_get());
3061 value = value ? value : "";
3062 eldbus_message_iter_basic_append(iter, 's', value);
3069 _text_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3070 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3071 Eldbus_Message **error)
3073 const char *obj_path = eldbus_message_path_get(request_msg);
3074 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3075 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3078 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, request_msg, error);
3080 if (!strcmp(property, "CharacterCount"))
3082 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
3083 eldbus_message_iter_basic_append(iter, 'i', val);
3086 if (!strcmp(property, "CaretOffset"))
3088 eo_do(obj, val = elm_interface_atspi_text_caret_offset_get());
3089 eldbus_message_iter_basic_append(iter, 'i', val);
3095 static Eldbus_Message*
3096 _application_properties_set(const Eldbus_Service_Interface *iface, const char *property, Eldbus_Message_Iter *iter, const Eldbus_Message *input_msg)
3098 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3099 const char *obj_path = eldbus_message_path_get(input_msg);
3100 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3103 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
3104 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, input_msg);
3106 if (!eldbus_message_iter_arguments_get(iter, "i", &value))
3108 return eldbus_message_error_new(input_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: int.");
3111 if (!strcmp(property, "Id"))
3114 Eldbus_Message *answer = eldbus_message_method_return_new(input_msg);
3115 eldbus_message_arguments_append(answer, "b", EINA_TRUE);
3123 _application_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3124 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3125 Eldbus_Message **error)
3127 const char *obj_path = eldbus_message_path_get(request_msg);
3128 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3129 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3131 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
3132 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, request_msg, error);
3134 if (!strcmp(property, "ToolkitName"))
3136 eldbus_message_iter_basic_append(iter, 's', "elementary");
3139 if (!strcmp(property, "Version"))
3142 snprintf(buf, sizeof(buf), "%d.%d", ELM_VERSION_MAJOR, ELM_VERSION_MINOR);
3143 eldbus_message_iter_basic_append(iter, 's', buf);
3146 if (!strcmp(property, "Id"))
3148 eldbus_message_iter_basic_append(iter, 'i', pd->id);
3154 static const Eldbus_Property accessible_properties[] = {
3155 { "Name", "s", NULL, NULL, 0 },
3156 { "Description", "s", NULL, NULL, 0 },
3157 { "Parent", "(so)", NULL, NULL, 0 },
3158 { "ChildCount", "i", NULL, NULL, 0 },
3159 { NULL, NULL, NULL, NULL, 0 }
3162 static const Eldbus_Property action_properties[] = {
3163 { "NActions", "i", _action_property_get, NULL, 0 },
3164 { NULL, NULL, NULL, NULL, 0 }
3167 static const Eldbus_Property value_properties[] = {
3168 { "MinimumValue", "d", NULL, NULL, 0 },
3169 { "MaximumValue", "d", NULL, NULL, 0 },
3170 { "MinimumIncrement", "d", NULL, NULL, 0 },
3171 { "CurrentValue", "d", NULL, NULL, 0 },
3172 { NULL, NULL, NULL, NULL, 0 }
3175 static const Eldbus_Property image_properties[] = {
3176 { "ImageDescription", "s", NULL, NULL, 0 },
3177 { "ImageLocale", "s", NULL, NULL, 0 },
3178 { NULL, NULL, NULL, NULL, 0 }
3181 static const Eldbus_Property selection_properties[] = {
3182 { "NSelectedChildren", "i", _selection_property_get, NULL, 0 },
3183 { NULL, NULL, NULL, NULL, 0 }
3186 static const Eldbus_Property text_properties[] = {
3187 { "CharacterCount", "i", NULL, NULL, 0 },
3188 { "CaretOffset", "i", NULL, NULL, 0 },
3189 { NULL, NULL, NULL, NULL, 0 }
3192 static const Eldbus_Property application_properties[] = {
3193 { "ToolkitName", "s", NULL, NULL, 0 },
3194 { "Version", "s", NULL, NULL, 0 },
3195 { "Id", "i", NULL, NULL, 0 },
3196 { NULL, NULL, NULL, NULL, 0 }
3199 static const Eldbus_Service_Interface_Desc accessible_iface_desc = {
3200 ATSPI_DBUS_INTERFACE_ACCESSIBLE, accessible_methods, NULL, accessible_properties, _accessible_property_get, NULL
3203 static const Eldbus_Service_Interface_Desc action_iface_desc = {
3204 ATSPI_DBUS_INTERFACE_ACTION, action_methods, NULL, action_properties, NULL, NULL
3207 static const Eldbus_Service_Interface_Desc value_iface_desc = {
3208 ATSPI_DBUS_INTERFACE_VALUE, NULL, NULL, value_properties, _value_properties_get, _value_properties_set
3211 static const Eldbus_Service_Interface_Desc image_iface_desc = {
3212 ATSPI_DBUS_INTERFACE_IMAGE, image_methods, NULL, image_properties, _image_properties_get, NULL
3215 static const Eldbus_Service_Interface_Desc selection_iface_desc = {
3216 ATSPI_DBUS_INTERFACE_SELECTION, selection_methods, NULL, selection_properties, NULL, NULL
3219 static const Eldbus_Service_Interface_Desc text_iface_desc = {
3220 ATSPI_DBUS_INTERFACE_TEXT, text_methods, NULL, text_properties, _text_properties_get, NULL
3223 static const Eldbus_Service_Interface_Desc editable_text_iface_desc = {
3224 ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, editable_text_methods, NULL, NULL, NULL, NULL
3227 static const Eldbus_Service_Interface_Desc application_iface_desc = {
3228 ATSPI_DBUS_INTERFACE_APPLICATION, NULL, NULL, application_properties, _application_properties_get, _application_properties_set
3232 _collection_match_rule_free(struct collection_match_rule *rule)
3234 Elm_Atspi_Attribute *attr;
3235 eina_list_free(rule->ifaces);
3236 EINA_LIST_FREE(rule->attributes, attr)
3238 eina_stringshare_del(attr->key);
3239 eina_stringshare_del(attr->value);
3244 _collection_roles_convert(uint64_t roles[2])
3246 // Currently elm roles and atspi roles are binary compatible.
3247 // Implement this function when it will be needed.
3252 _collection_iter_match_rule_get(Eldbus_Message_Iter *iter, struct collection_match_rule *rule)
3254 Eldbus_Message_Iter *states_iter, *attrib_iter, *iter_arg, *role_iter, *ifc_iter;
3255 unsigned int *array;
3256 int array_count, state_match, attrib_match, role_match, ifc_match, reverse;
3257 const char *ifc_name;
3259 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))
3261 ERR("Unable to get message arguments");
3265 memset(rule, 0x0, sizeof(struct collection_match_rule));
3266 rule->statematchtype = state_match;
3267 rule->attributematchtype = attrib_match;
3268 rule->rolematchtype = role_match;
3269 rule->interfacematchtype = ifc_match;
3270 rule->reverse = reverse;
3272 if (!eldbus_message_iter_fixed_array_get(states_iter, 'i', &array, &array_count))
3275 //Roles according to libatspi impementation are transferred in 2-int element fixed bit array
3276 if (array_count != 2)
3278 ERR("Unexpected states array size");
3281 uint64_t states = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3282 rule->states = _atspi_state_set_to_elm_atspi_state_set(states);
3284 //Roles according to libatspi impementation are transferred in 4-int element fixed bit array
3285 if (!eldbus_message_iter_fixed_array_get(role_iter, 'i', &array, &array_count))
3288 if (array_count != 4)
3290 ERR("Unexpected roles array size");
3294 //convert atspi roles to elm_roles
3295 rule->roles[0] = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3296 rule->roles[1] = ((uint64_t)array[2] | ((uint64_t)array[3] << 32));
3298 _collection_roles_convert(rule->roles);
3300 //Get matching properties
3301 while (eldbus_message_iter_get_and_next(attrib_iter, '{', &iter_arg))
3303 const char *key, *value;
3304 if (eldbus_message_iter_arguments_get(iter_arg, "ss", &key, &value))
3306 Elm_Atspi_Attribute *attrib = calloc(sizeof(Elm_Atspi_Attribute), 1);
3307 attrib->key = eina_stringshare_add(key);
3308 attrib->value = eina_stringshare_add(value);
3309 rule->attributes = eina_list_append(rule->attributes, attrib);
3313 //Get interfaces to match
3314 while (eldbus_message_iter_get_and_next(ifc_iter, 's', &ifc_name))
3316 const Eo_Class *class = NULL;
3317 if (!strcmp(ifc_name, "action"))
3318 class = ELM_INTERFACE_ATSPI_ACTION_MIXIN;
3319 else if (!strcmp(ifc_name, "component"))
3320 class = ELM_INTERFACE_ATSPI_COMPONENT_MIXIN;
3321 else if (!strcmp(ifc_name, "editabletext"))
3322 class = ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE;
3323 else if (!strcmp(ifc_name, "text"))
3324 class = ELM_INTERFACE_ATSPI_TEXT_INTERFACE;
3325 else if (!strcmp(ifc_name, "image"))
3326 class = ELM_INTERFACE_ATSPI_SELECTION_INTERFACE;
3327 else if (!strcmp(ifc_name, "value"))
3328 class = ELM_INTERFACE_ATSPI_VALUE_INTERFACE;
3331 rule->ifaces = eina_list_append(rule->ifaces, class);
3334 _collection_match_rule_free(rule);
3343 _collection_match_interfaces_helper(Eo *obj, Eina_List *ifcs, Eina_Bool condition, Eina_Bool ret_if_true, Eina_Bool ret_if_false)
3348 EINA_LIST_FOREACH(ifcs, l, class)
3350 if (eo_isa(obj, class) == condition)
3353 return ret_if_false;
3357 _collection_match_interfaces_lookup(Eo *obj, struct collection_match_rule *rule)
3359 Eina_Bool ret = EINA_FALSE;
3361 switch (rule->interfacematchtype)
3363 case ATSPI_Collection_MATCH_INVALID:
3366 case ATSPI_Collection_MATCH_ALL:
3367 ret = _collection_match_interfaces_helper(
3368 obj, rule->ifaces, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3370 case ATSPI_Collection_MATCH_ANY:
3371 ret = _collection_match_interfaces_helper(
3372 obj, rule->ifaces, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3374 case ATSPI_Collection_MATCH_NONE:
3375 ret = _collection_match_interfaces_helper(
3376 obj, rule->ifaces, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3385 _collection_match_states_lookup(Eo *obj, struct collection_match_rule *rule)
3387 Eina_Bool ret = EINA_FALSE;
3388 Elm_Atspi_State_Set ss;
3390 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
3392 switch (rule->statematchtype)
3394 case ATSPI_Collection_MATCH_INVALID:
3397 case ATSPI_Collection_MATCH_ALL:
3398 ret = (ss & rule->states) == rule->states;
3400 case ATSPI_Collection_MATCH_ANY:
3401 ret = (ss & rule->states) > 0;
3403 case ATSPI_Collection_MATCH_NONE:
3404 ret = (ss & rule->states) == 0;
3414 _collection_match_roles_lookup(Eo *obj, struct collection_match_rule *rule)
3416 Eina_Bool ret = EINA_FALSE;
3417 Elm_Atspi_Role role;
3420 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
3425 role_set = rule->roles[1];
3428 role_set = rule->roles[0];
3432 ERR("Elm_Atspi_Role enum value exceeds 127. Unable to compare with roles bit field.");
3436 switch (rule->rolematchtype)
3438 case ATSPI_Collection_MATCH_INVALID:
3441 case ATSPI_Collection_MATCH_ALL:
3442 case ATSPI_Collection_MATCH_ANY:
3443 ret = (role_set & (1ULL << role)) > 0;
3445 case ATSPI_Collection_MATCH_NONE:
3446 ret = (role_set & (1ULL << role)) == 0;
3456 _collection_match_attributes_helper(Eina_List *obj_attribs, Eina_List *attribs, Eina_Bool compare, Eina_Bool ret_if_compare, Eina_Bool ret_default)
3459 Elm_Atspi_Attribute *attr, *attr2;
3461 EINA_LIST_FOREACH(attribs, l, attr)
3463 EINA_LIST_FOREACH(obj_attribs, l2, attr2)
3465 if ((attr->key && attr2->key &&
3466 attr->value && attr2->value &&
3467 !strcmp(attr->key, attr2->key) &&
3468 !strcmp(attr->value, attr2->value)) == compare)
3470 return ret_if_compare;
3479 _collection_match_attributes_lookup(Eo *obj, struct collection_match_rule *rule)
3481 Eina_Bool ret = EINA_FALSE;
3482 Eina_List *obj_attribs;
3484 eo_do(obj, obj_attribs = elm_interface_atspi_accessible_attributes_get());
3486 switch (rule->attributematchtype)
3488 case ATSPI_Collection_MATCH_INVALID:
3491 case ATSPI_Collection_MATCH_ALL:
3492 ret = _collection_match_attributes_helper(
3493 obj_attribs, rule->attributes, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3495 case ATSPI_Collection_MATCH_ANY:
3496 ret = _collection_match_attributes_helper(
3497 obj_attribs, rule->attributes, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3499 case ATSPI_Collection_MATCH_NONE:
3500 ret = _collection_match_attributes_helper(
3501 obj_attribs, rule->attributes, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3507 elm_atspi_attributes_list_free(obj_attribs);
3513 _collection_sort_order_canonical(struct collection_match_rule *rule, Eina_List **ls,
3515 Eo *obj, long index, Eina_Bool flag,
3516 Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3519 Eina_List *children;
3520 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
3521 long acount = eina_list_count(children);
3522 Eina_Bool prev = pobj ? EINA_TRUE : EINA_FALSE;
3524 for (; i < acount && (max == 0 || count < max); i++)
3526 Eo *child = eina_list_nth(children, i);
3528 if (prev && child == pobj)
3530 eina_list_free(children);
3534 if (flag && _collection_match_interfaces_lookup(child, rule)
3535 && _collection_match_states_lookup(child, rule)
3536 && _collection_match_roles_lookup(child, rule)
3537 && _collection_match_attributes_lookup(child, rule))
3539 *ls = eina_list_append(*ls, child);
3546 if (recurse && traverse)
3547 count = _collection_sort_order_canonical(rule, ls, count,
3548 max, child, 0, EINA_TRUE,
3549 pobj, recurse, traverse);
3551 eina_list_free(children);
3556 _collection_sort_order_reverse_canonical(struct collection_match_rule *rule, Eina_List **ls,
3557 int count, int max, Eo *obj, Eina_Bool flag, Eo *pobj)
3559 Eo *nextobj, *parent;
3561 Eina_List *children;
3563 /* This breaks us out of the recursion. */
3564 if (!obj || obj == pobj)
3569 /* Add to the list if it matches */
3570 if (flag && _collection_match_interfaces_lookup(obj, rule)
3571 && _collection_match_states_lookup(obj, rule)
3572 && _collection_match_roles_lookup(obj, rule)
3573 && _collection_match_attributes_lookup(obj, rule)
3574 && (max == 0 || count < max))
3576 *ls = eina_list_append(*ls, obj);
3583 /* Get the current nodes index in it's parent and the parent object. */
3585 indexinparent = elm_interface_atspi_accessible_index_in_parent_get(),
3586 parent = elm_interface_atspi_accessible_parent_get());
3588 if ((indexinparent > 0) && ((max == 0) || (count < max)))
3590 /* there are still some siblings to visit so get the previous sibling
3591 and get it's last descendant.
3592 First, get the previous sibling */
3593 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
3594 nextobj = eina_list_nth(children, indexinparent - 1);
3595 eina_list_free(children);
3597 /* Now, drill down the right side to the last descendant */
3599 eo_do(nextobj, children = elm_interface_atspi_accessible_children_get());
3600 if (children) nextobj = eina_list_last_data_get(children);
3601 eina_list_free(children);
3604 /* recurse with the last descendant */
3605 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3606 nextobj, EINA_TRUE, pobj);
3608 else if (max == 0 || count < max)
3610 /* no more siblings so next node must be the parent */
3611 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3612 parent, EINA_TRUE, pobj);
3619 _collection_inbackorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3622 *list = eina_list_append(*list, obj);
3624 _collection_sort_order_reverse_canonical(rule, list, 0, max, obj, EINA_TRUE, collection);
3626 *list = eina_list_remove_list(*list, *list);
3632 _collection_inorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3633 int count, int max, Eo *obj, Eina_Bool traverse)
3637 count = _collection_sort_order_canonical(rule, list, count, max, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3639 while ((max == 0 || count < max) && obj && obj != collection)
3643 parent = elm_interface_atspi_accessible_parent_get(),
3644 idx = elm_interface_atspi_accessible_index_in_parent_get());
3645 count = _collection_sort_order_canonical(rule, list, count, max, parent,
3646 idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3650 if (max == 0 || count < max)
3651 count = _collection_sort_order_canonical(rule, list, count, max,
3652 obj, idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3658 _collection_query(struct collection_match_rule *rule, AtspiCollectionSortOrder sortby,
3659 Eina_List **list, int count, int max, Eo *obj, long index,
3660 Eina_Bool flag, Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3664 case ATSPI_Collection_SORT_ORDER_CANONICAL:
3665 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3666 pobj, recurse, traverse);
3668 case ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL:
3669 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3670 pobj, recurse, traverse);
3671 *list = eina_list_reverse(*list);
3675 WRN("Unhandled sort method");
3681 static Eldbus_Message*
3682 _collection_return_msg_from_list(Elm_Atspi_Bridge *bridge, const Eldbus_Message *msg, const Eina_List *objs)
3684 Eldbus_Message *ret;
3686 Eldbus_Message_Iter *iter, *array_iter;
3689 ret = eldbus_message_method_return_new(msg);
3690 if (!ret) return NULL;
3692 iter = eldbus_message_iter_get(ret);
3693 array_iter = eldbus_message_iter_container_new(iter, 'a', "(so)");
3695 EINA_LIST_FOREACH(objs, l, obj)
3697 _bridge_object_register(bridge, obj);
3698 _bridge_iter_object_reference_append(bridge, array_iter, obj);
3701 eldbus_message_iter_container_close(iter, array_iter);
3706 _collection_get_matches_from_handle(Eo *collection, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, int max, Eina_Bool traverse)
3708 Eina_List *result = NULL;
3714 case ATSPI_Collection_TREE_INORDER:
3715 _collection_inorder(collection, rule, &result, 0, max, current, traverse);
3716 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3717 result = eina_list_reverse(result);
3719 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3721 idx = elm_interface_atspi_accessible_index_in_parent_get(),
3722 parent = elm_interface_atspi_accessible_parent_get());
3723 _collection_query(rule, sortby, &result, 0, max, parent, idx, EINA_FALSE, NULL, EINA_TRUE, traverse);
3725 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3726 _collection_query(rule, sortby, &result, 0, max, current, 0, EINA_FALSE, NULL, EINA_TRUE, traverse);
3729 ERR("Tree parameter value not handled");
3735 static Eldbus_Message*
3736 _collection_get_matches_from(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3738 const char *obj_path = eldbus_message_path_get(msg);
3739 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3740 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3741 Eldbus_Message *ret;
3742 Eldbus_Message_Iter *iter, *rule_iter;
3743 struct collection_match_rule rule;
3745 AtspiCollectionTreeTraversalType tree;
3747 AtspiCollectionSortOrder sortby;
3748 Eina_List *result = NULL;
3750 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3752 iter = eldbus_message_iter_get(msg);
3753 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3755 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uuib", &obj_path, &rule_iter, &sortby, &tree, &count, &traverse))
3757 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3760 current = _bridge_object_from_path(bridge, obj_path);
3762 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3764 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3765 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3767 result = _collection_get_matches_from_handle(obj, current, &rule, sortby, tree, count, traverse);
3768 ret = _collection_return_msg_from_list(bridge, msg, result);
3770 eina_list_free(result);
3771 _collection_match_rule_free(&rule);
3777 _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)
3779 Eina_List *result = NULL;
3780 Eo *collection = obj;
3783 eo_do(obj, collection = elm_interface_atspi_accessible_parent_get());
3787 case ATSPI_Collection_TREE_INORDER:
3788 _collection_inbackorder(obj, rule, &result, max, current);
3789 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3790 result = eina_list_reverse(result);
3792 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3793 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3795 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3796 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3799 ERR("Tree parameter value not handled");
3806 static Eldbus_Message*
3807 _collection_get_matches_to(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3809 const char *obj_path = eldbus_message_path_get(msg);
3810 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3811 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3812 Eldbus_Message *ret;
3813 Eldbus_Message_Iter *iter, *rule_iter;
3814 struct collection_match_rule rule;
3816 AtspiCollectionTreeTraversalType tree;
3818 AtspiCollectionSortOrder sortby;
3819 Eina_List *result = NULL;
3822 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3824 iter = eldbus_message_iter_get(msg);
3825 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3827 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uubib", &obj_path, &rule_iter, &sortby, &tree, &limit, &count, &traverse))
3829 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, tree, limit count or traverse values.");
3832 current = _bridge_object_from_path(bridge, obj_path);
3834 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3836 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3837 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3839 result = _collection_get_matches_to_handle(obj, current, &rule, sortby, tree, limit, count, traverse);
3840 ret = _collection_return_msg_from_list(bridge, msg, result);
3842 eina_list_free(result);
3843 _collection_match_rule_free(&rule);
3848 static Eldbus_Message*
3849 _collection_get_matches(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
3851 const char *obj_path = eldbus_message_path_get(msg);
3852 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3853 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3854 Eldbus_Message *ret;
3855 Eldbus_Message_Iter *iter, *rule_iter;
3856 struct collection_match_rule rule;
3859 AtspiCollectionSortOrder sortby;
3860 Eina_List *result = NULL;
3862 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3864 iter = eldbus_message_iter_get(msg);
3865 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3867 if (!eldbus_message_iter_arguments_get(iter, "(aiia{ss}iaiiasib)uib", &rule_iter, &sortby, &count, &traverse))
3869 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3872 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3873 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3875 _collection_query(&rule, sortby, &result, 0, count, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3877 ret = _collection_return_msg_from_list(bridge, msg, result);
3879 eina_list_free(result);
3880 _collection_match_rule_free(&rule);
3885 static const Eldbus_Method collection_methods[] = {
3887 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3888 {"u", "sortby"}, {"u", "tree"}, {"i", "count"}, {"b", "traverse"}),
3889 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_from, 0 },
3891 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3892 {"u", "sortby"}, {"u", "tree"}, {"b", "limit_scope"},
3893 {"i", "count"}, {"b", "traverse"}),
3894 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_to, 0 },
3896 ELDBUS_ARGS({"(aiia{ss}iaiiasib)", "match_rule"},
3897 {"u", "sortby"}, {"i", "count"}, {"b", "traverse"}),
3898 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches, 0 },
3899 { NULL, NULL, NULL, NULL, 0 }
3902 static const Eldbus_Service_Interface_Desc collection_iface_desc = {
3903 ATSPI_DBUS_INTERFACE_COLLECTION, collection_methods, NULL, NULL, NULL, NULL
3907 _object_get_bus_name_and_path(Eo *bridge, const Eo *obj, const char **bus_name, const char **path)
3909 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
3911 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
3912 if (eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
3914 const char *pbus = "", *ppath = ATSPI_DBUS_PATH_NULL;
3915 eo_do(obj, elm_obj_atspi_proxy_address_get(&pbus, &ppath));
3918 if (bus_name) *bus_name = pbus;
3919 if (path) *path = ppath;
3922 DBG("Invalid proxy address! Address not set before connecting/listening. Or after proxy is removed.");
3924 if (bus_name) *bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
3925 if (path) *path = _bridge_path_from_object(bridge, obj);
3930 _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj)
3932 EINA_SAFETY_ON_NULL_RETURN(iter);
3934 const char *pbus = NULL, *ppath = NULL;
3935 _object_get_bus_name_and_path(bridge, obj, &pbus, &ppath);
3936 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3937 eldbus_message_iter_basic_append(iter_struct, 's', pbus);
3938 eldbus_message_iter_basic_append(iter_struct, 'o', ppath);
3939 eldbus_message_iter_container_close(iter, iter_struct);
3943 _object_desktop_reference_append(Eldbus_Message_Iter *iter)
3945 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3946 EINA_SAFETY_ON_NULL_RETURN(iter);
3948 eldbus_message_iter_basic_append(iter_struct, 's', ATSPI_DBUS_NAME_REGISTRY);
3949 eldbus_message_iter_basic_append(iter_struct, 'o', ATSPI_DBUS_PATH_ROOT);
3950 eldbus_message_iter_container_close(iter, iter_struct);
3954 _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj)
3956 Eldbus_Message_Iter *iter_array;
3957 iter_array = eldbus_message_iter_container_new(iter, 'a', "s");
3958 if (!iter_array) return;
3960 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
3962 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE);
3963 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COLLECTION);
3965 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN))
3966 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACTION);
3967 if (eo_isa(obj, ELM_ATSPI_APP_OBJECT_CLASS))
3968 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_APPLICATION);
3969 if (eo_isa(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN))
3970 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COMPONENT);
3971 if (eo_isa(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE))
3972 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_EDITABLE_TEXT);
3973 if (eo_isa(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN))
3974 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_IMAGE);
3975 if (eo_isa(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
3976 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_SELECTION);
3977 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
3978 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_TEXT);
3979 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
3980 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_VALUE);
3982 eldbus_message_iter_container_close(iter, iter_array);
3986 _cache_item_reference_append_cb(Eo *bridge, Eo *data, Eldbus_Message_Iter *iter_array)
3988 if (!eo_ref_get(data) || eo_destructed_is(data))
3991 Eldbus_Message_Iter *iter_struct, *iter_sub_array;
3992 Elm_Atspi_State_Set states;
3993 Elm_Atspi_Role role;
3994 Eo *root = elm_atspi_bridge_root_get(bridge);
3996 eo_do(data, role = elm_interface_atspi_accessible_role_get());
3998 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
3999 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_struct, EINA_TRUE);
4001 /* Marshall object path */
4002 _bridge_iter_object_reference_append(bridge, iter_struct, data);
4004 /* Marshall application */
4005 _bridge_iter_object_reference_append(bridge, iter_struct, root);
4008 eo_do(data, parent = elm_interface_atspi_accessible_parent_get());
4009 /* Marshall parent */
4010 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
4011 _object_desktop_reference_append(iter_struct);
4013 _bridge_iter_object_reference_append(bridge, iter_struct, parent);
4015 /* Marshall children */
4016 Eina_List *children_list = NULL, *l;
4019 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
4020 Elm_Atspi_State_Set ss;
4021 eo_do(data, ss = elm_interface_atspi_accessible_state_set_get());
4023 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
4024 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
4026 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
4027 if (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
4029 eo_do(data, children_list = elm_interface_atspi_accessible_children_get());
4031 EINA_LIST_FOREACH(children_list, l, child)
4032 _bridge_iter_object_reference_append(bridge, iter_sub_array, child);
4034 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
4035 eina_list_free(children_list);
4039 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4041 /* Marshall interfaces */
4042 _iter_interfaces_append(iter_struct, data);
4045 const char *name = NULL;
4046 eo_do(data, name = elm_interface_atspi_accessible_name_get());
4050 eldbus_message_iter_basic_append(iter_struct, 's', name);
4053 eldbus_message_iter_basic_append(iter_struct, 'u', role);
4055 /* Marshall description */
4056 const char* descritpion = NULL;
4057 eo_do(data, descritpion = elm_interface_atspi_accessible_description_get());
4060 eldbus_message_iter_basic_append(iter_struct, 's', descritpion);
4062 /* Marshall state set */
4063 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "u");
4064 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
4066 eo_do(data, states = elm_interface_atspi_accessible_state_set_get());
4068 unsigned int s1 = states & 0xFFFFFFFF;
4069 unsigned int s2 = (states >> 32) & 0xFFFFFFFF;
4070 eldbus_message_iter_basic_append(iter_sub_array, 'u', s1);
4071 eldbus_message_iter_basic_append(iter_sub_array, 'u', s2);
4073 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4074 eldbus_message_iter_container_close(iter_array, iter_struct);
4079 if (iter_struct) eldbus_message_iter_del(iter_struct);
4083 static Eldbus_Message *
4084 _cache_get_items(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
4086 Eldbus_Message_Iter *iter, *iter_array;
4087 Eldbus_Message *ret;
4088 Eina_List *to_process;
4091 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4092 if (!bridge) return NULL;
4094 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4096 ret = eldbus_message_method_return_new(msg);
4097 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4099 iter = eldbus_message_iter_get(ret);
4100 iter_array = eldbus_message_iter_container_new(iter, 'a', CACHE_ITEM_SIGNATURE);
4101 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
4103 eo_do(bridge, root = elm_obj_atspi_bridge_root_get());
4104 to_process = eina_list_append(NULL, root);
4108 Eo *obj = eina_list_data_get(to_process);
4109 to_process = eina_list_remove_list(to_process, to_process);
4110 _cache_item_reference_append_cb(bridge, obj, iter_array);
4111 _bridge_object_register(bridge, obj);
4113 Eina_List *children;
4114 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
4115 to_process = eina_list_merge(to_process, children);
4118 eldbus_message_iter_container_close(iter, iter_array);
4122 if (ret) eldbus_message_unref(ret);
4126 static const Eldbus_Method cache_methods[] = {
4127 { "GetItems", NULL, ELDBUS_ARGS({CACHE_ITEM_SIGNATURE, "items"}), _cache_get_items, 0 },
4128 { NULL, NULL, NULL, NULL, 0 }
4131 static const Eldbus_Signal cache_signals[] = {
4132 [ATSPI_OBJECT_CHILD_ADDED] = { "AddAccessible", ELDBUS_ARGS({"((so)(so)a(so)assusau)", "added"}), 0},
4133 [ATSPI_OBJECT_CHILD_REMOVED] = { "RemoveAccessible", ELDBUS_ARGS({ "(so)", "removed" }), 0},
4137 static const Eldbus_Service_Interface_Desc cache_iface_desc = {
4138 ATSPI_DBUS_INTERFACE_CACHE, cache_methods, cache_signals, NULL, NULL, NULL
4141 // Component interface
4142 static Eldbus_Message *
4143 _component_contains(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4145 const char *obj_path = eldbus_message_path_get(msg);
4146 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4147 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4149 Eina_Bool contains = EINA_FALSE;
4150 AtspiCoordType coord_type;
4151 Eldbus_Message *ret;
4153 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4155 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4156 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4158 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4159 eo_do(obj, contains = elm_interface_atspi_component_contains(type, x, y));
4161 ret = eldbus_message_method_return_new(msg);
4162 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4164 eldbus_message_arguments_append(ret, "b", contains);
4169 static Eldbus_Message *
4170 _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4172 const char *obj_path = eldbus_message_path_get(msg);
4173 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4174 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4175 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4177 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4179 Eo *accessible = NULL;
4180 AtspiCoordType coord_type;
4181 Eldbus_Message *ret;
4182 Eldbus_Message_Iter *iter;
4184 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4186 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
4187 if (_ee_obscured_get(obj))
4188 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
4191 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4192 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4194 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4195 Evas_Object *top = elm_object_top_widget_get(obj);
4198 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
4204 ret = eldbus_message_method_return_new(msg);
4205 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4207 iter = eldbus_message_iter_get(ret);
4208 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4209 eo_do(obj, accessible = elm_interface_atspi_component_accessible_at_point_get(type, x, y));
4210 _bridge_iter_object_reference_append(bridge, iter, accessible);
4211 _bridge_object_register(bridge, accessible);
4216 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
4218 NEIGHBOR_SEARCH_MODE_NORMAL = 0,
4219 NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT = 1,
4220 NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING = 2,
4221 NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE = 3,
4222 } GetNeighborSearchMode;
4224 typedef struct accessibility_navigation_pointer_table {
4225 AtspiRole (*object_get_role)(struct accessibility_navigation_pointer_table *t, void *ptr);
4226 uint64_t (*object_get_state_set)(struct accessibility_navigation_pointer_table *t, void *ptr);
4227 void *(*get_object_in_relation_by_type)(struct accessibility_navigation_pointer_table *t, void *ptr, AtspiRelationType type);
4228 unsigned char (*object_is_zero_size)(struct accessibility_navigation_pointer_table *t, void *ptr);
4229 void *(*get_parent)(struct accessibility_navigation_pointer_table *t, void *ptr);
4230 unsigned char (*object_is_scrollable)(struct accessibility_navigation_pointer_table *t, void *ptr);
4231 void *(*get_object_at_point)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4232 unsigned char (*object_contains)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4233 unsigned char (*object_is_proxy)(struct accessibility_navigation_pointer_table *t, void *ptr);
4234 } accessibility_navigation_pointer_table;
4236 #define CALL(fncname, ...) table->fncname(table, __VA_ARGS__)
4237 static unsigned char _accept_object_check_role(accessibility_navigation_pointer_table *table EINA_UNUSED, void *obj)
4239 return _elm_widget_atspi_role_acceptable_check(obj);
4242 static unsigned char _state_set_is_set(uint64_t state_set, AtspiStateType state)
4244 return (state_set & ((uint64_t)1 << (unsigned int)state)) != 0;
4247 static unsigned char _object_is_defunct(accessibility_navigation_pointer_table *table, void *ptr)
4249 uint64_t states = CALL(object_get_state_set, ptr);
4250 return _state_set_is_set(states, ATSPI_STATE_DEFUNCT);
4253 static unsigned char _object_role_is_acceptable_when_navigating_next_prev(accessibility_navigation_pointer_table *table, void *obj)
4255 AtspiRole role = CALL(object_get_role, obj);
4256 return role != ATSPI_ROLE_POPUP_MENU && role != ATSPI_ROLE_DIALOG;
4259 static void *_get_object_in_relation_flow(accessibility_navigation_pointer_table *table, void *source, unsigned char forward)
4261 return CALL(get_object_in_relation_by_type, source, forward ? ATSPI_RELATION_FLOWS_TO : ATSPI_RELATION_FLOWS_FROM);
4264 static unsigned char _object_is_item(accessibility_navigation_pointer_table *table, void *obj)
4266 AtspiRole role = CALL(object_get_role, obj);
4267 return role == ATSPI_ROLE_LIST_ITEM || role == ATSPI_ROLE_MENU_ITEM;
4270 static unsigned char _object_is_highlightable(accessibility_navigation_pointer_table *table, void *obj)
4272 uint64_t state_set = CALL(object_get_state_set, obj);
4273 return _state_set_is_set(state_set, ATSPI_STATE_HIGHLIGHTABLE);
4276 static unsigned char _object_is_visible(accessibility_navigation_pointer_table *table, void *obj)
4278 uint64_t state_set = CALL(object_get_state_set, obj);
4279 return _state_set_is_set(state_set, ATSPI_STATE_VISIBLE);
4282 static unsigned char _object_is_showing(accessibility_navigation_pointer_table *table, void *obj)
4284 uint64_t state_set = CALL(object_get_state_set, obj);
4285 return _state_set_is_set(state_set, ATSPI_STATE_SHOWING);
4288 static unsigned char _object_is_collapsed(accessibility_navigation_pointer_table *table, void *obj)
4290 uint64_t state_set = CALL(object_get_state_set, obj);
4292 _state_set_is_set(state_set, ATSPI_STATE_EXPANDABLE) &&
4293 !_state_set_is_set(state_set, ATSPI_STATE_EXPANDED);
4296 static unsigned char _object_has_modal_state(accessibility_navigation_pointer_table *table, void *obj)
4298 uint64_t state_set = CALL(object_get_state_set, obj);
4299 return _state_set_is_set(state_set, ATSPI_STATE_MODAL);
4302 static unsigned char _object_is_zero_size(accessibility_navigation_pointer_table *table, void *obj)
4304 return CALL(object_is_zero_size, obj);
4307 static void *_get_scrollable_parent(accessibility_navigation_pointer_table *table, void *obj)
4311 obj = CALL(get_parent, obj);
4312 if (obj && CALL(object_is_scrollable, obj)) return obj;
4316 static unsigned char _accept_object(accessibility_navigation_pointer_table *table, void *obj)
4319 if (!_object_is_visible(table, obj)) return 0;
4320 if (!_accept_object_check_role(table, obj)) return 0;
4321 if (CALL(get_object_in_relation_by_type, obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0;
4322 if (!_object_is_highlightable(table, obj)) return 0;
4324 if (_get_scrollable_parent(table, obj) != NULL)
4326 void *parent = CALL(get_parent, obj);
4330 return !_object_is_item(table, obj) || !_object_is_collapsed(table, parent);
4335 if (_object_is_zero_size(table, obj)) return 0;
4336 if (!_object_is_showing(table, obj)) return 0;
4341 /* The target cannot be a parent of root */
4342 static Eina_Bool _target_validation_check(Eo *target, Eo *root)
4345 eo_do(root, parent = elm_interface_atspi_accessible_parent_get());
4349 if (parent == target) return EINA_FALSE;
4350 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4356 static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigation_pointer_table *table,
4357 void *root, int x, int y, unsigned char coordinates_are_screen_based)
4359 if (!root) return NULL;
4360 void *prev_root = root;
4362 void *return_value = NULL;
4365 void *target = CALL(get_object_at_point, root, x, y, coordinates_are_screen_based);
4367 if (target == root || target == prev_root) break;
4368 if (!_target_validation_check(target, root)) break;
4370 // always return proxy, so atspi lib can call on it again
4371 if (CALL(object_is_proxy, target)) return target;
4374 void *relation_obj = CALL(get_object_in_relation_by_type, root, ATSPI_RELATION_CONTROLLED_BY);
4375 unsigned char contains = 0;
4378 contains = CALL(object_contains, relation_obj, x, y, coordinates_are_screen_based);
4379 if (contains) root = relation_obj;
4382 if (_accept_object(table, root))
4384 return_value = root;
4385 if (contains) break;
4389 if (return_value && _object_has_modal_state(table, return_value)) return_value = NULL;
4390 return return_value;
4393 static void *_find_non_defunct_child(accessibility_navigation_pointer_table *table,
4394 Eina_List *children, unsigned int current_index, unsigned char forward)
4396 unsigned int children_count = eina_list_count(children);
4397 for(; current_index < children_count; forward ? ++current_index : --current_index)
4399 void *n = eina_list_nth(children, current_index);
4400 if (n && !_object_is_defunct(table, n)) return n;
4405 static void *_directional_depth_first_search_try_non_defunct_child(accessibility_navigation_pointer_table *table,
4406 void *node, Eina_List *children, unsigned char forward)
4408 unsigned int children_count = eina_list_count(children);
4409 if (children_count > 0)
4411 unsigned char is_showing = _get_scrollable_parent(table, node) == NULL ? _object_is_showing(table, node) : 1;
4414 return _find_non_defunct_child(table, children, forward ? 0 : children_count - 1, forward);
4420 static Eina_List *_scrollable_parent_list_get(Eo *obj)
4422 Eina_List *ret = NULL;
4427 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
4430 if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4432 ret = eina_list_append(ret, parent);
4434 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4441 static void _viewport_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
4443 eo_do(obj, elm_interface_scrollable_content_viewport_geometry_get(x, y, w, h));
4444 /* widget implements scrollable interface but does not use scoller
4445 in this case, use widget geometry */
4446 if (*w == 0 || *h == 0)
4448 INF("%s is zero sized content viewport", eo_class_name_get(eo_class_get(obj)));
4449 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_FALSE, x, y, w, h));
4454 _new_scrollable_parent_viewport_geometry_get(Eo *node, Eo *start,
4455 int *x, int *y, int *w, int *h)
4457 Eina_Bool ret = EINA_FALSE;
4461 n_spl = _scrollable_parent_list_get(node);
4462 s_spl = _scrollable_parent_list_get(start);
4466 EINA_LIST_FOREACH(s_spl, l, sp)
4468 n_spl = eina_list_remove(n_spl, sp);
4471 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4473 unsigned int count = eina_list_count(n_spl);
4476 sp = eina_list_nth(n_spl, count - 1);
4477 _viewport_geometry_get(sp, &sx, &sy, &sw, &sh);
4489 static Eina_List *_valid_children_get(Eina_List *children, Eo *start, Eo *root)
4491 /* condition to find first(last) object regardless of scrollable parent.
4492 looping navigation does not care scrollable parent.
4493 1. currently highlighted object exists
4494 2. both start and root are same */
4495 Eo *current = _elm_object_accessibility_currently_highlighted_get();
4496 if (current && start == root) return children;
4499 child = eina_list_nth(children, 0);
4503 Evas_Coord x = 0, y = 0, w = 0, h = 0;
4504 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4506 if (_new_scrollable_parent_viewport_geometry_get(child, start,
4507 &sx, &sy, &sw, &sh))
4509 Eina_List *l, *l_next;
4510 EINA_LIST_FOREACH_SAFE(children, l, l_next, child)
4513 elm_interface_atspi_component_extents_get(EINA_FALSE,
4515 if (w == 0 || h == 0 ||
4516 !ELM_RECTS_INTERSECT(x, y, w, h, sx, sy, sw, sh))
4517 children = eina_list_remove_list(children, l);
4524 static void *_get_next_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4525 void *obj, void *start, void *root, unsigned char forward)
4527 if (!obj) return NULL;
4528 void *parent = CALL(get_parent, obj);
4529 if (!parent) return NULL;
4531 Eina_List *children;
4532 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
4533 children = _valid_children_get(children, start, root);
4535 unsigned int children_count = eina_list_count(children);
4536 if (children_count == 0)
4538 eina_list_free(children);
4541 unsigned int current = 0;
4542 for(; current < children_count && eina_list_nth(children, current) != obj; ++current) ;
4543 if (current >= children_count)
4545 eina_list_free(children);
4548 forward ? ++current : --current;
4549 void *ret = _find_non_defunct_child(table, children, current, forward);
4550 eina_list_free(children);
4555 _directional_depth_first_search_try_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4556 unsigned char *all_children_visited_ptr,
4557 void *node, void *start, void *root,
4558 unsigned char forward)
4562 void *sibling = _get_next_non_defunct_sibling(table, node, start, root, forward);
4563 if (sibling != NULL)
4566 *all_children_visited_ptr = 0;
4571 node = CALL(get_parent, node);
4572 if (node == NULL || node == root) return NULL;
4574 // in backward traversing stop the walk up on parent
4575 if (!forward) break;
4582 unsigned int current_search_size;
4583 unsigned int counter;
4584 } cycle_detection_data;
4586 void cycle_detection_initialize(cycle_detection_data *data, const void *key)
4590 data->current_search_size = 1;
4594 unsigned char cycle_detection_check_if_in_cycle(cycle_detection_data *data, const void *key)
4596 if (!data) return 1;
4597 if (data->key == key) return 1;
4598 if (--data->counter == 0)
4600 data->current_search_size <<= 1;
4601 if (data->current_search_size == 0) return 1;
4602 data->counter = data->current_search_size;
4611 if (eo_isa(obj, ELM_ACCESS_CLASS))
4613 Elm_Access_Info *info;
4615 info = _elm_access_info_get(obj);
4616 if (info && eo_isa(info->part_object, ELM_LAYOUT_CLASS))
4618 Eina_List *attrs, *l;
4619 Elm_Atspi_Attribute *attr;
4621 eo_do(info->part_object,
4622 attrs = elm_interface_atspi_accessible_attributes_get());
4623 EINA_LIST_FOREACH(attrs, l, attr)
4625 if (!strcmp(attr->key, "___PlugID"))
4627 elm_atspi_attributes_list_free(attrs);
4631 elm_atspi_attributes_list_free(attrs);
4638 _proxy_in_parent_get(Eo *obj)
4642 Eina_List *children_list = NULL;
4643 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4646 EINA_LIST_FOREACH(children_list, l, child)
4648 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4654 eina_list_free(children_list);
4660 _deputy_of_proxy_in_parent_get(Eo *obj)
4664 Eina_List *children_list = NULL;
4665 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4667 unsigned int index = 0;
4669 EINA_LIST_FOREACH(children_list, l, child)
4671 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4675 WRN("Proxy does not have deputy object");
4679 deputy = eina_list_nth(children_list, index - 1);
4684 eina_list_free(children_list);
4690 _check_chain_end_with_attribute(Eo *obj, unsigned char forward)
4692 Eina_List *attrs, *l;
4693 Elm_Atspi_Attribute *attr;
4694 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
4697 EINA_LIST_FOREACH(attrs, l, attr)
4699 if (!strcmp(attr->key, "relation_chain_end"))
4701 if (((!strcmp(attr->value, "prev,end")) && forward == 0) || ((!strcmp(attr->value, "next,end")) && forward == 1) || (!strcmp(attr->value, "prev,next,end")))
4703 elm_atspi_attributes_list_free(attrs);
4708 elm_atspi_attributes_list_free(attrs);
4712 static void *_calculate_neighbor_impl(accessibility_navigation_pointer_table *table, void *root, void *start, unsigned char forward, GetNeighborSearchMode search_mode)
4714 if (start && _check_chain_end_with_attribute(start, forward)) return start;
4715 if (root && _object_is_defunct(table, root)) return NULL;
4716 if (start && _object_is_defunct(table, start))
4722 if (search_mode == NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE)
4724 /* This only works if we navigate backward, and it is not possible to
4725 find in embedded process. In this case the deputy should be used */
4726 return _deputy_of_proxy_in_parent_get(start);
4729 void *node = start ? start : root;
4730 if (!node) return NULL;
4732 // initialization of all-children-visited flag for start node - we assume
4733 // that when we begin at start node and we navigate backward, then all children
4734 // are visited, so navigation will ignore start's children and go to
4735 // previous sibling available.
4736 /* Regarding condtion (start != root):
4737 The last object can be found only if all_children_visited is false.
4738 The start is same with root, when looking for the last object. */
4739 unsigned char all_children_visited = (start != root) && (search_mode != NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT && !forward);
4741 // true, if starting element should be ignored. this is only used in rare case of
4742 // recursive search failing to find an object.
4743 // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
4744 // element A algorithm has to descend into BUS_B and search element B and its children. this is done
4745 // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
4746 // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
4747 // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
4748 // this flag means, that object A was already checked previously and we should skip it and its children.
4749 unsigned char force_next = (search_mode == NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING);
4751 cycle_detection_data cycle_detection;
4752 cycle_detection_initialize(&cycle_detection, node);
4755 if (_object_is_defunct(table, node)) return NULL;
4757 // always accept proxy object from different world
4758 if (!force_next && CALL(object_is_proxy, node)) return node;
4760 Eina_List *children;
4761 eo_do(node, children = elm_interface_atspi_accessible_children_get());
4762 children = _valid_children_get(children, start, root);
4765 // 1. not start node
4766 // 2. parent after all children in backward traversing
4767 // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
4768 // Objects with those roles shouldnt be reachable, when navigating next / prev.
4769 unsigned char all_children_visited_or_moving_forward = (eina_list_count(children) == 0 || forward || all_children_visited);
4770 if (!force_next && node != start && all_children_visited_or_moving_forward && _accept_object(table, node))
4772 if (start == NULL || _object_role_is_acceptable_when_navigating_next_prev(table, node))
4774 eina_list_free(children);
4779 void *next_related_in_direction = !force_next ? _get_object_in_relation_flow(table, node, forward) : NULL;
4781 /* force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
4782 in this case the node is elm_layout which is parent of proxy object.
4783 There is an access object working for the proxy object, and the access
4784 object could have relation information. This relation information should
4785 be checked first before using the elm_layout as a node. */
4786 if (force_next && forward)
4789 deputy = _deputy_of_proxy_in_parent_get(node);
4790 next_related_in_direction =
4791 _get_object_in_relation_flow(table, deputy, forward);
4794 if (next_related_in_direction && _object_is_defunct(table, next_related_in_direction))
4795 next_related_in_direction = NULL;
4796 unsigned char want_cycle_detection = 0;
4797 if (next_related_in_direction)
4799 /* Check next_related_in_direction is deputy object */
4803 /* If the prev object is deputy, then go to inside of its proxy first */
4804 if (_deputy_is(next_related_in_direction))
4806 parent = elm_widget_parent_get(next_related_in_direction);
4807 next_related_in_direction =
4808 _proxy_in_parent_get(parent);
4813 /* If current object is deputy, and it has relation next object,
4814 then do not use the relation next object, and use proxy first */
4815 if (_deputy_is(node))
4817 parent = elm_widget_parent_get(node);
4818 next_related_in_direction =
4819 _proxy_in_parent_get(parent);
4823 node = next_related_in_direction;
4824 want_cycle_detection = 1;
4827 void *child = !force_next && !all_children_visited ?
4828 _directional_depth_first_search_try_non_defunct_child(table, node, children, forward) : NULL;
4829 if (child != NULL) want_cycle_detection = 1;
4832 if (!force_next && node == root)
4834 eina_list_free(children);
4837 all_children_visited = 1;
4838 child = _directional_depth_first_search_try_non_defunct_sibling(table, &all_children_visited, node, start, root, forward);
4844 if (want_cycle_detection && cycle_detection_check_if_in_cycle(&cycle_detection, node))
4846 eina_list_free(children);
4849 eina_list_free(children);
4854 typedef struct accessibility_navigation_pointer_table_impl {
4855 accessibility_navigation_pointer_table ptrs;
4857 } accessibility_navigation_pointer_table_impl;
4859 static AtspiRole _object_get_role_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4861 Elm_Atspi_Role role;
4863 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
4864 return _elm_role_to_atspi_role(role);
4867 static uint64_t _object_get_state_set_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4869 Elm_Atspi_State_Set states;
4871 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
4872 return _elm_atspi_state_set_to_atspi_state_set(states);
4875 static void *_get_object_in_relation_by_type_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr, AtspiRelationType type)
4879 const Eo *source = ptr;
4880 Elm_Atspi_Relation_Set relations;
4881 Elm_Atspi_Relation_Type expected_relation_type = _atspi_relation_to_elm_relation(type);
4882 eo_do(source, relations = elm_interface_atspi_accessible_relation_set_get());
4883 Elm_Atspi_Relation *rel;
4885 EINA_LIST_FOREACH(relations, l, rel)
4887 if (rel->type == expected_relation_type)
4889 Eina_List *last = eina_list_last(rel->objects);
4890 return eina_list_data_get(last);
4897 static unsigned char _object_is_zero_size_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4901 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_TRUE, &x, &y, &w, &h));
4902 return w == 0 || h == 0;
4905 unsigned char _object_is_scrollable_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4908 return eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
4911 void *_get_parent_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4913 Eo *obj = (Eo*)ptr, *ret_obj;
4914 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
4918 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)
4920 Eo *obj = (Eo*)ptr, *target;
4921 eo_do(obj, target = elm_interface_atspi_component_accessible_at_point_get(coordinates_are_screen_based, x, y));
4925 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)
4928 Eina_Bool return_value;
4929 eo_do(obj, return_value = elm_interface_atspi_component_contains(coordinates_are_screen_based, x, y));
4930 return return_value ? 1 : 0;
4933 unsigned char _object_is_proxy_impl(struct accessibility_navigation_pointer_table *table_, void *obj)
4935 accessibility_navigation_pointer_table_impl *table = (accessibility_navigation_pointer_table_impl*)table_;
4936 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(table->bridge, pd, 0);
4937 const char *our_bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
4938 const char *obj_bus_name;
4939 _object_get_bus_name_and_path(table->bridge, (Eo*)obj, &obj_bus_name, NULL);
4940 return our_bus_name && obj_bus_name && strcmp(our_bus_name, obj_bus_name) != 0;
4943 accessibility_navigation_pointer_table_impl construct_accessibility_navigation_pointer_table(Eo *bridge)
4945 accessibility_navigation_pointer_table_impl table;
4946 #define INIT(n) table.ptrs.n = _## n ## _impl
4947 INIT(object_get_role);
4948 INIT(object_get_state_set);
4949 INIT(get_object_in_relation_by_type);
4950 INIT(object_is_zero_size);
4952 INIT(object_is_scrollable);
4953 INIT(get_object_at_point);
4954 INIT(object_contains);
4955 INIT(object_is_proxy);
4957 table.bridge = bridge;
4962 static Eo *_calculate_navigable_accessible_at_point(Eo *bridge, Eo *root, Eina_Bool coord_type, int x, int y)
4964 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4965 Eo *result = (Eo*)_calculate_navigable_accessible_at_point_impl(&table.ptrs, root, x, y, coord_type ? 1 : 0);
4969 static Eo *_calculate_neighbor(Eo *bridge, Eo *root, Eo *start, Eina_Bool forward, int search_mode)
4971 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4972 Eo *result = (Eo*)_calculate_neighbor_impl(&table.ptrs, root, start, forward ? 1 : 0, (GetNeighborSearchMode)search_mode);
4978 static Eldbus_Message *
4979 _component_get_extents(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4981 const char *obj_path = eldbus_message_path_get(msg);
4982 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4983 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4985 AtspiCoordType coord_type;
4986 Eldbus_Message *ret;
4987 Eldbus_Message_Iter *iter, *iter_struct;
4989 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4991 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4992 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4994 ret = eldbus_message_method_return_new(msg);
4995 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4997 iter = eldbus_message_iter_get(ret);
4999 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5000 eo_do(obj, elm_interface_atspi_component_extents_get(type, &x, &y, &w, &h));
5001 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
5002 EINA_SAFETY_ON_NULL_GOTO(iter_struct, fail);
5004 eldbus_message_iter_basic_append(iter_struct, 'i', x);
5005 eldbus_message_iter_basic_append(iter_struct, 'i', y);
5006 eldbus_message_iter_basic_append(iter_struct, 'i', w);
5007 eldbus_message_iter_basic_append(iter_struct, 'i', h);
5009 eldbus_message_iter_container_close(iter, iter_struct);
5013 if (ret) eldbus_message_unref(ret);
5017 static Eldbus_Message *
5018 _component_get_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5020 const char *obj_path = eldbus_message_path_get(msg);
5021 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5022 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5024 AtspiCoordType coord_type;
5025 Eldbus_Message *ret;
5027 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5029 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
5030 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5032 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5033 eo_do(obj, elm_interface_atspi_component_position_get(type, &x, &y));
5035 ret = eldbus_message_method_return_new(msg);
5036 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5038 eldbus_message_arguments_append(ret, "i", x);
5039 eldbus_message_arguments_append(ret, "i", y);
5044 static Eldbus_Message *
5045 _component_get_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5047 const char *obj_path = eldbus_message_path_get(msg);
5048 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5049 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5051 Eldbus_Message *ret;
5053 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5055 eo_do(obj, elm_interface_atspi_component_size_get(&x, &y));
5057 ret = eldbus_message_method_return_new(msg);
5058 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5060 eldbus_message_arguments_append(ret, "i", x);
5061 eldbus_message_arguments_append(ret, "i", y);
5066 static AtspiComponentLayer
5067 _elm_layer_2_atspi_layer(int layer)
5069 if (layer <= ELM_OBJECT_LAYER_BACKGROUND) return ATSPI_LAYER_CANVAS;
5070 if (layer < ELM_OBJECT_LAYER_FOCUS) return ATSPI_LAYER_WIDGET;
5071 if (layer <= ELM_OBJECT_LAYER_TOOLTIP) return ATSPI_LAYER_POPUP;
5073 return ATSPI_LAYER_OVERLAY;
5076 static Eldbus_Message *
5077 _component_get_layer(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5079 const char *obj_path = eldbus_message_path_get(msg);
5080 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5081 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5083 Eldbus_Message *ret;
5084 AtspiComponentLayer atspi_layer;
5086 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5088 eo_do(obj, layer = elm_interface_atspi_component_layer_get());
5090 ret = eldbus_message_method_return_new(msg);
5091 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5093 atspi_layer = _elm_layer_2_atspi_layer(layer);
5094 eldbus_message_arguments_append(ret, "u", atspi_layer);
5099 static Eldbus_Message *
5100 _component_grab_focus(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5102 const char *obj_path = eldbus_message_path_get(msg);
5103 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5104 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5105 Eldbus_Message *ret;
5106 Eina_Bool focus = EINA_FALSE;
5109 return _dbus_invalid_ref_error_new(msg);
5111 eo_do(obj, focus = elm_interface_atspi_component_focus_grab());
5113 ret = eldbus_message_method_return_new(msg);
5114 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5116 eldbus_message_arguments_append(ret, "b", focus);
5121 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5122 static Eldbus_Message *
5123 _component_grab_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5125 const char *obj_path = eldbus_message_path_get(msg);
5126 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5127 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5128 Eldbus_Message *ret;
5129 Eina_Bool highlight = EINA_FALSE;
5131 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5133 eo_do(obj, highlight = elm_interface_atspi_component_highlight_grab());
5135 ret = eldbus_message_method_return_new(msg);
5136 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5138 eldbus_message_arguments_append(ret, "b", highlight);
5143 static Eldbus_Message *
5144 _component_clear_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5146 const char *obj_path = eldbus_message_path_get(msg);
5147 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5148 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5149 Eldbus_Message *ret;
5150 Eina_Bool highlight = EINA_FALSE;
5152 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5154 eo_do(obj, highlight = elm_interface_atspi_component_highlight_clear());
5156 ret = eldbus_message_method_return_new(msg);
5157 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5159 eldbus_message_arguments_append(ret, "b", highlight);
5165 static Eldbus_Message *
5166 _component_get_alpha(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5168 const char *obj_path = eldbus_message_path_get(msg);
5169 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5170 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5171 Eldbus_Message *ret;
5175 return _dbus_invalid_ref_error_new(msg);
5177 eo_do(obj, alpha = elm_interface_atspi_component_alpha_get());
5179 ret = eldbus_message_method_return_new(msg);
5180 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5182 eldbus_message_arguments_append(ret, "d", alpha);
5187 static Eldbus_Message *
5188 _component_set_extends(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5190 const char *obj_path = eldbus_message_path_get(msg);
5191 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5192 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5194 AtspiCoordType coord_type;
5195 Eldbus_Message *ret;
5196 Eina_Bool result = EINA_FALSE;
5198 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5200 if (!eldbus_message_arguments_get(msg, "iiiiu", &x, &y, &w, &h, &coord_type))
5201 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5203 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5204 eo_do(obj, result = elm_interface_atspi_component_extents_set(type, x, y, w, h));
5206 ret = eldbus_message_method_return_new(msg);
5207 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5209 eldbus_message_arguments_append(ret, "b", result);
5214 static Eldbus_Message *
5215 _component_set_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5217 const char *obj_path = eldbus_message_path_get(msg);
5218 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5219 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5221 Eina_Bool result = EINA_FALSE;
5222 AtspiCoordType coord_type;
5223 Eldbus_Message *ret;
5225 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5227 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
5228 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5230 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5231 eo_do(obj, result = elm_interface_atspi_component_position_set(type, x, y));
5233 ret = eldbus_message_method_return_new(msg);
5234 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5236 eldbus_message_arguments_append(ret, "b", result);
5241 static Eldbus_Message *
5242 _component_set_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5244 const char *obj_path = eldbus_message_path_get(msg);
5245 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5246 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5249 Eldbus_Message *ret;
5251 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5253 if (!eldbus_message_arguments_get(msg, "ii", &w, &h))
5254 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5256 eo_do(obj, result = elm_interface_atspi_component_size_set(w, h));
5258 ret = eldbus_message_method_return_new(msg);
5259 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5261 eldbus_message_arguments_append(ret, "b", result);
5266 static const Eldbus_Method component_methods[] = {
5267 { "Contains", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "contains"}), _component_contains, 0 },
5268 { "GetAccessibleAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)", "accessible"}), _component_get_accessible_at_point, 0 },
5269 { "GetExtents", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"(iiii)", "extents"}), _component_get_extents, 0 },
5270 { "GetPosition", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"i", "x"}, {"i","y"}), _component_get_position, 0 },
5271 { "GetSize", NULL, ELDBUS_ARGS({"i", "w"}, {"i", "h"}), _component_get_size, 0 },
5272 { "GetLayer", NULL, ELDBUS_ARGS({"u", "layer"}), _component_get_layer, 0 },
5273 // { "GetMDIZOrder", NULL, ELDBUS_ARGS({"n", "MDIZOrder"}), _component_get_mdizorder, 0 },
5274 { "GrabFocus", NULL, ELDBUS_ARGS({"b", "focus"}), _component_grab_focus, 0 },
5275 { "GetAlpha", NULL, ELDBUS_ARGS({"d", "alpha"}), _component_get_alpha, 0 },
5276 { "SetExtents", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "width"}, {"i", "height"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_extends, 0 },
5277 { "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
5278 { "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
5280 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5281 { "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
5282 { "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
5284 { NULL, NULL, NULL, NULL, 0 }
5287 static const Eldbus_Service_Interface_Desc component_iface_desc = {
5288 ATSPI_DBUS_INTERFACE_COMPONENT, component_methods, NULL, NULL, NULL, NULL
5292 _on_elm_atspi_bridge_app_register(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
5294 const char *errname, *errmsg;
5296 if (eldbus_message_error_get(msg, &errname, &errmsg))
5298 ERR("%s %s", errname, errmsg);
5301 DBG("Application successfuly registered at ATSPI2 bus.");
5305 _elm_atspi_bridge_app_register(Eo *bridge)
5307 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5309 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5310 ATSPI_DBUS_PATH_ROOT,
5311 ATSPI_DBUS_INTERFACE_SOCKET,
5313 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5315 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
5316 eldbus_connection_send(pd->a11y_bus, message, _on_elm_atspi_bridge_app_register, NULL, -1);
5322 _elm_atspi_bridge_app_unregister(Eo *bridge)
5325 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5327 root = elm_atspi_bridge_root_get(bridge);
5329 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5330 ATSPI_DBUS_PATH_ROOT,
5331 ATSPI_DBUS_INTERFACE_SOCKET,
5333 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5335 _bridge_iter_object_reference_append(bridge, iter, root);
5336 eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1);
5342 _cache_register(Eo *obj)
5344 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
5345 pd->cache_interface = eldbus_service_interface_register(pd->a11y_bus, CACHE_INTERFACE_PATH, &cache_iface_desc);
5346 eldbus_service_object_data_set(pd->cache_interface, ELM_ATSPI_BRIDGE_CLASS_NAME, obj);
5350 _set_broadcast_flag(const char *event, Eo *bridge)
5353 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5355 tokens = eina_str_split(event, ":", 3);
5357 if (!tokens) return;
5359 if (!strcmp(tokens[0], "Object"))
5361 if (!tokens[1] || *tokens[1] == '\0') return; // do not handle "Object:*"
5362 else if (!strcmp(tokens[1], "StateChanged"))
5364 if (!tokens[2] || *tokens[2] == '\0')
5365 pd->object_state_broadcast_mask = -1; // broadcast all
5366 eina_str_tolower(&tokens[2]);
5367 struct atspi_state_desc *sd = eina_hash_find(pd->state_hash, tokens[2]);
5369 STATE_TYPE_SET(pd->object_state_broadcast_mask, sd->elm_state);
5371 else if (!strcmp(tokens[1], "PropertyChange"))
5373 if (!tokens[2] || *tokens[2] == '\0')
5374 pd->object_property_broadcast_mask = -1; //broadcast all
5375 else if (!strcmp(tokens[2], "AccessibleValue"))
5376 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_VALUE);
5377 else if (!strcmp(tokens[2], "AccessibleName"))
5378 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_NAME);
5379 else if (!strcmp(tokens[2], "AccessibleDescription"))
5380 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_DESCRIPTION);
5381 else if (!strcmp(tokens[2], "AccessibleParent"))
5382 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_PARENT);
5383 else if (!strcmp(tokens[2], "AccessibleRole"))
5384 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_ROLE);
5386 else if (!strcmp(tokens[1], "ChildrenChanged"))
5388 if (!tokens[2] || *tokens[2] == '\0')
5389 pd->object_children_broadcast_mask = -1; // broadcast all
5390 else if (!strcmp(tokens[2], "add"))
5391 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_ADDED);
5392 else if (!strcmp(tokens[2], "remove"))
5393 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_REMOVED);
5395 else if (!strcmp(tokens[1], "TextChanged"))
5396 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED);
5397 else if (!strcmp(tokens[1], "TextCaretMoved"))
5398 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED);
5399 else if (!strcmp(tokens[1], "TextBoundsChanged"))
5400 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED);
5401 else if (!strcmp(tokens[1], "TextSelectionChanged"))
5402 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED);
5403 else if (!strcmp(tokens[1], "TextAttributesChanged"))
5404 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED);
5405 else if (!strcmp(tokens[1], "VisibleDataChanged"))
5406 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED);
5407 else if (!strcmp(tokens[1], "ActiveDescendantChanged"))
5408 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED);
5409 else if (!strcmp(tokens[1], "BoundsChanged"))
5410 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_BOUNDS_CHANGED);
5411 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5412 else if (!strcmp(tokens[1], "MoveOuted"))
5413 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED);
5416 else if (!strcmp(tokens[0], "Window"))
5418 if (!tokens[1] || *tokens[1] == '\0')
5419 pd->window_signal_broadcast_mask = -1; // broadcast all
5420 else if (!strcmp(tokens[1], "Create"))
5421 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_CREATE);
5422 else if (!strcmp(tokens[1], "Destroy"))
5423 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DESTROY);
5424 else if (!strcmp(tokens[1], "Activate"))
5425 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_ACTIVATE);
5426 else if (!strcmp(tokens[1], "Deactivate"))
5427 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DEACTIVATE);
5428 else if (!strcmp(tokens[1], "Maximize"))
5429 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MAXIMIZE);
5430 else if (!strcmp(tokens[1], "Minimize"))
5431 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MINIMIZE);
5432 else if (!strcmp(tokens[1], "Resize"))
5433 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESIZE);
5434 else if (!strcmp(tokens[1], "Restore"))
5435 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESTORE);
5443 _registered_listeners_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
5445 const char *event, *bus;
5447 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
5448 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
5450 DBG("Updating registered ATSPI signals list.");
5451 pd->object_broadcast_mask = 0;
5452 pd->object_children_broadcast_mask = 0;
5453 pd->object_property_broadcast_mask = 0;
5454 pd->object_state_broadcast_mask = 0;
5455 pd->window_signal_broadcast_mask = 0;
5457 if (eldbus_message_error_get(msg, &event, &bus))
5459 WRN("%s %s", event, bus);
5462 Eldbus_Message_Iter *iter, *siter;
5463 if (!eldbus_message_arguments_get(msg, "a(ss)", &iter))
5465 ERR("Invalid answer type from GetRegisteredEvents method call!");
5468 while (eldbus_message_iter_get_and_next(iter, 'r', &siter))
5470 if (!eldbus_message_iter_arguments_get(siter, "ss", &bus, &event))
5472 ERR("Unable to get message arguments");
5475 _set_broadcast_flag(event, data);
5480 //TIZEN_ONLY(20170910) atspi: emit signal after atspi bridge is connected
5481 pd->connected = EINA_TRUE;
5482 eo_do(data, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_CONNECTED, NULL));
5483 _elm_win_atspi(EINA_TRUE);
5487 eo_do(data, root = elm_obj_atspi_bridge_root_get());
5488 _bridge_cache_build(data, root);
5490 // initialize pending proxy
5491 EINA_LIST_FREE(pd->socket_queue, pr)
5492 _socket_ifc_create(pd->a11y_bus, pr);
5493 EINA_LIST_FREE(pd->plug_queue, pr)
5494 _plug_connect(pd->a11y_bus, pr);
5496 pd->socket_queue = pd->plug_queue = NULL;
5501 _registered_events_list_update(Eo *bridge)
5503 Eldbus_Message *msg;
5504 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5507 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "GetRegisteredEvents");
5508 p = eldbus_connection_send(pd->a11y_bus, msg, _registered_listeners_get, bridge, -1);
5509 pd->pending_requests = eina_list_append(pd->pending_requests, p);
5513 _handle_listener_change(void *data, const Eldbus_Message *msg EINA_UNUSED)
5515 _registered_events_list_update(data);
5518 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5520 _scroll_gesture_required_is(Eo *obj)
5522 Eina_Bool ret = EINA_FALSE;
5523 Eina_List *l, *attr_list = NULL;
5524 Elm_Atspi_Attribute *attr = NULL;
5526 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5527 EINA_LIST_FOREACH(attr_list, l, attr)
5529 if (!strcmp(attr->key, "gesture_required") && !strcmp(attr->value, "scroll"))
5536 elm_atspi_attributes_list_free(attr_list);
5543 _state_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5545 Elm_Atspi_Event_State_Changed_Data *state_data = event_info;
5546 const char *type_desc;
5547 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5549 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
5550 if ((state_data->type == ELM_ATSPI_STATE_ACTIVE) && eo_isa(obj, ELM_WIN_CLASS))
5552 pd->window_activated = state_data->new_value;
5555 // TIZEN_ONLY(20161209): reduce IPC of object:state-changed:showing
5556 if ((state_data->type == ELM_ATSPI_STATE_SHOWING) ||
5557 (state_data->type == ELM_ATSPI_STATE_VISIBLE))
5559 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5560 Elm_Atspi_State_Set ss;
5562 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5563 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
5564 if (state_data->new_value) /* Showing */
5566 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5567 (role != ELM_ATSPI_ROLE_PAGE_TAB) &&
5568 (role != ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW) &&
5569 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)))
5572 else /* Not Showing */
5574 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5575 (role != ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW) &&
5576 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)) &&
5577 (_elm_object_accessibility_currently_highlighted_get() != (void *)obj))
5583 if (!STATE_TYPE_GET(pd->object_state_broadcast_mask, state_data->type))
5586 if ((state_data->type > ELM_ATSPI_STATE_LAST_DEFINED) ||
5587 (int)state_data->type < 0)
5590 type_desc = elm_states_to_atspi_state[state_data->type].name;
5592 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5593 unsigned int det2 = 0;
5594 if (state_data->type == ELM_ATSPI_STATE_HIGHLIGHTED)
5596 if (_ee_obscured_get(obj))
5599 if (_scroll_gesture_required_is(obj))
5602 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5603 &_event_obj_signals[ATSPI_OBJECT_EVENT_STATE_CHANGED], type_desc, state_data->new_value, det2, NULL);
5609 _bounds_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5611 Elm_Atspi_Event_Geometry_Changed_Data *geo_data = event_info;
5613 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5614 &_event_obj_signals[ATSPI_OBJECT_EVENT_BOUNDS_CHANGED], "", 0, 0, "(iiii)",
5615 geo_data->x, geo_data->y, geo_data->width, geo_data->height);
5620 _property_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5622 const char *property = event_info;
5624 enum _Atspi_Object_Property prop = ATSPI_OBJECT_PROPERTY_LAST;
5626 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5628 if (!strcmp(property, "parent"))
5630 prop = ATSPI_OBJECT_PROPERTY_PARENT;
5631 atspi_desc = "accessible-parent";
5633 else if (!strcmp(property, "name"))
5635 prop = ATSPI_OBJECT_PROPERTY_NAME;
5636 atspi_desc = "accessible-name";
5638 else if (!strcmp(property, "description"))
5640 prop = ATSPI_OBJECT_PROPERTY_DESCRIPTION;
5641 atspi_desc = "accessible-description";
5643 else if (!strcmp(property, "role"))
5645 prop = ATSPI_OBJECT_PROPERTY_ROLE;
5646 atspi_desc = "accessible-role";
5648 else if (!strcmp(property, "value"))
5650 prop = ATSPI_OBJECT_PROPERTY_VALUE;
5651 atspi_desc = "accessible-value";
5653 if (prop == ATSPI_OBJECT_PROPERTY_LAST)
5655 ERR("Unrecognized property name!");
5658 if (!STATE_TYPE_GET(pd->object_property_broadcast_mask, prop))
5660 DBG("Masking property %s changed event.", property);
5664 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5665 &_event_obj_signals[ATSPI_OBJECT_EVENT_PROPERTY_CHANGED], atspi_desc, 0, 0, NULL, NULL);
5670 _visible_data_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5672 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5674 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED))
5677 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5678 &_event_obj_signals[ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED], "",
5685 _active_descendant_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5687 Eo *child = event_info;
5690 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5692 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED))
5695 eo_do(child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5697 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5698 &_event_obj_signals[ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED], "",
5699 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), child);
5704 _children_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5706 const char *atspi_desc = NULL;
5707 Elm_Atspi_Event_Children_Changed_Data *ev_data = event_info;
5709 enum _Atspi_Object_Child_Event_Type type;
5711 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5713 type = ev_data->is_added ? ATSPI_OBJECT_CHILD_ADDED : ATSPI_OBJECT_CHILD_REMOVED;
5715 // update cached objects
5716 if (ev_data->is_added)
5717 _bridge_cache_build(data, ev_data->child);
5719 if (!STATE_TYPE_GET(pd->object_children_broadcast_mask, type))
5724 case ATSPI_OBJECT_CHILD_ADDED:
5726 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5728 case ATSPI_OBJECT_CHILD_REMOVED:
5729 atspi_desc = "remove";
5730 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5734 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5735 &_event_obj_signals[ATSPI_OBJECT_EVENT_CHILDREN_CHANGED], atspi_desc,
5736 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), ev_data->child);
5741 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5743 _move_outed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5745 const Elm_Atspi_Move_Outed_Type *type = event_info;
5747 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5749 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED))
5751 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5752 &_event_obj_signals[ATSPI_OBJECT_EVENT_MOVE_OUTED], "", *type, 0, NULL, NULL);
5757 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
5759 _window_activated_detail_value_add(Eo *obj)
5761 unsigned int ret = ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED;
5762 Eina_List *l, *attr_list = NULL;
5763 Elm_Atspi_Attribute *attr = NULL;
5765 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5766 EINA_LIST_FOREACH(attr_list, l, attr)
5768 if (!strcmp(attr->key, "default_label"))
5770 if(!strcmp(attr->value, "enabled_without_window"))
5772 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED_WITHOUT_WINDOW;
5774 else if(!strcmp(attr->value, "disabled"))
5776 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_DISABLED;
5781 elm_atspi_attributes_list_free(attr_list);
5783 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5784 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5785 if (role == ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW)
5786 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_KEYBOARD;
5792 _window_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info EINA_UNUSED)
5794 enum _Atspi_Window_Signals type;
5796 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5798 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED)
5799 type = ATSPI_WINDOW_EVENT_CREATE;
5800 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED)
5801 type = ATSPI_WINDOW_EVENT_DESTROY;
5802 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DEACTIVATED)
5803 type = ATSPI_WINDOW_EVENT_DEACTIVATE;
5804 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5805 type = ATSPI_WINDOW_EVENT_ACTIVATE;
5806 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MAXIMIZED)
5807 type = ATSPI_WINDOW_EVENT_MAXIMIZE;
5808 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MINIMIZED)
5809 type = ATSPI_WINDOW_EVENT_MINIMIZE;
5810 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_RESTORED)
5811 type = ATSPI_WINDOW_EVENT_RESTORE;
5815 if (!STATE_TYPE_GET(pd->window_signal_broadcast_mask, type))
5820 ERR("A11Y connection closed. Unable to send ATSPI event.");
5824 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
5825 unsigned int det1 = 0;
5826 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5827 det1 = _window_activated_detail_value_add(obj);
5830 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_WINDOW,
5831 &_window_obj_signals[type], "", det1, 0, "i", 0);
5836 _selection_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5838 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5840 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_SELECTION_CHANGED))
5843 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5844 &_event_obj_signals[ATSPI_OBJECT_EVENT_SELECTION_CHANGED], "", 0, 0, "i", 0);
5848 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, ...)
5850 Eldbus_Message *msg;
5851 Eldbus_Message_Iter *iter , *iter_stack[64], *iter_struct;
5857 EINA_SAFETY_ON_NULL_RETURN(infc);
5858 EINA_SAFETY_ON_NULL_RETURN(signal);
5859 EINA_SAFETY_ON_NULL_RETURN(minor);
5860 EINA_SAFETY_ON_NULL_RETURN(obj);
5861 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5863 path = _bridge_path_from_object(bridge, obj);
5865 msg = eldbus_message_signal_new(path, infc, signal->name);
5868 va_start(va, variant_sig);
5870 iter = eldbus_message_iter_get(msg);
5871 eldbus_message_iter_arguments_append(iter, "sii", minor, det1, det2);
5875 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', variant_sig);
5877 const char *tmp = variant_sig;
5883 iter_stack[top + 1] = eldbus_message_iter_container_new(iter_stack[top], 'r', NULL);
5887 eldbus_message_iter_basic_append(iter_stack[top], 's', va_arg(va, char*));
5890 eldbus_message_iter_basic_append(iter_stack[top], 'i', va_arg(va, int));
5893 atspi_obj = va_arg(va, Eo*);
5894 path = _bridge_path_from_object(bridge, atspi_obj);
5895 eldbus_message_iter_basic_append(iter_stack[top], 'o', path);
5898 eldbus_message_iter_container_close(iter_stack[top - 1], iter_stack[top]);
5902 ERR("Not supported d-bus type: %c.", *tmp);
5908 else // AT-SPI implementation forces checks on variant in signature even if not used.
5910 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', "i");
5911 eldbus_message_iter_basic_append(iter_stack[top], 'i', 0);
5916 ERR("Invalid d-bus signature: () do not match.");
5918 eldbus_message_iter_container_close(iter, iter_stack[0]);
5920 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
5921 path = _bridge_path_from_object(bridge, elm_atspi_bridge_root_get(bridge));
5922 eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
5923 eldbus_message_iter_basic_append(iter_struct, 'o', path);
5924 eldbus_message_iter_container_close(iter, iter_struct);
5926 eldbus_connection_send(pd->a11y_bus, msg, NULL, NULL, -1);
5927 DBG("Send %s.%s[%s,%d,%d]", infc, signal->name, minor, det1, det2);
5931 _text_caret_moved_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5935 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5937 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED))
5940 eo_do(obj, cursor_pos = elm_interface_atspi_text_caret_offset_get());
5942 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5943 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED], "", cursor_pos, 0, NULL, NULL);
5949 _text_text_inserted_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5951 Elm_Atspi_Text_Change_Info *info = event_info;
5953 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5955 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5960 WRN("Try to send signal with NULL value");
5964 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5965 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "insert", info->pos, info->len, "s", info->content);
5971 _text_text_removed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5973 Elm_Atspi_Text_Change_Info *info = event_info;
5975 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5977 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5982 WRN("Try to send signal with NULL value");
5986 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5987 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "delete", info->pos, info->len, "s", info->content);
5993 _text_selection_changed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5995 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5997 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED))
6000 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
6001 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED], "", 0, 0, NULL, NULL);
6006 //TIZEN_ONLY(20160527) - Add direct reading feature
6008 _on_reading_state_changed(void *data EINA_UNUSED, const Eldbus_Message *msg)
6011 const char *say_signal_name = "";
6012 Elm_Atspi_Say_Info *say_info;
6014 if (eldbus_message_arguments_get(msg, "is", &i, &say_signal_name))
6015 { if (read_command_id)
6017 say_info = eina_hash_find(read_command_id, &i);
6020 if (say_info->func && say_signal_name)
6021 say_info->func(say_info->data, say_signal_name);
6022 eina_hash_del(read_command_id, &i, NULL);
6031 _event_handlers_register(Eo *bridge)
6033 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6035 _registered_events_list_update(bridge);
6037 // register signal handlers in order to update list of registered listeners of ATSPI-Clients
6038 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);
6039 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);
6040 //TIZEN_ONLY(20160527) - Add direct reading feature
6041 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);
6043 pd->key_flr = ecore_event_filter_add(NULL, _elm_atspi_bridge_key_filter, NULL, bridge);
6047 _bridge_object_unregister(Eo *bridge, Eo *obj)
6049 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6051 eina_hash_del(pd->cache, &obj, obj);
6055 _on_object_add(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6057 Eldbus_Message *sig;
6058 Eldbus_Message_Iter *iter;
6060 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6062 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_ADDED);
6063 iter = eldbus_message_iter_get(sig);
6064 _cache_item_reference_append_cb(data, obj, iter);
6066 eldbus_service_signal_send(pd->cache_interface, sig);
6072 _on_object_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6074 Eldbus_Message *sig;
6076 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6078 _bridge_object_unregister(data, obj);
6080 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_REMOVED);
6081 Eldbus_Message_Iter *iter = eldbus_message_iter_get(sig);
6082 _bridge_iter_object_reference_append(data, iter, obj);
6083 eldbus_service_signal_send(pd->cache_interface, sig);
6089 _bridge_cache_build(Eo *bridge, void *obj)
6091 Eina_List *children;
6092 Elm_Atspi_State_Set ss;
6095 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6097 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6100 if (!eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
6101 _bridge_object_register(bridge, obj);
6103 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
6104 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
6106 if (eo_isa(obj, ELM_INTERFACE_ATSPI_WINDOW_INTERFACE))
6108 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_ACTIVE))
6110 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6111 pd->window_activated = EINA_TRUE;
6116 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6117 pd->window_activated = EINA_FALSE;
6121 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
6122 EINA_LIST_FREE(children, child)
6123 _bridge_cache_build(bridge, child);
6127 _interfaces_unregister(Eo *bridge)
6129 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6131 #define INTERFACE_SAFE_FREE(ifc) \
6133 eldbus_service_interface_unregister(ifc); \
6136 INTERFACE_SAFE_FREE(pd->interfaces.accessible);
6137 INTERFACE_SAFE_FREE(pd->interfaces.application);
6138 INTERFACE_SAFE_FREE(pd->interfaces.action);
6139 INTERFACE_SAFE_FREE(pd->interfaces.component);
6140 INTERFACE_SAFE_FREE(pd->interfaces.collection);
6141 INTERFACE_SAFE_FREE(pd->interfaces.editable_text);
6142 INTERFACE_SAFE_FREE(pd->interfaces.image);
6143 INTERFACE_SAFE_FREE(pd->interfaces.selection);
6144 INTERFACE_SAFE_FREE(pd->interfaces.text);
6145 INTERFACE_SAFE_FREE(pd->interfaces.value);
6149 _a11y_connection_shutdown(Eo *bridge)
6151 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6152 Eldbus_Pending *pending;
6155 _elm_atspi_bridge_app_unregister(bridge);
6158 eina_hash_free(pd->cache);
6161 if (pd->cache_interface)
6162 eldbus_service_object_unregister(pd->cache_interface);
6163 pd->cache_interface = NULL;
6165 _interfaces_unregister(bridge);
6167 if (pd->key_flr) ecore_event_filter_del(pd->key_flr);
6170 if (pd->register_hdl) eldbus_signal_handler_del(pd->register_hdl);
6171 pd->register_hdl = NULL;
6173 if (pd->unregister_hdl) eldbus_signal_handler_del(pd->unregister_hdl);
6174 pd->unregister_hdl = NULL;
6176 //TIZEN_ONLY(20160527) - Add direct reading feature
6177 if (pd->reading_state_changed_hdl) eldbus_signal_handler_del(pd->reading_state_changed_hdl);
6178 pd->reading_state_changed_hdl = NULL;
6181 EINA_LIST_FREE(pd->pending_requests, pending)
6182 eldbus_pending_cancel(pending);
6183 pd->pending_requests = NULL;
6185 if (pd->a11y_bus) eldbus_connection_unref(pd->a11y_bus);
6186 pd->a11y_bus = NULL;
6188 if (pd->state_hash) eina_hash_free(pd->state_hash);
6189 pd->state_hash = NULL;
6191 if (pd->event_hash) eina_hash_free(pd->event_hash);
6192 pd->event_hash = NULL;
6194 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, elm_interface_atspi_accessible_event_handler_del(pd->event_hdlr));
6195 pd->event_hdlr = NULL;
6197 eo_do(bridge, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, NULL));
6198 pd->connected = EINA_FALSE;
6201 static void _disconnect_cb(void *data, Eldbus_Connection *conn EINA_UNUSED, void *event_info EINA_UNUSED)
6203 _a11y_connection_shutdown(data);
6207 _interfaces_register(Eo *bridge)
6209 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6211 pd->interfaces.accessible =
6212 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &accessible_iface_desc);
6213 eldbus_service_object_data_set(pd->interfaces.accessible, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6215 pd->interfaces.application =
6216 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &application_iface_desc);
6217 eldbus_service_object_data_set(pd->interfaces.application, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6219 pd->interfaces.action =
6220 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &action_iface_desc);
6221 eldbus_service_object_data_set(pd->interfaces.action, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6223 pd->interfaces.component =
6224 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &component_iface_desc);
6225 eldbus_service_object_data_set(pd->interfaces.component, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6227 pd->interfaces.collection =
6228 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &collection_iface_desc);
6229 eldbus_service_object_data_set(pd->interfaces.collection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6231 pd->interfaces.editable_text =
6232 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &editable_text_iface_desc);
6233 eldbus_service_object_data_set(pd->interfaces.editable_text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6235 pd->interfaces.image =
6236 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &image_iface_desc);
6237 eldbus_service_object_data_set(pd->interfaces.image, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6239 pd->interfaces.selection =
6240 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &selection_iface_desc);
6241 eldbus_service_object_data_set(pd->interfaces.selection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6243 pd->interfaces.text =
6244 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &text_iface_desc);
6245 eldbus_service_object_data_set(pd->interfaces.text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6247 pd->interfaces.value =
6248 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &value_iface_desc);
6249 eldbus_service_object_data_set(pd->interfaces.value, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6253 _bridge_accessible_event_dispatch(void *data, Eo *accessible, const Eo_Event_Description *desc, void *event_info)
6255 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6257 _bridge_object_register(data, accessible);
6259 Eo_Event_Cb cb = eina_hash_find(pd->event_hash, &desc);
6260 return cb ? cb(data, accessible, desc, event_info) : EINA_TRUE;
6264 _a11y_bus_initialize(Eo *obj, const char *socket_addr)
6266 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
6267 pd->a11y_bus = eldbus_private_address_connection_get(socket_addr);
6271 eldbus_connection_event_callback_add(pd->a11y_bus, ELDBUS_CONNECTION_EVENT_DISCONNECTED, _disconnect_cb, obj);
6273 // init data structures
6274 pd->cache = eina_hash_pointer_new(NULL);
6275 pd->state_hash = _elm_atspi_state_hash_build();
6276 pd->event_hash = _elm_atspi_event_hash_build();
6279 _cache_register(obj);
6280 _interfaces_register(obj);
6281 _event_handlers_register(obj);
6282 if (!getenv("ELM_ATSPI_NO_EMBED"))
6283 _elm_atspi_bridge_app_register(obj);
6285 // register accesible object event listener
6286 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, pd->event_hdlr = elm_interface_atspi_accessible_event_handler_add(_bridge_accessible_event_dispatch, obj));
6291 _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6293 const char *errname, *errmsg, *sock_addr = NULL;
6294 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6296 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6298 if (eldbus_message_error_get(msg, &errname, &errmsg))
6300 ERR("%s %s", errname, errmsg);
6304 if (!eldbus_message_arguments_get(msg, "s", &sock_addr) || !sock_addr)
6306 ERR("Could not get A11Y Bus socket address.");
6310 _a11y_socket_address = eina_stringshare_add(sock_addr);
6311 _a11y_bus_initialize((Eo*)data, sock_addr);
6314 static void _a11y_connection_init(Eo *bridge)
6316 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6317 Eina_Bool is_connected;
6319 eo_do(bridge, is_connected = elm_obj_atspi_bridge_connected_get());
6321 if (is_connected) return;
6323 // TIZEN_ONLY(20170512): send window activated event to at_spi2 only once per session
6324 pd->window_activated_broadcast_needed = EINA_TRUE;
6326 Eldbus_Message *m = eldbus_object_method_call_new(pd->bus_obj, A11Y_DBUS_INTERFACE, "GetAddress");
6327 Eldbus_Pending *p = eldbus_object_send(pd->bus_obj, m, _a11y_bus_address_get, bridge, 100);
6330 pd->pending_requests = eina_list_append(pd->pending_requests, p);
6334 _screen_reader_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6336 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6337 const char *errname, *errmsg;
6338 Eina_Bool is_enabled;
6339 Eldbus_Message_Iter *variant;
6341 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6343 if (eldbus_message_error_get(msg, &errname, &errmsg))
6345 WRN("%s %s", errname, errmsg);
6348 if (!eldbus_message_arguments_get(msg, "v", &variant))
6350 ERR("'ScreenReaderEnabled' not packed into variant.");
6353 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6355 ERR("Could not get 'ScreenReaderEnabled' boolean property");
6358 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6359 pd->screen_reader_enabled = !!is_enabled;
6361 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6362 //register/unregister access objects accordingly.
6363 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6364 _elm_win_screen_reader(is_enabled);
6369 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6371 _at_spi_client_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6373 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6374 const char *errname, *errmsg;
6375 Eina_Bool is_enabled;
6376 Eldbus_Message_Iter *variant;
6378 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6380 if (eldbus_message_error_get(msg, &errname, &errmsg))
6382 WRN("%s %s", errname, errmsg);
6385 if (!eldbus_message_arguments_get(msg, "v", &variant))
6387 ERR("'" A11Y_DBUS_ENABLED_PROPERTY "' not packed into variant.");
6390 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6392 ERR("Could not get '" A11Y_DBUS_ENABLED_PROPERTY "' boolean property");
6396 _a11y_connection_init(data);
6399 _elm_win_atspi(EINA_FALSE);
6400 DBG("AT-SPI2 stack not enabled.");
6406 static void _bridge_object_register(Eo *bridge, Eo *obj)
6408 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6410 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6412 WRN("Unable to register class w/o Elm_Interface_Atspi_Accessible!");
6416 if (eina_hash_find(pd->cache, &obj))
6419 eina_hash_add(pd->cache, &obj, obj);
6423 _elm_atspi_bridge_init(void)
6427 _instance = eo_add(ELM_ATSPI_BRIDGE_CLASS, NULL);
6433 _elm_atspi_bridge_get(void)
6439 _elm_atspi_bridge_shutdown(void)
6446 if (_a11y_socket_address)
6447 eina_stringshare_del(_a11y_socket_address);
6448 _a11y_socket_address = NULL;
6451 static Key_Event_Info*
6452 _key_event_info_new(int event_type, const Ecore_Event_Key *data, Eo *bridge)
6454 Key_Event_Info *ret;
6455 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
6457 ret = calloc(sizeof(Key_Event_Info), 1);
6459 ret->type = event_type;
6461 ret->bridge = bridge;
6463 ret->event.keyname = eina_stringshare_add(data->keyname);
6464 ret->event.key = eina_stringshare_add(data->key);
6465 ret->event.string = eina_stringshare_add(data->string);
6466 ret->event.compose = eina_stringshare_add(data->compose);
6468 // not sure why it is here, but explicite keep it NULLed.
6469 ret->event.data = NULL;
6475 _key_event_info_free(Key_Event_Info *data)
6477 EINA_SAFETY_ON_NULL_RETURN(data);
6479 eina_stringshare_del(data->event.keyname);
6480 eina_stringshare_del(data->event.key);
6481 eina_stringshare_del(data->event.string);
6482 eina_stringshare_del(data->event.compose);
6488 _iter_marshall_key_event(Eldbus_Message_Iter *iter, Key_Event_Info *data)
6490 Eldbus_Message_Iter *struct_iter;
6491 EINA_SAFETY_ON_NULL_RETURN(data);
6493 struct_iter = eldbus_message_iter_container_new(iter, 'r', NULL);
6495 const char *str = data->event.keyname ? data->event.keyname : "";
6496 int is_text = data->event.keyname ? 1 : 0;
6498 if (data->type == ECORE_EVENT_KEY_DOWN)
6499 type = ATSPI_KEY_PRESSED_EVENT;
6501 type = ATSPI_KEY_RELEASED_EVENT;
6503 eldbus_message_iter_arguments_append(struct_iter, "uiiiisb", type, 0, data->event.keycode, 0, data->event.timestamp, str, is_text);
6504 eldbus_message_iter_container_close(iter, struct_iter);
6508 _on_event_del(void *user_data, void *func_data EINA_UNUSED)
6510 Key_Event_Info *info = user_data;
6511 _key_event_info_free(info);
6515 _on_listener_answer(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6517 Key_Event_Info *info = data;
6518 const char *errname, *errmsg;
6519 Eina_Bool ret = EINA_TRUE;
6521 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(info->bridge, pd);
6523 if (eldbus_message_error_get(msg, &errname, &errmsg))
6525 ERR("%s %s", errname, errmsg);
6528 if (!eldbus_message_arguments_get(msg, "b", &ret))
6530 ERR("Return message doen not contian return value");
6535 _key_event_info_free(info);
6539 ecore_event_add(info->type, &info->event, _on_event_del, info);
6540 pd->reemited_events = eina_list_append(pd->reemited_events, &info->event);
6544 _elm_atspi_bridge_key_filter(void *data, void *loop EINA_UNUSED, int type, void *event)
6546 Eldbus_Message *msg;
6547 Eldbus_Message_Iter *iter;
6548 Ecore_Event_Key *key_event = event;
6552 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_TRUE);
6554 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6555 if (!pd->window_activated) return EINA_TRUE;
6558 if ((type != ECORE_EVENT_KEY_DOWN) && (type != ECORE_EVENT_KEY_UP)) return EINA_TRUE;
6560 // check if reemited
6561 if (eina_list_data_find(pd->reemited_events, event))
6563 pd->reemited_events = eina_list_remove(pd->reemited_events, event);
6567 // TIZEN_ONLY(20170118): Not handle events if keyboard is on
6570 Eina_List *children, *l;
6572 eo_do(pd->root, children = elm_interface_atspi_accessible_children_get());
6574 EINA_LIST_FOREACH(children, l, child)
6576 if (elm_widget_focus_get(child)) break;
6578 eina_list_free(children);
6580 Elm_Win_Keyboard_Mode mode;
6581 mode = elm_win_keyboard_mode_get(child);
6582 if (mode == ELM_WIN_KEYBOARD_ON) return EINA_TRUE;
6586 ke = _key_event_info_new(type, key_event, bridge);
6587 if (!ke) return EINA_TRUE;
6589 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_DEC,
6590 ATSPI_DBUS_INTERFACE_DEC, "NotifyListenersSync");
6591 iter = eldbus_message_iter_get(msg);
6592 _iter_marshall_key_event(iter, ke);
6594 // timeout should be kept reasonaby low to avoid delays
6595 if (!eldbus_connection_send(pd->a11y_bus, msg, _on_listener_answer, ke, 100))
6602 _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6604 return pd->connected;
6608 _elm_atspi_bridge_root_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6612 pd->root = eo_add(ELM_ATSPI_APP_OBJECT_CLASS, NULL);
6613 elm_interface_atspi_accessible_added(pd->root);
6620 _properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
6622 Eldbus_Proxy_Event_Property_Changed *ev = event;
6625 const char *ifc = eldbus_proxy_interface_get(ev->proxy);
6626 if (ev->name && !strcmp(ev->name, "ScreenReaderEnabled" ) &&
6627 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6629 if (!eina_value_get(ev->value, &val))
6631 ERR("Unable to get ScreenReaderEnabled property value");
6634 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6635 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6636 pd->screen_reader_enabled = !!val;
6638 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6639 //register/unregister access objects accordingly.
6640 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6641 _elm_win_screen_reader(val);
6645 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6646 if (ev->name && !strcmp(ev->name, A11Y_DBUS_ENABLED_PROPERTY) &&
6647 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6649 if (!eina_value_get(ev->value, &val))
6651 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6652 ERR("Unable to get " A11Y_DBUS_ENABLED_PROPERTY " property value");
6658 _a11y_connection_init(bridge);
6661 _elm_win_atspi(EINA_FALSE);
6662 _a11y_connection_shutdown(bridge);
6669 _elm_atspi_bridge_eo_base_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6671 Eldbus_Proxy *proxy;
6672 Eldbus_Pending *req;
6674 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_constructor());
6678 if (!(pd->session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION)))
6680 ERR("Unable to connect to Session Bus");
6683 if (!(pd->bus_obj = eldbus_object_get(pd->session_bus, A11Y_DBUS_NAME, A11Y_DBUS_PATH)))
6685 ERR("Could not get /org/a11y/bus object");
6688 if (!(proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE)))
6690 ERR("Could not get proxy object for %s interface", A11Y_DBUS_STATUS_INTERFACE);
6693 if (!(req = eldbus_proxy_property_get(proxy, "ScreenReaderEnabled", _screen_reader_enabled_get, obj)))
6695 ERR("Could not send PropertyGet request");
6698 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6700 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6701 if (!(req = eldbus_proxy_property_get(proxy, A11Y_DBUS_ENABLED_PROPERTY, _at_spi_client_enabled_get, obj)))
6703 ERR("Could not send PropertyGet request");
6707 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6710 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
6711 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
6712 _properties_changed_cb, obj);
6717 eldbus_object_unref(pd->bus_obj);
6720 eldbus_connection_unref(pd->session_bus);
6721 pd->session_bus = NULL;
6726 _elm_atspi_bridge_eo_base_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6728 _a11y_connection_shutdown(obj);
6730 if (pd->bus_obj) eldbus_object_unref(pd->bus_obj);
6731 if (pd->session_bus) eldbus_connection_unref(pd->session_bus);
6732 if (pd->root) eo_del(pd->root);
6734 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_destructor());
6738 elm_atspi_bridge_object_address_get(Eo *obj, char **bus, char **path)
6740 Eo *bridge = _elm_atspi_bridge_get();
6743 ERR("Connection with accessibility bus not established.");
6746 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
6747 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6749 ERR("Connection with accessibility bus not established.");
6752 if (bus) *bus = strdup(eldbus_connection_unique_name_get(pd->a11y_bus));
6753 if (path) *path = strdup(_bridge_path_from_object(bridge, obj));
6759 _proxy_property_get(const Eldbus_Service_Interface *interface, const char *property,
6760 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED,
6761 Eldbus_Message **error EINA_UNUSED)
6764 Eo *obj = eldbus_service_object_data_get(interface, "_atspi_obj");
6765 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6767 if (!strcmp(property, "Object"))
6770 eo_do(obj, parent = eo_parent_get());
6771 if (!elm_atspi_bridge_object_address_get(parent, &bus, &path))
6774 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
6777 eldbus_message_iter_basic_append(iter_struct, 's', bus);
6778 eldbus_message_iter_basic_append(iter_struct, 'o', path);
6779 eldbus_message_iter_container_close(iter, iter_struct);
6788 static const Eldbus_Property proxy_properties[] = {
6789 { "Object", "(so)", _proxy_property_get, NULL, 0 },
6790 { NULL, NULL, NULL, NULL, 0 }
6793 static const Eldbus_Service_Interface_Desc _proxy_iface_desc = {
6794 ELM_ATSPI_DBUS_INTERFACE_PROXY, socket_methods, NULL, proxy_properties, NULL, NULL
6797 static void _embedded_reply_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6799 Eo *parent, *proxy = data;
6800 const char *err, *txt;
6802 if (eldbus_message_error_get(msg, &err, &txt))
6804 ERR("AT-SPI: Embedded method call failed: %s %s", err, txt);
6805 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6808 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_CONNECTED, NULL));
6810 eo_do(proxy, parent = eo_parent_get());
6812 elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, proxy);
6816 _plug_embedded_send(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6818 char *obj_path = NULL;
6820 Eldbus_Message *msg = NULL;
6822 eo_do(proxy, parent = eo_parent_get());
6823 if (!parent) goto fail;
6825 msg = eldbus_message_method_call_new(bus, path, ATSPI_DBUS_INTERFACE_SOCKET, "Embedded");
6826 if (!msg) goto fail;
6828 if (!elm_atspi_bridge_object_address_get(parent, NULL, &obj_path))
6831 if (!eldbus_message_arguments_append(msg, "s", obj_path))
6834 if (!eldbus_connection_send(conn, msg, _embedded_reply_cb, proxy, 100))
6837 ELM_SAFE_FREE(obj_path, free);
6841 ERR("AT-SPI: Unable to send Embedded request.");
6842 if (msg) eldbus_message_unref(msg);
6843 ELM_SAFE_FREE(obj_path, free);
6844 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6847 static void _socket_addr_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6850 const char *bus, *path, *err, *txt;
6851 Eldbus_Message_Iter *iter, *iter_variant, *iter_struct;
6853 Eo *bridge = _elm_atspi_bridge_get();
6856 ERR("AT-SPI: Atspi bridge is not enabled.");
6859 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6861 if (eldbus_message_error_get(msg, &err, &txt))
6863 ERR("Unable to connect to socket: %s %s", err, txt);
6867 iter = eldbus_message_iter_get(msg);
6868 if (!eldbus_message_iter_arguments_get(iter, "v", &iter_variant))
6870 ERR("Unable to get variant parameter");
6874 if (!eldbus_message_iter_arguments_get(iter_variant, "(so)", &iter_struct))
6876 ERR("Unable to get so parameters");
6880 if (!eldbus_message_iter_arguments_get(iter_struct, "so", &bus, &path))
6882 ERR("Unable to get so parameters");
6886 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
6888 _plug_embedded_send(pd->a11y_bus, proxy, bus, path);
6893 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6897 eo_do(proxy, elm_obj_atspi_proxy_address_get_retry_timer_add());
6901 _plug_address_discover(Eldbus_Connection *conn, Eo *proxy, const char *svc_bus, const char *svc_path)
6903 Eldbus_Object *dobj;
6904 dobj = eldbus_object_get(conn, svc_bus, svc_path);
6907 ERR("Unable to get eldbus object from: %s %s", svc_bus, svc_path);
6911 Eldbus_Message *msg = eldbus_object_method_call_new(dobj, ELDBUS_FDO_INTERFACE_PROPERTIES, "Get");
6912 eldbus_message_arguments_append(msg, "ss", ELM_ATSPI_DBUS_INTERFACE_PROXY, "Object");
6913 eldbus_object_send(dobj, msg, _socket_addr_get_cb, proxy, 100);
6916 static void _plug_connect(Eldbus_Connection *conn, Eo *proxy)
6918 const char *bus, *path;
6920 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
6921 eo_do(proxy, path = eo_key_data_get("__svc_path"));
6925 _plug_address_discover(conn, proxy, bus, path);
6930 eo_do(proxy, elm_obj_atspi_proxy_address_get(&bus, &path));
6933 ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set. Unable to connect");
6934 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6937 _plug_embedded_send(conn, proxy, bus, path);
6942 static Eina_Bool _from_list_remove(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6944 Eina_List **list = data;
6945 *list = eina_list_remove(*list, obj);
6949 EAPI void elm_atspi_bridge_utils_proxy_connect(Eo *proxy)
6951 Eo *bridge = _elm_atspi_bridge_get();
6955 ERR("AT-SPI: Atspi bridge is not enabled.");
6956 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6959 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6963 if (!eina_list_data_find(pd->plug_queue, proxy))
6965 pd->plug_queue = eina_list_append(pd->plug_queue, proxy);
6966 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->plug_queue));
6970 _plug_connect(pd->a11y_bus, proxy);
6974 * @brief Service name sanitizer according to specs:
6975 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
6976 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
6978 char *_sanitize_service_name(const char *name)
6980 char ret[256] = "\0";
6982 if (!name) return NULL;
6984 const char *tmp = name;
6987 // name element should not begin with digit. Swallow non-charater prefix
6988 while ((*tmp != '\0') && !isalpha(*tmp)) tmp++;
6990 // append rest of character valid charactes [A-Z][a-z][0-9]_
6991 while ((*tmp != '\0') && (dst < &ret[sizeof(ret) - 1]))
6993 if (isalpha(*tmp) || isdigit(*tmp) || (*tmp == '_'))
7002 Eo* _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type)
7005 char bus[256], path[256], *name;
7008 name = _sanitize_service_name(svcname);
7009 if (!name) return NULL;
7011 res = snprintf(bus, sizeof(bus), "elm.atspi.proxy.socket.%s-%d", name, svcnum);
7012 if (res < 0 || (res >= (int)sizeof(bus)))
7018 res = snprintf(path, sizeof(path), "/elm/atspi/proxy/socket/%s/%d", name, svcnum);
7019 if (res < 0 || (res >= (int)sizeof(path)))
7027 ret = eo_add(ELM_ATSPI_PROXY_CLASS, parent, elm_obj_atspi_proxy_constructor(type));
7028 if (!ret) return NULL;
7030 eo_do(ret, eo_key_data_set("__svc_bus", eina_stringshare_add(bus)));
7031 eo_do(ret, eo_key_data_set("__svc_path", eina_stringshare_add(path)));
7037 _on_socket_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
7039 Eldbus_Service_Interface *ifc = data;
7041 Eldbus_Connection *conn = eldbus_service_connection_get(ifc);
7042 eo_do(obj, bus = eo_key_data_get("__svc_bus"));
7043 eldbus_name_release(conn, bus, NULL, NULL);
7044 eldbus_service_interface_unregister(ifc);
7049 _proxy_interface_register(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
7051 Eldbus_Service_Interface *proxy_infc;
7052 Eo *bridge = _elm_atspi_bridge_get();
7055 ERR("AT-SPI: Atspi bridge is not enabled.");
7058 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7060 eldbus_name_request(conn, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, NULL, NULL);
7061 proxy_infc = eldbus_service_interface_register(pd->a11y_bus, path, &_proxy_iface_desc);
7063 ERR("AT-SPI: Proxy interface registration failed");
7064 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _on_socket_del, proxy_infc));
7065 eldbus_service_object_data_set(proxy_infc, "_atspi_obj", proxy);
7068 static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy)
7070 const char *bus, *path;
7071 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7072 Eo *bridge = _elm_atspi_bridge_get();
7073 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7076 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7077 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7080 _proxy_interface_register(conn, proxy, bus, path);
7082 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7083 pd->interfaces.socket =
7084 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &socket_iface_desc);
7088 EAPI void elm_atspi_bridge_utils_proxy_listen(Eo *proxy)
7090 Eo *bridge = _elm_atspi_bridge_get();
7093 ERR("AT-SPI: Atspi bridge is not enabled.");
7096 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7099 if (!eina_list_data_find(pd->socket_queue, proxy))
7101 pd->socket_queue = eina_list_append(pd->socket_queue, proxy);
7102 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->socket_queue));
7106 _socket_ifc_create(pd->a11y_bus, proxy);
7109 //TIZEN_ONLY(20160527) - Add direct reading feature
7111 _on_read_command_call(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7113 const char *errname, *errmsg;
7117 Elm_Atspi_Say_Info *say_info = data;
7119 if (eldbus_message_error_get(msg, &errname, &errmsg))
7121 ERR("%s %s", errname, errmsg);
7127 // get read command id and map it to obj
7128 if (eldbus_message_arguments_get(msg, "sbi", &s, &b, &i))
7130 if (!read_command_id)
7131 read_command_id = eina_hash_int32_new(NULL);
7133 if (!read_command_id) {
7134 ERR("eina_hash_int32_new() failed to create new map to store callbacks for direct reading commands");
7138 eina_hash_add(read_command_id, &i, say_info);
7144 elm_atspi_bridge_utils_say(const char* text,
7145 Eina_Bool discardable,
7146 const Elm_Atspi_Say_Signal_Cb func,
7149 Eldbus_Message *msg;
7150 Eldbus_Message_Iter *iter;
7151 Elm_Atspi_Say_Info *say_info = NULL;
7152 Eo *bridge = _elm_atspi_bridge_get();
7155 ERR("AT-SPI: Atspi bridge is not enabled.");
7158 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7161 ERR("AT-SPI: a11y bus is not set.");
7165 msg = eldbus_message_method_call_new(ELM_ATSPI_DIRECT_READ_BUS,
7166 ELM_ATSPI_DIRECT_READ_PATH,
7167 ELM_ATSPI_DIRECT_READ_INTERFACE,
7169 iter = eldbus_message_iter_get(msg);
7170 eldbus_message_iter_arguments_append(iter, "sb", text, discardable);
7172 say_info = calloc(1, sizeof(Elm_Atspi_Say_Info));
7174 say_info->func = func;
7175 say_info->data = (void *)data;
7178 eldbus_connection_send(pd->a11y_bus, msg, _on_read_command_call, say_info, -1);
7182 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7184 _offset_set_reply_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7186 const char *err, *txt;
7188 if (eldbus_message_error_get(msg, &err, &txt))
7190 ERR("AT-SPI: SetOffset method call failed: %s %s", err, txt);
7195 void elm_atspi_bridge_utils_proxy_offset_set(Eo *proxy, int x, int y)
7197 const char *bus, *path;
7198 Eo *bridge = _elm_atspi_bridge_get();
7199 if (!bridge) return;
7201 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7203 if (!pd->a11y_bus) return;
7205 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7206 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7208 Eldbus_Message *msg = NULL;
7210 msg = eldbus_message_method_call_new(bus, path, ELM_ATSPI_DBUS_INTERFACE_PROXY, "SetOffset");
7211 if (!msg) goto fail;
7213 if (!eldbus_message_arguments_append(msg, "i", x))
7216 if (!eldbus_message_arguments_append(msg, "i", y))
7219 if (!eldbus_connection_send(pd->a11y_bus, msg, _offset_set_reply_cb, NULL, 100))
7225 ERR("AT-SPI: Unable to send SetOffset request.");
7226 if (msg) eldbus_message_unref(msg);
7229 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
7230 EAPI Eina_Bool elm_atspi_bridge_utils_is_screen_reader_enabled(void)
7232 Eo *bridge = _elm_atspi_bridge_get();
7235 ERR("AT-SPI: Atspi bridge is not enabled.");
7238 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
7239 return pd->screen_reader_enabled;
7242 #include "elm_atspi_bridge.eo.c"