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"}),
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]);
2763 static Eldbus_Message *
2764 _socket_embedded(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
2767 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2768 const char *obj_path = eldbus_message_path_get(msg);
2770 const char *bus, *path;
2771 Eo *bridge = _elm_atspi_bridge_get();
2772 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2773 eo_do(obj, proxy = elm_interface_atspi_accessible_parent_get());
2775 if (!eo_isa(proxy, ELM_ATSPI_PROXY_CLASS))
2776 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to embed object.");
2778 if (!eldbus_message_arguments_get(msg, "s", &path))
2779 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Plug id expected.");
2781 bus = eldbus_message_sender_get(msg);
2783 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
2785 _bridge_cache_build(bridge, proxy);
2787 return eldbus_message_method_return_new(msg);
2790 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2791 static Eldbus_Message *
2792 _socket_offset_set(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
2796 Eo *obj = eldbus_service_object_data_get(iface, "_atspi_obj");
2797 eo_do(obj, parent = eo_parent_get());
2798 Evas_Object *top = elm_object_top_widget_get(parent);
2800 if (!eldbus_message_arguments_get(msg, "ii", &x, &y))
2801 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
2803 eo_do(top, elm_interface_atspi_component_socket_offset_set(x, y));
2805 return eldbus_message_method_return_new(msg);
2809 static const Eldbus_Method editable_text_methods[] = {
2810 { "SetTextContents", ELDBUS_ARGS({"s", "newcontents"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_content_set, 0 },
2811 { "InsertText", ELDBUS_ARGS({"i", "position"}, {"s", "text"}, {"i", "length"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_insert, 0 },
2812 { "CopyText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), NULL, _editable_text_text_copy, 0 },
2813 { "CutText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_cut, 0 },
2814 { "DeleteText", ELDBUS_ARGS({"i", "startPos"}, {"i", "endPos"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_delete, 0 },
2815 { "PasteText", ELDBUS_ARGS({"i", "position"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_paste, 0 },
2816 { NULL, NULL, NULL, NULL, 0 }
2819 static const Eldbus_Method socket_methods[] = {
2820 { "Embedded", ELDBUS_ARGS({"s", "id"}), ELDBUS_ARGS({NULL, NULL}), _socket_embedded, 0 },
2821 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
2822 { "SetOffset", ELDBUS_ARGS({"i", "x"}, {"i", "y"}), ELDBUS_ARGS({NULL, NULL}), _socket_offset_set, 0 },
2824 { NULL, NULL, NULL, NULL, 0 }
2827 static const Eldbus_Service_Interface_Desc socket_iface_desc = {
2828 ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL
2832 _bridge_object_from_path(Eo *bridge, const char *path)
2834 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2835 unsigned long long eo_ptr = 0;
2837 const char *tmp = path;
2840 int len = strlen(ELM_ACCESS_OBJECT_PATH_PREFIX);
2841 if (strncmp(path, ELM_ACCESS_OBJECT_PATH_PREFIX, len))
2844 tmp = path + len; /* Skip over the prefix */
2845 if (!strcmp(ELM_ACCESS_OBJECT_PATH_ROOT, tmp))
2846 return elm_atspi_bridge_root_get(bridge);
2848 sscanf(tmp, "%llu", &eo_ptr);
2849 eo = (Eo *) (uintptr_t) eo_ptr;
2851 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
2852 if (!eina_hash_find(pd->cache, &eo))
2854 WRN("Request for non-registered object: %s", path);
2858 ret = eo_isa(eo, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN) ? eo : NULL;
2864 _bridge_path_from_object(Eo *bridge, const Eo *eo)
2866 static char path[64];
2869 return ATSPI_DBUS_PATH_NULL;
2871 if (eo == elm_atspi_bridge_root_get(bridge))
2872 snprintf(path, sizeof(path), "%s%s", ELM_ACCESS_OBJECT_PATH_PREFIX, ELM_ACCESS_OBJECT_PATH_ROOT);
2874 snprintf(path, sizeof(path), ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE, (unsigned long long)(uintptr_t)eo);
2879 _accessible_property_get(const Eldbus_Service_Interface *interface, const char *property,
2880 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2881 Eldbus_Message **error)
2883 const char *ret = NULL, *obj_path = eldbus_message_path_get(request_msg);
2884 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2885 Eo *ret_obj = NULL, *obj = _bridge_object_from_path(bridge, obj_path);
2887 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, request_msg, error);
2889 if (!strcmp(property, "Name"))
2891 eo_do(obj, ret = elm_interface_atspi_accessible_name_get());
2894 eldbus_message_iter_basic_append(iter, 's', ret);
2897 else if (!strcmp(property, "Description"))
2899 eo_do(obj, ret = elm_interface_atspi_accessible_description_get());
2902 eldbus_message_iter_basic_append(iter, 's', ret);
2905 else if (!strcmp(property, "Parent"))
2907 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
2908 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
2909 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
2910 if ((!ret_obj) && (ELM_ATSPI_ROLE_APPLICATION == role))
2911 _object_desktop_reference_append(iter);
2913 _bridge_iter_object_reference_append(bridge, iter, ret_obj);
2916 else if (!strcmp(property, "ChildCount"))
2918 Eina_List *l = NULL;
2919 eo_do(obj, l = elm_interface_atspi_accessible_children_get());
2920 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(l));
2928 _selection_property_get(const Eldbus_Service_Interface *interface, const char *property,
2929 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2930 Eldbus_Message **error)
2933 const char *obj_path = eldbus_message_path_get(request_msg);
2934 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2935 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2937 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE, request_msg, error);
2939 if (!strcmp(property, "NSelectedChildren"))
2941 eo_do(obj, n = elm_interface_atspi_selection_selected_children_count_get());
2942 eldbus_message_iter_basic_append(iter, 'i', n);
2949 _action_property_get(const Eldbus_Service_Interface *interface, const char *property,
2950 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
2951 Eldbus_Message **error)
2954 const char *obj_path = eldbus_message_path_get(request_msg);
2955 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2956 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2958 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN, request_msg, error);
2960 if (!strcmp(property, "NActions"))
2962 eo_do(obj, actions = elm_interface_atspi_action_actions_get());
2963 eldbus_message_iter_basic_append(iter, 'i', eina_list_count(actions));
2964 eina_list_free(actions);
2970 static Eldbus_Message*
2971 _value_properties_set(const Eldbus_Service_Interface *interface, const char *property,
2972 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg)
2976 const char *obj_path = eldbus_message_path_get(request_msg);
2977 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2978 Eo *obj = _bridge_object_from_path(bridge, obj_path);
2980 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg);
2982 if (!eldbus_message_iter_arguments_get(iter, "d", &value))
2984 return eldbus_message_error_new(request_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: double.");
2987 if (!strcmp(property, "CurrentValue"))
2989 eo_do(obj, ret = elm_interface_atspi_value_and_text_set(value, NULL));
2990 Eldbus_Message *answer = eldbus_message_method_return_new(request_msg);
2991 eldbus_message_arguments_append(answer, "b", ret);
2999 _value_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3000 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3001 Eldbus_Message **error)
3004 const char *obj_path = eldbus_message_path_get(request_msg);
3005 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3006 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3008 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE, request_msg, error);
3010 if (!strcmp(property, "CurrentValue"))
3012 eo_do(obj, elm_interface_atspi_value_and_text_get(&value, NULL));
3013 eldbus_message_iter_basic_append(iter, 'd', value);
3016 if (!strcmp(property, "MinimumValue"))
3018 eo_do(obj, elm_interface_atspi_value_range_get(&value, NULL, NULL));
3019 eldbus_message_iter_basic_append(iter, 'd', value);
3022 if (!strcmp(property, "MaximumValue"))
3024 eo_do(obj, elm_interface_atspi_value_range_get(NULL, &value, NULL));
3025 eldbus_message_iter_basic_append(iter, 'd', value);
3028 if (!strcmp(property, "MinimumIncrement"))
3030 eo_do(obj, value = elm_interface_atspi_value_increment_get());
3031 eldbus_message_iter_basic_append(iter, 'd', value);
3038 _image_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3039 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3040 Eldbus_Message **error)
3043 const char *obj_path = eldbus_message_path_get(request_msg);
3044 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3045 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3047 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN, request_msg, error);
3049 if (!strcmp(property, "ImageDescription"))
3051 eo_do(obj, value = elm_interface_atspi_image_description_get());
3052 value = value ? value : "";
3053 eldbus_message_iter_basic_append(iter, 's', value);
3056 if (!strcmp(property, "ImageLocale"))
3058 eo_do(obj, value = elm_interface_atspi_image_locale_get());
3059 value = value ? value : "";
3060 eldbus_message_iter_basic_append(iter, 's', value);
3067 _text_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3068 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3069 Eldbus_Message **error)
3071 const char *obj_path = eldbus_message_path_get(request_msg);
3072 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3073 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3076 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE, request_msg, error);
3078 if (!strcmp(property, "CharacterCount"))
3080 eo_do(obj, val = elm_interface_atspi_text_character_count_get());
3081 eldbus_message_iter_basic_append(iter, 'i', val);
3084 if (!strcmp(property, "CaretOffset"))
3086 eo_do(obj, val = elm_interface_atspi_text_caret_offset_get());
3087 eldbus_message_iter_basic_append(iter, 'i', val);
3093 static Eldbus_Message*
3094 _application_properties_set(const Eldbus_Service_Interface *iface, const char *property, Eldbus_Message_Iter *iter, const Eldbus_Message *input_msg)
3096 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3097 const char *obj_path = eldbus_message_path_get(input_msg);
3098 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3101 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
3102 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, input_msg);
3104 if (!eldbus_message_iter_arguments_get(iter, "i", &value))
3106 return eldbus_message_error_new(input_msg, "org.freedesktop.DBus.Error.InvalidArgs", "Expected value of type: int.");
3109 if (!strcmp(property, "Id"))
3112 Eldbus_Message *answer = eldbus_message_method_return_new(input_msg);
3113 eldbus_message_arguments_append(answer, "b", EINA_TRUE);
3121 _application_properties_get(const Eldbus_Service_Interface *interface, const char *property,
3122 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg,
3123 Eldbus_Message **error)
3125 const char *obj_path = eldbus_message_path_get(request_msg);
3126 Eo *bridge = eldbus_service_object_data_get(interface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3127 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3129 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
3130 ELM_ATSPI_PROPERTY_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_ATSPI_APP_OBJECT_CLASS, request_msg, error);
3132 if (!strcmp(property, "ToolkitName"))
3134 eldbus_message_iter_basic_append(iter, 's', "elementary");
3137 if (!strcmp(property, "Version"))
3140 snprintf(buf, sizeof(buf), "%d.%d", ELM_VERSION_MAJOR, ELM_VERSION_MINOR);
3141 eldbus_message_iter_basic_append(iter, 's', buf);
3144 if (!strcmp(property, "Id"))
3146 eldbus_message_iter_basic_append(iter, 'i', pd->id);
3152 static const Eldbus_Property accessible_properties[] = {
3153 { "Name", "s", NULL, NULL, 0 },
3154 { "Description", "s", NULL, NULL, 0 },
3155 { "Parent", "(so)", NULL, NULL, 0 },
3156 { "ChildCount", "i", NULL, NULL, 0 },
3157 { NULL, NULL, NULL, NULL, 0 }
3160 static const Eldbus_Property action_properties[] = {
3161 { "NActions", "i", _action_property_get, NULL, 0 },
3162 { NULL, NULL, NULL, NULL, 0 }
3165 static const Eldbus_Property value_properties[] = {
3166 { "MinimumValue", "d", NULL, NULL, 0 },
3167 { "MaximumValue", "d", NULL, NULL, 0 },
3168 { "MinimumIncrement", "d", NULL, NULL, 0 },
3169 { "CurrentValue", "d", NULL, NULL, 0 },
3170 { NULL, NULL, NULL, NULL, 0 }
3173 static const Eldbus_Property image_properties[] = {
3174 { "ImageDescription", "s", NULL, NULL, 0 },
3175 { "ImageLocale", "s", NULL, NULL, 0 },
3176 { NULL, NULL, NULL, NULL, 0 }
3179 static const Eldbus_Property selection_properties[] = {
3180 { "NSelectedChildren", "i", _selection_property_get, NULL, 0 },
3181 { NULL, NULL, NULL, NULL, 0 }
3184 static const Eldbus_Property text_properties[] = {
3185 { "CharacterCount", "i", NULL, NULL, 0 },
3186 { "CaretOffset", "i", NULL, NULL, 0 },
3187 { NULL, NULL, NULL, NULL, 0 }
3190 static const Eldbus_Property application_properties[] = {
3191 { "ToolkitName", "s", NULL, NULL, 0 },
3192 { "Version", "s", NULL, NULL, 0 },
3193 { "Id", "i", NULL, NULL, 0 },
3194 { NULL, NULL, NULL, NULL, 0 }
3197 static const Eldbus_Service_Interface_Desc accessible_iface_desc = {
3198 ATSPI_DBUS_INTERFACE_ACCESSIBLE, accessible_methods, NULL, accessible_properties, _accessible_property_get, NULL
3201 static const Eldbus_Service_Interface_Desc action_iface_desc = {
3202 ATSPI_DBUS_INTERFACE_ACTION, action_methods, NULL, action_properties, NULL, NULL
3205 static const Eldbus_Service_Interface_Desc value_iface_desc = {
3206 ATSPI_DBUS_INTERFACE_VALUE, NULL, NULL, value_properties, _value_properties_get, _value_properties_set
3209 static const Eldbus_Service_Interface_Desc image_iface_desc = {
3210 ATSPI_DBUS_INTERFACE_IMAGE, image_methods, NULL, image_properties, _image_properties_get, NULL
3213 static const Eldbus_Service_Interface_Desc selection_iface_desc = {
3214 ATSPI_DBUS_INTERFACE_SELECTION, selection_methods, NULL, selection_properties, NULL, NULL
3217 static const Eldbus_Service_Interface_Desc text_iface_desc = {
3218 ATSPI_DBUS_INTERFACE_TEXT, text_methods, NULL, text_properties, _text_properties_get, NULL
3221 static const Eldbus_Service_Interface_Desc editable_text_iface_desc = {
3222 ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, editable_text_methods, NULL, NULL, NULL, NULL
3225 static const Eldbus_Service_Interface_Desc application_iface_desc = {
3226 ATSPI_DBUS_INTERFACE_APPLICATION, NULL, NULL, application_properties, _application_properties_get, _application_properties_set
3230 _collection_match_rule_free(struct collection_match_rule *rule)
3232 Elm_Atspi_Attribute *attr;
3233 eina_list_free(rule->ifaces);
3234 EINA_LIST_FREE(rule->attributes, attr)
3236 eina_stringshare_del(attr->key);
3237 eina_stringshare_del(attr->value);
3242 _collection_roles_convert(uint64_t roles[2])
3244 // Currently elm roles and atspi roles are binary compatible.
3245 // Implement this function when it will be needed.
3250 _collection_iter_match_rule_get(Eldbus_Message_Iter *iter, struct collection_match_rule *rule)
3252 Eldbus_Message_Iter *states_iter, *attrib_iter, *iter_arg, *role_iter, *ifc_iter;
3253 unsigned int *array;
3254 int array_count, state_match, attrib_match, role_match, ifc_match, reverse;
3255 const char *ifc_name;
3257 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))
3259 ERR("Unable to get message arguments");
3263 memset(rule, 0x0, sizeof(struct collection_match_rule));
3264 rule->statematchtype = state_match;
3265 rule->attributematchtype = attrib_match;
3266 rule->rolematchtype = role_match;
3267 rule->interfacematchtype = ifc_match;
3268 rule->reverse = reverse;
3270 if (!eldbus_message_iter_fixed_array_get(states_iter, 'i', &array, &array_count))
3273 //Roles according to libatspi impementation are transferred in 2-int element fixed bit array
3274 if (array_count != 2)
3276 ERR("Unexpected states array size");
3279 uint64_t states = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3280 rule->states = _atspi_state_set_to_elm_atspi_state_set(states);
3282 //Roles according to libatspi impementation are transferred in 4-int element fixed bit array
3283 if (!eldbus_message_iter_fixed_array_get(role_iter, 'i', &array, &array_count))
3286 if (array_count != 4)
3288 ERR("Unexpected roles array size");
3292 //convert atspi roles to elm_roles
3293 rule->roles[0] = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
3294 rule->roles[1] = ((uint64_t)array[2] | ((uint64_t)array[3] << 32));
3296 _collection_roles_convert(rule->roles);
3298 //Get matching properties
3299 while (eldbus_message_iter_get_and_next(attrib_iter, '{', &iter_arg))
3301 const char *key, *value;
3302 if (eldbus_message_iter_arguments_get(iter_arg, "ss", &key, &value))
3304 Elm_Atspi_Attribute *attrib = calloc(sizeof(Elm_Atspi_Attribute), 1);
3305 attrib->key = eina_stringshare_add(key);
3306 attrib->value = eina_stringshare_add(value);
3307 rule->attributes = eina_list_append(rule->attributes, attrib);
3311 //Get interfaces to match
3312 while (eldbus_message_iter_get_and_next(ifc_iter, 's', &ifc_name))
3314 const Eo_Class *class = NULL;
3315 if (!strcmp(ifc_name, "action"))
3316 class = ELM_INTERFACE_ATSPI_ACTION_MIXIN;
3317 else if (!strcmp(ifc_name, "component"))
3318 class = ELM_INTERFACE_ATSPI_COMPONENT_MIXIN;
3319 else if (!strcmp(ifc_name, "editabletext"))
3320 class = ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE;
3321 else if (!strcmp(ifc_name, "text"))
3322 class = ELM_INTERFACE_ATSPI_TEXT_INTERFACE;
3323 else if (!strcmp(ifc_name, "image"))
3324 class = ELM_INTERFACE_ATSPI_SELECTION_INTERFACE;
3325 else if (!strcmp(ifc_name, "value"))
3326 class = ELM_INTERFACE_ATSPI_VALUE_INTERFACE;
3329 rule->ifaces = eina_list_append(rule->ifaces, class);
3332 _collection_match_rule_free(rule);
3341 _collection_match_interfaces_helper(Eo *obj, Eina_List *ifcs, Eina_Bool condition, Eina_Bool ret_if_true, Eina_Bool ret_if_false)
3346 EINA_LIST_FOREACH(ifcs, l, class)
3348 if (eo_isa(obj, class) == condition)
3351 return ret_if_false;
3355 _collection_match_interfaces_lookup(Eo *obj, struct collection_match_rule *rule)
3357 Eina_Bool ret = EINA_FALSE;
3359 switch (rule->interfacematchtype)
3361 case ATSPI_Collection_MATCH_INVALID:
3364 case ATSPI_Collection_MATCH_ALL:
3365 ret = _collection_match_interfaces_helper(
3366 obj, rule->ifaces, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3368 case ATSPI_Collection_MATCH_ANY:
3369 ret = _collection_match_interfaces_helper(
3370 obj, rule->ifaces, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3372 case ATSPI_Collection_MATCH_NONE:
3373 ret = _collection_match_interfaces_helper(
3374 obj, rule->ifaces, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3383 _collection_match_states_lookup(Eo *obj, struct collection_match_rule *rule)
3385 Eina_Bool ret = EINA_FALSE;
3386 Elm_Atspi_State_Set ss;
3388 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
3390 switch (rule->statematchtype)
3392 case ATSPI_Collection_MATCH_INVALID:
3395 case ATSPI_Collection_MATCH_ALL:
3396 ret = (ss & rule->states) == rule->states;
3398 case ATSPI_Collection_MATCH_ANY:
3399 ret = (ss & rule->states) > 0;
3401 case ATSPI_Collection_MATCH_NONE:
3402 ret = (ss & rule->states) == 0;
3412 _collection_match_roles_lookup(Eo *obj, struct collection_match_rule *rule)
3414 Eina_Bool ret = EINA_FALSE;
3415 Elm_Atspi_Role role;
3418 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
3423 role_set = rule->roles[1];
3426 role_set = rule->roles[0];
3430 ERR("Elm_Atspi_Role enum value exceeds 127. Unable to compare with roles bit field.");
3434 switch (rule->rolematchtype)
3436 case ATSPI_Collection_MATCH_INVALID:
3439 case ATSPI_Collection_MATCH_ALL:
3440 case ATSPI_Collection_MATCH_ANY:
3441 ret = (role_set & (1ULL << role)) > 0;
3443 case ATSPI_Collection_MATCH_NONE:
3444 ret = (role_set & (1ULL << role)) == 0;
3454 _collection_match_attributes_helper(Eina_List *obj_attribs, Eina_List *attribs, Eina_Bool compare, Eina_Bool ret_if_compare, Eina_Bool ret_default)
3457 Elm_Atspi_Attribute *attr, *attr2;
3459 EINA_LIST_FOREACH(attribs, l, attr)
3461 EINA_LIST_FOREACH(obj_attribs, l2, attr2)
3463 if ((attr->key && attr2->key &&
3464 attr->value && attr2->value &&
3465 !strcmp(attr->key, attr2->key) &&
3466 !strcmp(attr->value, attr2->value)) == compare)
3468 return ret_if_compare;
3477 _collection_match_attributes_lookup(Eo *obj, struct collection_match_rule *rule)
3479 Eina_Bool ret = EINA_FALSE;
3480 Eina_List *obj_attribs;
3482 eo_do(obj, obj_attribs = elm_interface_atspi_accessible_attributes_get());
3484 switch (rule->attributematchtype)
3486 case ATSPI_Collection_MATCH_INVALID:
3489 case ATSPI_Collection_MATCH_ALL:
3490 ret = _collection_match_attributes_helper(
3491 obj_attribs, rule->attributes, EINA_FALSE, EINA_FALSE, EINA_TRUE);
3493 case ATSPI_Collection_MATCH_ANY:
3494 ret = _collection_match_attributes_helper(
3495 obj_attribs, rule->attributes, EINA_TRUE, EINA_TRUE, EINA_FALSE);
3497 case ATSPI_Collection_MATCH_NONE:
3498 ret = _collection_match_attributes_helper(
3499 obj_attribs, rule->attributes, EINA_TRUE, EINA_FALSE, EINA_TRUE);
3505 elm_atspi_attributes_list_free(obj_attribs);
3511 _collection_sort_order_canonical(struct collection_match_rule *rule, Eina_List **ls,
3513 Eo *obj, long index, Eina_Bool flag,
3514 Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3517 Eina_List *children;
3518 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
3519 long acount = eina_list_count(children);
3520 Eina_Bool prev = pobj ? EINA_TRUE : EINA_FALSE;
3522 for (; i < acount && (max == 0 || count < max); i++)
3524 Eo *child = eina_list_nth(children, i);
3526 if (prev && child == pobj)
3528 eina_list_free(children);
3532 if (flag && _collection_match_interfaces_lookup(child, rule)
3533 && _collection_match_states_lookup(child, rule)
3534 && _collection_match_roles_lookup(child, rule)
3535 && _collection_match_attributes_lookup(child, rule))
3537 *ls = eina_list_append(*ls, child);
3544 if (recurse && traverse)
3545 count = _collection_sort_order_canonical(rule, ls, count,
3546 max, child, 0, EINA_TRUE,
3547 pobj, recurse, traverse);
3549 eina_list_free(children);
3554 _collection_sort_order_reverse_canonical(struct collection_match_rule *rule, Eina_List **ls,
3555 int count, int max, Eo *obj, Eina_Bool flag, Eo *pobj)
3557 Eo *nextobj, *parent;
3559 Eina_List *children;
3561 /* This breaks us out of the recursion. */
3562 if (!obj || obj == pobj)
3567 /* Add to the list if it matches */
3568 if (flag && _collection_match_interfaces_lookup(obj, rule)
3569 && _collection_match_states_lookup(obj, rule)
3570 && _collection_match_roles_lookup(obj, rule)
3571 && _collection_match_attributes_lookup(obj, rule)
3572 && (max == 0 || count < max))
3574 *ls = eina_list_append(*ls, obj);
3581 /* Get the current nodes index in it's parent and the parent object. */
3583 indexinparent = elm_interface_atspi_accessible_index_in_parent_get(),
3584 parent = elm_interface_atspi_accessible_parent_get());
3586 if ((indexinparent > 0) && ((max == 0) || (count < max)))
3588 /* there are still some siblings to visit so get the previous sibling
3589 and get it's last descendant.
3590 First, get the previous sibling */
3591 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
3592 nextobj = eina_list_nth(children, indexinparent - 1);
3593 eina_list_free(children);
3595 /* Now, drill down the right side to the last descendant */
3597 eo_do(nextobj, children = elm_interface_atspi_accessible_children_get());
3598 if (children) nextobj = eina_list_last_data_get(children);
3599 eina_list_free(children);
3602 /* recurse with the last descendant */
3603 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3604 nextobj, EINA_TRUE, pobj);
3606 else if (max == 0 || count < max)
3608 /* no more siblings so next node must be the parent */
3609 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
3610 parent, EINA_TRUE, pobj);
3617 _collection_inbackorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3620 *list = eina_list_append(*list, obj);
3622 _collection_sort_order_reverse_canonical(rule, list, 0, max, obj, EINA_TRUE, collection);
3624 *list = eina_list_remove_list(*list, *list);
3630 _collection_inorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
3631 int count, int max, Eo *obj, Eina_Bool traverse)
3635 count = _collection_sort_order_canonical(rule, list, count, max, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3637 while ((max == 0 || count < max) && obj && obj != collection)
3641 parent = elm_interface_atspi_accessible_parent_get(),
3642 idx = elm_interface_atspi_accessible_index_in_parent_get());
3643 count = _collection_sort_order_canonical(rule, list, count, max, parent,
3644 idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3648 if (max == 0 || count < max)
3649 count = _collection_sort_order_canonical(rule, list, count, max,
3650 obj, idx + 1, EINA_TRUE, NULL, EINA_TRUE, traverse);
3656 _collection_query(struct collection_match_rule *rule, AtspiCollectionSortOrder sortby,
3657 Eina_List **list, int count, int max, Eo *obj, long index,
3658 Eina_Bool flag, Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
3662 case ATSPI_Collection_SORT_ORDER_CANONICAL:
3663 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3664 pobj, recurse, traverse);
3666 case ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL:
3667 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
3668 pobj, recurse, traverse);
3669 *list = eina_list_reverse(*list);
3673 WRN("Unhandled sort method");
3679 static Eldbus_Message*
3680 _collection_return_msg_from_list(Elm_Atspi_Bridge *bridge, const Eldbus_Message *msg, const Eina_List *objs)
3682 Eldbus_Message *ret;
3684 Eldbus_Message_Iter *iter, *array_iter;
3687 ret = eldbus_message_method_return_new(msg);
3688 if (!ret) return NULL;
3690 iter = eldbus_message_iter_get(ret);
3691 array_iter = eldbus_message_iter_container_new(iter, 'a', "(so)");
3693 EINA_LIST_FOREACH(objs, l, obj)
3695 _bridge_object_register(bridge, obj);
3696 _bridge_iter_object_reference_append(bridge, array_iter, obj);
3699 eldbus_message_iter_container_close(iter, array_iter);
3704 _collection_get_matches_from_handle(Eo *collection, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, int max, Eina_Bool traverse)
3706 Eina_List *result = NULL;
3712 case ATSPI_Collection_TREE_INORDER:
3713 _collection_inorder(collection, rule, &result, 0, max, current, traverse);
3714 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3715 result = eina_list_reverse(result);
3717 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3719 idx = elm_interface_atspi_accessible_index_in_parent_get(),
3720 parent = elm_interface_atspi_accessible_parent_get());
3721 _collection_query(rule, sortby, &result, 0, max, parent, idx, EINA_FALSE, NULL, EINA_TRUE, traverse);
3723 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3724 _collection_query(rule, sortby, &result, 0, max, current, 0, EINA_FALSE, NULL, EINA_TRUE, traverse);
3727 ERR("Tree parameter value not handled");
3733 static Eldbus_Message*
3734 _collection_get_matches_from(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3736 const char *obj_path = eldbus_message_path_get(msg);
3737 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3738 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3739 Eldbus_Message *ret;
3740 Eldbus_Message_Iter *iter, *rule_iter;
3741 struct collection_match_rule rule;
3743 AtspiCollectionTreeTraversalType tree;
3745 AtspiCollectionSortOrder sortby;
3746 Eina_List *result = NULL;
3748 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3750 iter = eldbus_message_iter_get(msg);
3751 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3753 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uuib", &obj_path, &rule_iter, &sortby, &tree, &count, &traverse))
3755 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3758 current = _bridge_object_from_path(bridge, obj_path);
3760 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3762 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3763 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3765 result = _collection_get_matches_from_handle(obj, current, &rule, sortby, tree, count, traverse);
3766 ret = _collection_return_msg_from_list(bridge, msg, result);
3768 eina_list_free(result);
3769 _collection_match_rule_free(&rule);
3775 _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)
3777 Eina_List *result = NULL;
3778 Eo *collection = obj;
3781 eo_do(obj, collection = elm_interface_atspi_accessible_parent_get());
3785 case ATSPI_Collection_TREE_INORDER:
3786 _collection_inbackorder(obj, rule, &result, max, current);
3787 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
3788 result = eina_list_reverse(result);
3790 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
3791 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3793 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
3794 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
3797 ERR("Tree parameter value not handled");
3804 static Eldbus_Message*
3805 _collection_get_matches_to(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
3807 const char *obj_path = eldbus_message_path_get(msg);
3808 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3809 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
3810 Eldbus_Message *ret;
3811 Eldbus_Message_Iter *iter, *rule_iter;
3812 struct collection_match_rule rule;
3814 AtspiCollectionTreeTraversalType tree;
3816 AtspiCollectionSortOrder sortby;
3817 Eina_List *result = NULL;
3820 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3822 iter = eldbus_message_iter_get(msg);
3823 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3825 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uubib", &obj_path, &rule_iter, &sortby, &tree, &limit, &count, &traverse))
3827 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, tree, limit count or traverse values.");
3830 current = _bridge_object_from_path(bridge, obj_path);
3832 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3834 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3835 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3837 result = _collection_get_matches_to_handle(obj, current, &rule, sortby, tree, limit, count, traverse);
3838 ret = _collection_return_msg_from_list(bridge, msg, result);
3840 eina_list_free(result);
3841 _collection_match_rule_free(&rule);
3846 static Eldbus_Message*
3847 _collection_get_matches(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
3849 const char *obj_path = eldbus_message_path_get(msg);
3850 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3851 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3852 Eldbus_Message *ret;
3853 Eldbus_Message_Iter *iter, *rule_iter;
3854 struct collection_match_rule rule;
3857 AtspiCollectionSortOrder sortby;
3858 Eina_List *result = NULL;
3860 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3862 iter = eldbus_message_iter_get(msg);
3863 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3865 if (!eldbus_message_iter_arguments_get(iter, "(aiia{ss}iaiiasib)uib", &rule_iter, &sortby, &count, &traverse))
3867 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3870 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3871 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3873 _collection_query(&rule, sortby, &result, 0, count, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3875 ret = _collection_return_msg_from_list(bridge, msg, result);
3877 eina_list_free(result);
3878 _collection_match_rule_free(&rule);
3883 static const Eldbus_Method collection_methods[] = {
3885 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3886 {"u", "sortby"}, {"u", "tree"}, {"i", "count"}, {"b", "traverse"}),
3887 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_from, 0 },
3889 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3890 {"u", "sortby"}, {"u", "tree"}, {"b", "limit_scope"},
3891 {"i", "count"}, {"b", "traverse"}),
3892 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_to, 0 },
3894 ELDBUS_ARGS({"(aiia{ss}iaiiasib)", "match_rule"},
3895 {"u", "sortby"}, {"i", "count"}, {"b", "traverse"}),
3896 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches, 0 },
3897 { NULL, NULL, NULL, NULL, 0 }
3900 static const Eldbus_Service_Interface_Desc collection_iface_desc = {
3901 ATSPI_DBUS_INTERFACE_COLLECTION, collection_methods, NULL, NULL, NULL, NULL
3905 _object_get_bus_name_and_path(Eo *bridge, const Eo *obj, const char **bus_name, const char **path)
3907 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
3909 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
3910 if (eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
3912 const char *pbus = "", *ppath = ATSPI_DBUS_PATH_NULL;
3913 eo_do(obj, elm_obj_atspi_proxy_address_get(&pbus, &ppath));
3916 if (bus_name) *bus_name = pbus;
3917 if (path) *path = ppath;
3920 DBG("Invalid proxy address! Address not set before connecting/listening. Or after proxy is removed.");
3922 if (bus_name) *bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
3923 if (path) *path = _bridge_path_from_object(bridge, obj);
3928 _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj)
3930 EINA_SAFETY_ON_NULL_RETURN(iter);
3932 const char *pbus = NULL, *ppath = NULL;
3933 _object_get_bus_name_and_path(bridge, obj, &pbus, &ppath);
3934 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3935 eldbus_message_iter_basic_append(iter_struct, 's', pbus);
3936 eldbus_message_iter_basic_append(iter_struct, 'o', ppath);
3937 eldbus_message_iter_container_close(iter, iter_struct);
3941 _object_desktop_reference_append(Eldbus_Message_Iter *iter)
3943 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
3944 EINA_SAFETY_ON_NULL_RETURN(iter);
3946 eldbus_message_iter_basic_append(iter_struct, 's', ATSPI_DBUS_NAME_REGISTRY);
3947 eldbus_message_iter_basic_append(iter_struct, 'o', ATSPI_DBUS_PATH_ROOT);
3948 eldbus_message_iter_container_close(iter, iter_struct);
3952 _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj)
3954 Eldbus_Message_Iter *iter_array;
3955 iter_array = eldbus_message_iter_container_new(iter, 'a', "s");
3956 if (!iter_array) return;
3958 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
3960 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE);
3961 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COLLECTION);
3963 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN))
3964 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACTION);
3965 if (eo_isa(obj, ELM_ATSPI_APP_OBJECT_CLASS))
3966 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_APPLICATION);
3967 if (eo_isa(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN))
3968 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COMPONENT);
3969 if (eo_isa(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE))
3970 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_EDITABLE_TEXT);
3971 if (eo_isa(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN))
3972 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_IMAGE);
3973 if (eo_isa(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
3974 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_SELECTION);
3975 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
3976 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_TEXT);
3977 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
3978 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_VALUE);
3980 eldbus_message_iter_container_close(iter, iter_array);
3984 _cache_item_reference_append_cb(Eo *bridge, Eo *data, Eldbus_Message_Iter *iter_array)
3986 if (!eo_ref_get(data) || eo_destructed_is(data))
3989 Eldbus_Message_Iter *iter_struct, *iter_sub_array;
3990 Elm_Atspi_State_Set states;
3991 Elm_Atspi_Role role;
3992 Eo *root = elm_atspi_bridge_root_get(bridge);
3994 eo_do(data, role = elm_interface_atspi_accessible_role_get());
3996 iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
3997 EINA_SAFETY_ON_NULL_RETURN_VAL(iter_struct, EINA_TRUE);
3999 /* Marshall object path */
4000 _bridge_iter_object_reference_append(bridge, iter_struct, data);
4002 /* Marshall application */
4003 _bridge_iter_object_reference_append(bridge, iter_struct, root);
4006 eo_do(data, parent = elm_interface_atspi_accessible_parent_get());
4007 /* Marshall parent */
4008 if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role))
4009 _object_desktop_reference_append(iter_struct);
4011 _bridge_iter_object_reference_append(bridge, iter_struct, parent);
4013 /* Marshall children */
4014 Eina_List *children_list = NULL, *l;
4017 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
4018 Elm_Atspi_State_Set ss;
4019 eo_do(data, ss = elm_interface_atspi_accessible_state_set_get());
4021 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
4022 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
4024 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
4025 if (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
4027 eo_do(data, children_list = elm_interface_atspi_accessible_children_get());
4029 EINA_LIST_FOREACH(children_list, l, child)
4030 _bridge_iter_object_reference_append(bridge, iter_sub_array, child);
4032 //TIZEN_ONLY(20150709) Do not register children of MANAGES_DESCENDATS objects
4033 eina_list_free(children_list);
4037 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4039 /* Marshall interfaces */
4040 _iter_interfaces_append(iter_struct, data);
4043 const char *name = NULL;
4044 eo_do(data, name = elm_interface_atspi_accessible_name_get());
4048 eldbus_message_iter_basic_append(iter_struct, 's', name);
4051 eldbus_message_iter_basic_append(iter_struct, 'u', role);
4053 /* Marshall description */
4054 const char* descritpion = NULL;
4055 eo_do(data, descritpion = elm_interface_atspi_accessible_description_get());
4058 eldbus_message_iter_basic_append(iter_struct, 's', descritpion);
4060 /* Marshall state set */
4061 iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "u");
4062 EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
4064 eo_do(data, states = elm_interface_atspi_accessible_state_set_get());
4066 unsigned int s1 = states & 0xFFFFFFFF;
4067 unsigned int s2 = (states >> 32) & 0xFFFFFFFF;
4068 eldbus_message_iter_basic_append(iter_sub_array, 'u', s1);
4069 eldbus_message_iter_basic_append(iter_sub_array, 'u', s2);
4071 eldbus_message_iter_container_close(iter_struct, iter_sub_array);
4072 eldbus_message_iter_container_close(iter_array, iter_struct);
4077 if (iter_struct) eldbus_message_iter_del(iter_struct);
4081 static Eldbus_Message *
4082 _cache_get_items(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
4084 Eldbus_Message_Iter *iter, *iter_array;
4085 Eldbus_Message *ret;
4086 Eina_List *to_process;
4089 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4090 if (!bridge) return NULL;
4092 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4094 ret = eldbus_message_method_return_new(msg);
4095 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4097 iter = eldbus_message_iter_get(ret);
4098 iter_array = eldbus_message_iter_container_new(iter, 'a', CACHE_ITEM_SIGNATURE);
4099 EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
4101 eo_do(bridge, root = elm_obj_atspi_bridge_root_get());
4102 to_process = eina_list_append(NULL, root);
4106 Eo *obj = eina_list_data_get(to_process);
4107 to_process = eina_list_remove_list(to_process, to_process);
4108 _cache_item_reference_append_cb(bridge, obj, iter_array);
4109 _bridge_object_register(bridge, obj);
4111 Eina_List *children;
4112 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
4113 to_process = eina_list_merge(to_process, children);
4116 eldbus_message_iter_container_close(iter, iter_array);
4120 if (ret) eldbus_message_unref(ret);
4124 static const Eldbus_Method cache_methods[] = {
4125 { "GetItems", NULL, ELDBUS_ARGS({CACHE_ITEM_SIGNATURE, "items"}), _cache_get_items, 0 },
4126 { NULL, NULL, NULL, NULL, 0 }
4129 static const Eldbus_Signal cache_signals[] = {
4130 [ATSPI_OBJECT_CHILD_ADDED] = { "AddAccessible", ELDBUS_ARGS({"((so)(so)a(so)assusau)", "added"}), 0},
4131 [ATSPI_OBJECT_CHILD_REMOVED] = { "RemoveAccessible", ELDBUS_ARGS({ "(so)", "removed" }), 0},
4135 static const Eldbus_Service_Interface_Desc cache_iface_desc = {
4136 ATSPI_DBUS_INTERFACE_CACHE, cache_methods, cache_signals, NULL, NULL, NULL
4139 // Component interface
4140 static Eldbus_Message *
4141 _component_contains(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4143 const char *obj_path = eldbus_message_path_get(msg);
4144 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4145 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4147 Eina_Bool contains = EINA_FALSE;
4148 AtspiCoordType coord_type;
4149 Eldbus_Message *ret;
4151 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4153 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4154 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4156 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4157 eo_do(obj, contains = elm_interface_atspi_component_contains(type, x, y));
4159 ret = eldbus_message_method_return_new(msg);
4160 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4162 eldbus_message_arguments_append(ret, "b", contains);
4167 static Eldbus_Message *
4168 _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4170 const char *obj_path = eldbus_message_path_get(msg);
4171 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4172 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4173 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
4175 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4177 Eo *accessible = NULL;
4178 AtspiCoordType coord_type;
4179 Eldbus_Message *ret;
4180 Eldbus_Message_Iter *iter;
4182 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4184 // TIZEN_ONLY(20161213) - do not response if ecore evas is obscured
4185 if (_ee_obscured_get(obj))
4186 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "ecore evas is obscured.");
4189 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
4190 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4192 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
4193 Evas_Object *top = elm_object_top_widget_get(obj);
4196 eo_do(top, elm_interface_atspi_component_socket_offset_get(&sx, &sy));
4202 ret = eldbus_message_method_return_new(msg);
4203 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4205 iter = eldbus_message_iter_get(ret);
4206 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4207 eo_do(obj, accessible = elm_interface_atspi_component_accessible_at_point_get(type, x, y));
4208 _bridge_iter_object_reference_append(bridge, iter, accessible);
4209 _bridge_object_register(bridge, accessible);
4214 // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
4216 NEIGHBOR_SEARCH_MODE_NORMAL = 0,
4217 NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT = 1,
4218 NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING = 2,
4219 NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE = 3,
4220 } GetNeighborSearchMode;
4222 typedef struct accessibility_navigation_pointer_table {
4223 AtspiRole (*object_get_role)(struct accessibility_navigation_pointer_table *t, void *ptr);
4224 uint64_t (*object_get_state_set)(struct accessibility_navigation_pointer_table *t, void *ptr);
4225 void *(*get_object_in_relation_by_type)(struct accessibility_navigation_pointer_table *t, void *ptr, AtspiRelationType type);
4226 unsigned char (*object_is_zero_size)(struct accessibility_navigation_pointer_table *t, void *ptr);
4227 void *(*get_parent)(struct accessibility_navigation_pointer_table *t, void *ptr);
4228 unsigned char (*object_is_scrollable)(struct accessibility_navigation_pointer_table *t, void *ptr);
4229 void *(*get_object_at_point)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4230 unsigned char (*object_contains)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based);
4231 unsigned char (*object_is_proxy)(struct accessibility_navigation_pointer_table *t, void *ptr);
4232 } accessibility_navigation_pointer_table;
4234 #define CALL(fncname, ...) table->fncname(table, __VA_ARGS__)
4235 static unsigned char _accept_object_check_role(accessibility_navigation_pointer_table *table EINA_UNUSED, void *obj)
4237 return _elm_widget_atspi_role_acceptable_check(obj);
4240 static unsigned char _state_set_is_set(uint64_t state_set, AtspiStateType state)
4242 return (state_set & ((uint64_t)1 << (unsigned int)state)) != 0;
4245 static unsigned char _object_is_defunct(accessibility_navigation_pointer_table *table, void *ptr)
4247 uint64_t states = CALL(object_get_state_set, ptr);
4248 return _state_set_is_set(states, ATSPI_STATE_DEFUNCT);
4251 static unsigned char _object_role_is_acceptable_when_navigating_next_prev(accessibility_navigation_pointer_table *table, void *obj)
4253 AtspiRole role = CALL(object_get_role, obj);
4254 return role != ATSPI_ROLE_POPUP_MENU && role != ATSPI_ROLE_DIALOG;
4257 static void *_get_object_in_relation_flow(accessibility_navigation_pointer_table *table, void *source, unsigned char forward)
4259 return CALL(get_object_in_relation_by_type, source, forward ? ATSPI_RELATION_FLOWS_TO : ATSPI_RELATION_FLOWS_FROM);
4262 static unsigned char _object_is_item(accessibility_navigation_pointer_table *table, void *obj)
4264 AtspiRole role = CALL(object_get_role, obj);
4265 return role == ATSPI_ROLE_LIST_ITEM || role == ATSPI_ROLE_MENU_ITEM;
4268 static unsigned char _object_is_highlightable(accessibility_navigation_pointer_table *table, void *obj)
4270 uint64_t state_set = CALL(object_get_state_set, obj);
4271 return _state_set_is_set(state_set, ATSPI_STATE_HIGHLIGHTABLE);
4274 static unsigned char _object_is_visible(accessibility_navigation_pointer_table *table, void *obj)
4276 uint64_t state_set = CALL(object_get_state_set, obj);
4277 return _state_set_is_set(state_set, ATSPI_STATE_VISIBLE);
4280 static unsigned char _object_is_showing(accessibility_navigation_pointer_table *table, void *obj)
4282 uint64_t state_set = CALL(object_get_state_set, obj);
4283 return _state_set_is_set(state_set, ATSPI_STATE_SHOWING);
4286 static unsigned char _object_is_collapsed(accessibility_navigation_pointer_table *table, void *obj)
4288 uint64_t state_set = CALL(object_get_state_set, obj);
4290 _state_set_is_set(state_set, ATSPI_STATE_EXPANDABLE) &&
4291 !_state_set_is_set(state_set, ATSPI_STATE_EXPANDED);
4294 static unsigned char _object_has_modal_state(accessibility_navigation_pointer_table *table, void *obj)
4296 uint64_t state_set = CALL(object_get_state_set, obj);
4297 return _state_set_is_set(state_set, ATSPI_STATE_MODAL);
4300 static unsigned char _object_is_zero_size(accessibility_navigation_pointer_table *table, void *obj)
4302 return CALL(object_is_zero_size, obj);
4305 static void *_get_scrollable_parent(accessibility_navigation_pointer_table *table, void *obj)
4309 obj = CALL(get_parent, obj);
4310 if (obj && CALL(object_is_scrollable, obj)) return obj;
4314 static unsigned char _accept_object(accessibility_navigation_pointer_table *table, void *obj)
4317 if (!_object_is_visible(table, obj)) return 0;
4318 if (!_accept_object_check_role(table, obj)) return 0;
4319 if (CALL(get_object_in_relation_by_type, obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0;
4320 if (!_object_is_highlightable(table, obj)) return 0;
4322 if (_get_scrollable_parent(table, obj) != NULL)
4324 void *parent = CALL(get_parent, obj);
4328 return !_object_is_item(table, obj) || !_object_is_collapsed(table, parent);
4333 if (_object_is_zero_size(table, obj)) return 0;
4334 if (!_object_is_showing(table, obj)) return 0;
4339 /* The target cannot be a parent of root */
4340 static Eina_Bool _target_validation_check(Eo *target, Eo *root)
4343 eo_do(root, parent = elm_interface_atspi_accessible_parent_get());
4347 if (parent == target) return EINA_FALSE;
4348 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4354 static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigation_pointer_table *table,
4355 void *root, int x, int y, unsigned char coordinates_are_screen_based)
4357 if (!root) return NULL;
4358 void *prev_root = root;
4360 void *return_value = NULL;
4363 void *target = CALL(get_object_at_point, root, x, y, coordinates_are_screen_based);
4365 if (target == root || target == prev_root) break;
4366 if (!_target_validation_check(target, root)) break;
4368 // always return proxy, so atspi lib can call on it again
4369 if (CALL(object_is_proxy, target)) return target;
4372 void *relation_obj = CALL(get_object_in_relation_by_type, root, ATSPI_RELATION_CONTROLLED_BY);
4373 unsigned char contains = 0;
4376 contains = CALL(object_contains, relation_obj, x, y, coordinates_are_screen_based);
4377 if (contains) root = relation_obj;
4380 if (_accept_object(table, root))
4382 return_value = root;
4383 if (contains) break;
4387 if (return_value && _object_has_modal_state(table, return_value)) return_value = NULL;
4388 return return_value;
4391 static void *_find_non_defunct_child(accessibility_navigation_pointer_table *table,
4392 Eina_List *children, unsigned int current_index, unsigned char forward)
4394 unsigned int children_count = eina_list_count(children);
4395 for(; current_index < children_count; forward ? ++current_index : --current_index)
4397 void *n = eina_list_nth(children, current_index);
4398 if (n && !_object_is_defunct(table, n)) return n;
4403 static void *_directional_depth_first_search_try_non_defunct_child(accessibility_navigation_pointer_table *table,
4404 void *node, Eina_List *children, unsigned char forward)
4406 unsigned int children_count = eina_list_count(children);
4407 if (children_count > 0)
4409 unsigned char is_showing = _get_scrollable_parent(table, node) == NULL ? _object_is_showing(table, node) : 1;
4412 return _find_non_defunct_child(table, children, forward ? 0 : children_count - 1, forward);
4418 static Eina_List *_scrollable_parent_list_get(Eo *obj)
4420 Eina_List *ret = NULL;
4425 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
4428 if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4430 ret = eina_list_append(ret, parent);
4432 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
4439 static void _viewport_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
4441 eo_do(obj, elm_interface_scrollable_content_viewport_geometry_get(x, y, w, h));
4442 /* widget implements scrollable interface but does not use scoller
4443 in this case, use widget geometry */
4444 if (*w == 0 || *h == 0)
4446 INF("%s is zero sized content viewport", eo_class_name_get(eo_class_get(obj)));
4447 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_FALSE, x, y, w, h));
4452 _new_scrollable_parent_viewport_geometry_get(Eo *node, Eo *start,
4453 int *x, int *y, int *w, int *h)
4455 Eina_Bool ret = EINA_FALSE;
4459 n_spl = _scrollable_parent_list_get(node);
4460 s_spl = _scrollable_parent_list_get(start);
4464 EINA_LIST_FOREACH(s_spl, l, sp)
4466 n_spl = eina_list_remove(n_spl, sp);
4469 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4471 unsigned int count = eina_list_count(n_spl);
4474 sp = eina_list_nth(n_spl, count - 1);
4475 _viewport_geometry_get(sp, &sx, &sy, &sw, &sh);
4487 static Eina_List *_valid_children_get(Eina_List *children, Eo *start, Eo *root)
4489 /* condition to find first(last) object regardless of scrollable parent.
4490 looping navigation does not care scrollable parent.
4491 1. currently highlighted object exists
4492 2. both start and root are same */
4493 Eo *current = _elm_object_accessibility_currently_highlighted_get();
4494 if (current && start == root) return children;
4497 child = eina_list_nth(children, 0);
4501 Evas_Coord x = 0, y = 0, w = 0, h = 0;
4502 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
4504 if (_new_scrollable_parent_viewport_geometry_get(child, start,
4505 &sx, &sy, &sw, &sh))
4507 Eina_List *l, *l_next;
4508 EINA_LIST_FOREACH_SAFE(children, l, l_next, child)
4511 elm_interface_atspi_component_extents_get(EINA_FALSE,
4513 if (w == 0 || h == 0 ||
4514 !ELM_RECTS_INTERSECT(x, y, w, h, sx, sy, sw, sh))
4515 children = eina_list_remove_list(children, l);
4522 static void *_get_next_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4523 void *obj, void *start, void *root, unsigned char forward)
4525 if (!obj) return NULL;
4526 void *parent = CALL(get_parent, obj);
4527 if (!parent) return NULL;
4529 Eina_List *children;
4530 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
4531 children = _valid_children_get(children, start, root);
4533 unsigned int children_count = eina_list_count(children);
4534 if (children_count == 0)
4536 eina_list_free(children);
4539 unsigned int current = 0;
4540 for(; current < children_count && eina_list_nth(children, current) != obj; ++current) ;
4541 if (current >= children_count)
4543 eina_list_free(children);
4546 forward ? ++current : --current;
4547 void *ret = _find_non_defunct_child(table, children, current, forward);
4548 eina_list_free(children);
4553 _directional_depth_first_search_try_non_defunct_sibling(accessibility_navigation_pointer_table *table,
4554 unsigned char *all_children_visited_ptr,
4555 void *node, void *start, void *root,
4556 unsigned char forward)
4560 void *sibling = _get_next_non_defunct_sibling(table, node, start, root, forward);
4561 if (sibling != NULL)
4564 *all_children_visited_ptr = 0;
4569 node = CALL(get_parent, node);
4570 if (node == NULL || node == root) return NULL;
4572 // in backward traversing stop the walk up on parent
4573 if (!forward) break;
4580 unsigned int current_search_size;
4581 unsigned int counter;
4582 } cycle_detection_data;
4584 void cycle_detection_initialize(cycle_detection_data *data, const void *key)
4588 data->current_search_size = 1;
4592 unsigned char cycle_detection_check_if_in_cycle(cycle_detection_data *data, const void *key)
4594 if (!data) return 1;
4595 if (data->key == key) return 1;
4596 if (--data->counter == 0)
4598 data->current_search_size <<= 1;
4599 if (data->current_search_size == 0) return 1;
4600 data->counter = data->current_search_size;
4609 if (eo_isa(obj, ELM_ACCESS_CLASS))
4611 Elm_Access_Info *info;
4613 info = _elm_access_info_get(obj);
4614 if (info && eo_isa(info->part_object, ELM_LAYOUT_CLASS))
4616 Eina_List *attrs, *l;
4617 Elm_Atspi_Attribute *attr;
4619 eo_do(info->part_object,
4620 attrs = elm_interface_atspi_accessible_attributes_get());
4621 EINA_LIST_FOREACH(attrs, l, attr)
4623 if (!strcmp(attr->key, "___PlugID"))
4625 elm_atspi_attributes_list_free(attrs);
4629 elm_atspi_attributes_list_free(attrs);
4636 _proxy_in_parent_get(Eo *obj)
4640 Eina_List *children_list = NULL;
4641 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4644 EINA_LIST_FOREACH(children_list, l, child)
4646 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4652 eina_list_free(children_list);
4658 _deputy_of_proxy_in_parent_get(Eo *obj)
4662 Eina_List *children_list = NULL;
4663 eo_do(obj, children_list = elm_interface_atspi_accessible_children_get());
4665 unsigned int index = 0;
4667 EINA_LIST_FOREACH(children_list, l, child)
4669 if (eo_isa(child, ELM_ATSPI_PROXY_CLASS))
4673 WRN("Proxy does not have deputy object");
4677 deputy = eina_list_nth(children_list, index - 1);
4682 eina_list_free(children_list);
4688 _check_chain_end_with_attribute(Eo *obj, unsigned char forward)
4690 Eina_List *attrs, *l;
4691 Elm_Atspi_Attribute *attr;
4692 eo_do(obj, attrs = elm_interface_atspi_accessible_attributes_get());
4695 EINA_LIST_FOREACH(attrs, l, attr)
4697 if (!strcmp(attr->key, "relation_chain_end"))
4699 if (((!strcmp(attr->value, "prev,end")) && forward == 0) || ((!strcmp(attr->value, "next,end")) && forward == 1) || (!strcmp(attr->value, "prev,next,end")))
4701 elm_atspi_attributes_list_free(attrs);
4706 elm_atspi_attributes_list_free(attrs);
4710 static void *_calculate_neighbor_impl(accessibility_navigation_pointer_table *table, void *root, void *start, unsigned char forward, GetNeighborSearchMode search_mode)
4712 if (start && _check_chain_end_with_attribute(start, forward)) return start;
4713 if (root && _object_is_defunct(table, root)) return NULL;
4714 if (start && _object_is_defunct(table, start))
4720 if (search_mode == NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE)
4722 /* This only works if we navigate backward, and it is not possible to
4723 find in embedded process. In this case the deputy should be used */
4724 return _deputy_of_proxy_in_parent_get(start);
4727 void *node = start ? start : root;
4728 if (!node) return NULL;
4730 // initialization of all-children-visited flag for start node - we assume
4731 // that when we begin at start node and we navigate backward, then all children
4732 // are visited, so navigation will ignore start's children and go to
4733 // previous sibling available.
4734 /* Regarding condtion (start != root):
4735 The last object can be found only if all_children_visited is false.
4736 The start is same with root, when looking for the last object. */
4737 unsigned char all_children_visited = (start != root) && (search_mode != NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT && !forward);
4739 // true, if starting element should be ignored. this is only used in rare case of
4740 // recursive search failing to find an object.
4741 // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
4742 // element A algorithm has to descend into BUS_B and search element B and its children. this is done
4743 // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
4744 // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
4745 // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
4746 // this flag means, that object A was already checked previously and we should skip it and its children.
4747 unsigned char force_next = (search_mode == NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING);
4749 cycle_detection_data cycle_detection;
4750 cycle_detection_initialize(&cycle_detection, node);
4753 if (_object_is_defunct(table, node)) return NULL;
4755 // always accept proxy object from different world
4756 if (!force_next && CALL(object_is_proxy, node)) return node;
4758 Eina_List *children;
4759 eo_do(node, children = elm_interface_atspi_accessible_children_get());
4760 children = _valid_children_get(children, start, root);
4763 // 1. not start node
4764 // 2. parent after all children in backward traversing
4765 // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
4766 // Objects with those roles shouldnt be reachable, when navigating next / prev.
4767 unsigned char all_children_visited_or_moving_forward = (eina_list_count(children) == 0 || forward || all_children_visited);
4768 if (!force_next && node != start && all_children_visited_or_moving_forward && _accept_object(table, node))
4770 if (start == NULL || _object_role_is_acceptable_when_navigating_next_prev(table, node))
4772 eina_list_free(children);
4777 void *next_related_in_direction = !force_next ? _get_object_in_relation_flow(table, node, forward) : NULL;
4779 /* force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
4780 in this case the node is elm_layout which is parent of proxy object.
4781 There is an access object working for the proxy object, and the access
4782 object could have relation information. This relation information should
4783 be checked first before using the elm_layout as a node. */
4784 if (force_next && forward)
4787 deputy = _deputy_of_proxy_in_parent_get(node);
4788 next_related_in_direction =
4789 _get_object_in_relation_flow(table, deputy, forward);
4792 if (next_related_in_direction && _object_is_defunct(table, next_related_in_direction))
4793 next_related_in_direction = NULL;
4794 unsigned char want_cycle_detection = 0;
4795 if (next_related_in_direction)
4797 /* Check next_related_in_direction is deputy object */
4801 /* If the prev object is deputy, then go to inside of its proxy first */
4802 if (_deputy_is(next_related_in_direction))
4804 parent = elm_widget_parent_get(next_related_in_direction);
4805 next_related_in_direction =
4806 _proxy_in_parent_get(parent);
4811 /* If current object is deputy, and it has relation next object,
4812 then do not use the relation next object, and use proxy first */
4813 if (_deputy_is(node))
4815 parent = elm_widget_parent_get(node);
4816 next_related_in_direction =
4817 _proxy_in_parent_get(parent);
4821 node = next_related_in_direction;
4822 want_cycle_detection = 1;
4825 void *child = !force_next && !all_children_visited ?
4826 _directional_depth_first_search_try_non_defunct_child(table, node, children, forward) : NULL;
4827 if (child != NULL) want_cycle_detection = 1;
4830 if (!force_next && node == root)
4832 eina_list_free(children);
4835 all_children_visited = 1;
4836 child = _directional_depth_first_search_try_non_defunct_sibling(table, &all_children_visited, node, start, root, forward);
4842 if (want_cycle_detection && cycle_detection_check_if_in_cycle(&cycle_detection, node))
4844 eina_list_free(children);
4847 eina_list_free(children);
4852 typedef struct accessibility_navigation_pointer_table_impl {
4853 accessibility_navigation_pointer_table ptrs;
4855 } accessibility_navigation_pointer_table_impl;
4857 static AtspiRole _object_get_role_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4859 Elm_Atspi_Role role;
4861 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
4862 return _elm_role_to_atspi_role(role);
4865 static uint64_t _object_get_state_set_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4867 Elm_Atspi_State_Set states;
4869 eo_do(obj, states = elm_interface_atspi_accessible_state_set_get());
4870 return _elm_atspi_state_set_to_atspi_state_set(states);
4873 static void *_get_object_in_relation_by_type_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr, AtspiRelationType type)
4877 const Eo *source = ptr;
4878 Elm_Atspi_Relation_Set relations;
4879 Elm_Atspi_Relation_Type expected_relation_type = _atspi_relation_to_elm_relation(type);
4880 eo_do(source, relations = elm_interface_atspi_accessible_relation_set_get());
4881 Elm_Atspi_Relation *rel;
4883 EINA_LIST_FOREACH(relations, l, rel)
4885 if (rel->type == expected_relation_type)
4887 Eina_List *last = eina_list_last(rel->objects);
4888 return eina_list_data_get(last);
4895 static unsigned char _object_is_zero_size_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4899 eo_do(obj, elm_interface_atspi_component_extents_get(EINA_TRUE, &x, &y, &w, &h));
4900 return w == 0 || h == 0;
4903 unsigned char _object_is_scrollable_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4906 return eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
4909 void *_get_parent_impl(struct accessibility_navigation_pointer_table *table EINA_UNUSED, void *ptr)
4911 Eo *obj = (Eo*)ptr, *ret_obj;
4912 eo_do(obj, ret_obj = elm_interface_atspi_accessible_parent_get());
4916 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)
4918 Eo *obj = (Eo*)ptr, *target;
4919 eo_do(obj, target = elm_interface_atspi_component_accessible_at_point_get(coordinates_are_screen_based, x, y));
4923 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)
4926 Eina_Bool return_value;
4927 eo_do(obj, return_value = elm_interface_atspi_component_contains(coordinates_are_screen_based, x, y));
4928 return return_value ? 1 : 0;
4931 unsigned char _object_is_proxy_impl(struct accessibility_navigation_pointer_table *table_, void *obj)
4933 accessibility_navigation_pointer_table_impl *table = (accessibility_navigation_pointer_table_impl*)table_;
4934 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(table->bridge, pd, 0);
4935 const char *our_bus_name = eldbus_connection_unique_name_get(pd->a11y_bus);
4936 const char *obj_bus_name;
4937 _object_get_bus_name_and_path(table->bridge, (Eo*)obj, &obj_bus_name, NULL);
4938 return our_bus_name && obj_bus_name && strcmp(our_bus_name, obj_bus_name) != 0;
4941 accessibility_navigation_pointer_table_impl construct_accessibility_navigation_pointer_table(Eo *bridge)
4943 accessibility_navigation_pointer_table_impl table;
4944 #define INIT(n) table.ptrs.n = _## n ## _impl
4945 INIT(object_get_role);
4946 INIT(object_get_state_set);
4947 INIT(get_object_in_relation_by_type);
4948 INIT(object_is_zero_size);
4950 INIT(object_is_scrollable);
4951 INIT(get_object_at_point);
4952 INIT(object_contains);
4953 INIT(object_is_proxy);
4955 table.bridge = bridge;
4960 static Eo *_calculate_navigable_accessible_at_point(Eo *bridge, Eo *root, Eina_Bool coord_type, int x, int y)
4962 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4963 Eo *result = (Eo*)_calculate_navigable_accessible_at_point_impl(&table.ptrs, root, x, y, coord_type ? 1 : 0);
4967 static Eo *_calculate_neighbor(Eo *bridge, Eo *root, Eo *start, Eina_Bool forward, int search_mode)
4969 accessibility_navigation_pointer_table_impl table = construct_accessibility_navigation_pointer_table(bridge);
4970 Eo *result = (Eo*)_calculate_neighbor_impl(&table.ptrs, root, start, forward ? 1 : 0, (GetNeighborSearchMode)search_mode);
4976 static Eldbus_Message *
4977 _component_get_extents(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
4979 const char *obj_path = eldbus_message_path_get(msg);
4980 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
4981 Eo *obj = _bridge_object_from_path(bridge, obj_path);
4983 AtspiCoordType coord_type;
4984 Eldbus_Message *ret;
4985 Eldbus_Message_Iter *iter, *iter_struct;
4987 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
4989 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
4990 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
4992 ret = eldbus_message_method_return_new(msg);
4993 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
4995 iter = eldbus_message_iter_get(ret);
4997 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
4998 eo_do(obj, elm_interface_atspi_component_extents_get(type, &x, &y, &w, &h));
4999 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
5000 EINA_SAFETY_ON_NULL_GOTO(iter_struct, fail);
5002 eldbus_message_iter_basic_append(iter_struct, 'i', x);
5003 eldbus_message_iter_basic_append(iter_struct, 'i', y);
5004 eldbus_message_iter_basic_append(iter_struct, 'i', w);
5005 eldbus_message_iter_basic_append(iter_struct, 'i', h);
5007 eldbus_message_iter_container_close(iter, iter_struct);
5011 if (ret) eldbus_message_unref(ret);
5015 static Eldbus_Message *
5016 _component_get_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5018 const char *obj_path = eldbus_message_path_get(msg);
5019 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5020 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5022 AtspiCoordType coord_type;
5023 Eldbus_Message *ret;
5025 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5027 if (!eldbus_message_arguments_get(msg, "u", &coord_type))
5028 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5030 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5031 eo_do(obj, elm_interface_atspi_component_position_get(type, &x, &y));
5033 ret = eldbus_message_method_return_new(msg);
5034 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5036 eldbus_message_arguments_append(ret, "i", x);
5037 eldbus_message_arguments_append(ret, "i", y);
5042 static Eldbus_Message *
5043 _component_get_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5045 const char *obj_path = eldbus_message_path_get(msg);
5046 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5047 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5049 Eldbus_Message *ret;
5051 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5053 eo_do(obj, elm_interface_atspi_component_size_get(&x, &y));
5055 ret = eldbus_message_method_return_new(msg);
5056 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5058 eldbus_message_arguments_append(ret, "i", x);
5059 eldbus_message_arguments_append(ret, "i", y);
5064 static AtspiComponentLayer
5065 _elm_layer_2_atspi_layer(int layer)
5067 if (layer <= ELM_OBJECT_LAYER_BACKGROUND) return ATSPI_LAYER_CANVAS;
5068 if (layer < ELM_OBJECT_LAYER_FOCUS) return ATSPI_LAYER_WIDGET;
5069 if (layer <= ELM_OBJECT_LAYER_TOOLTIP) return ATSPI_LAYER_POPUP;
5071 return ATSPI_LAYER_OVERLAY;
5074 static Eldbus_Message *
5075 _component_get_layer(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5077 const char *obj_path = eldbus_message_path_get(msg);
5078 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5079 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5081 Eldbus_Message *ret;
5082 AtspiComponentLayer atspi_layer;
5084 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5086 eo_do(obj, layer = elm_interface_atspi_component_layer_get());
5088 ret = eldbus_message_method_return_new(msg);
5089 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5091 atspi_layer = _elm_layer_2_atspi_layer(layer);
5092 eldbus_message_arguments_append(ret, "u", atspi_layer);
5097 static Eldbus_Message *
5098 _component_grab_focus(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5100 const char *obj_path = eldbus_message_path_get(msg);
5101 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5102 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5103 Eldbus_Message *ret;
5104 Eina_Bool focus = EINA_FALSE;
5107 return _dbus_invalid_ref_error_new(msg);
5109 eo_do(obj, focus = elm_interface_atspi_component_focus_grab());
5111 ret = eldbus_message_method_return_new(msg);
5112 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5114 eldbus_message_arguments_append(ret, "b", focus);
5119 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5120 static Eldbus_Message *
5121 _component_grab_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5123 const char *obj_path = eldbus_message_path_get(msg);
5124 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5125 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5126 Eldbus_Message *ret;
5127 Eina_Bool highlight = EINA_FALSE;
5129 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5131 eo_do(obj, highlight = elm_interface_atspi_component_highlight_grab());
5133 ret = eldbus_message_method_return_new(msg);
5134 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5136 eldbus_message_arguments_append(ret, "b", highlight);
5141 static Eldbus_Message *
5142 _component_clear_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5144 const char *obj_path = eldbus_message_path_get(msg);
5145 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5146 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5147 Eldbus_Message *ret;
5148 Eina_Bool highlight = EINA_FALSE;
5150 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5152 eo_do(obj, highlight = elm_interface_atspi_component_highlight_clear());
5154 ret = eldbus_message_method_return_new(msg);
5155 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5157 eldbus_message_arguments_append(ret, "b", highlight);
5163 static Eldbus_Message *
5164 _component_get_alpha(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5166 const char *obj_path = eldbus_message_path_get(msg);
5167 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5168 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5169 Eldbus_Message *ret;
5173 return _dbus_invalid_ref_error_new(msg);
5175 eo_do(obj, alpha = elm_interface_atspi_component_alpha_get());
5177 ret = eldbus_message_method_return_new(msg);
5178 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5180 eldbus_message_arguments_append(ret, "d", alpha);
5185 static Eldbus_Message *
5186 _component_set_extends(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5188 const char *obj_path = eldbus_message_path_get(msg);
5189 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5190 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5192 AtspiCoordType coord_type;
5193 Eldbus_Message *ret;
5194 Eina_Bool result = EINA_FALSE;
5196 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5198 if (!eldbus_message_arguments_get(msg, "iiiiu", &x, &y, &w, &h, &coord_type))
5199 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5201 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5202 eo_do(obj, result = elm_interface_atspi_component_extents_set(type, x, y, w, h));
5204 ret = eldbus_message_method_return_new(msg);
5205 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5207 eldbus_message_arguments_append(ret, "b", result);
5212 static Eldbus_Message *
5213 _component_set_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5215 const char *obj_path = eldbus_message_path_get(msg);
5216 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5217 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5219 Eina_Bool result = EINA_FALSE;
5220 AtspiCoordType coord_type;
5221 Eldbus_Message *ret;
5223 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5225 if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
5226 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5228 Eina_Bool type = coord_type == ATSPI_COORD_TYPE_SCREEN ? EINA_TRUE : EINA_FALSE;
5229 eo_do(obj, result = elm_interface_atspi_component_position_set(type, x, y));
5231 ret = eldbus_message_method_return_new(msg);
5232 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5234 eldbus_message_arguments_append(ret, "b", result);
5239 static Eldbus_Message *
5240 _component_set_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
5242 const char *obj_path = eldbus_message_path_get(msg);
5243 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
5244 Eo *obj = _bridge_object_from_path(bridge, obj_path);
5247 Eldbus_Message *ret;
5249 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
5251 if (!eldbus_message_arguments_get(msg, "ii", &w, &h))
5252 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
5254 eo_do(obj, result = elm_interface_atspi_component_size_set(w, h));
5256 ret = eldbus_message_method_return_new(msg);
5257 EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
5259 eldbus_message_arguments_append(ret, "b", result);
5264 static const Eldbus_Method component_methods[] = {
5265 { "Contains", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "contains"}), _component_contains, 0 },
5266 { "GetAccessibleAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)", "accessible"}), _component_get_accessible_at_point, 0 },
5267 { "GetExtents", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"(iiii)", "extents"}), _component_get_extents, 0 },
5268 { "GetPosition", ELDBUS_ARGS({"u", "coord_type"}), ELDBUS_ARGS({"i", "x"}, {"i","y"}), _component_get_position, 0 },
5269 { "GetSize", NULL, ELDBUS_ARGS({"i", "w"}, {"i", "h"}), _component_get_size, 0 },
5270 { "GetLayer", NULL, ELDBUS_ARGS({"u", "layer"}), _component_get_layer, 0 },
5271 // { "GetMDIZOrder", NULL, ELDBUS_ARGS({"n", "MDIZOrder"}), _component_get_mdizorder, 0 },
5272 { "GrabFocus", NULL, ELDBUS_ARGS({"b", "focus"}), _component_grab_focus, 0 },
5273 { "GetAlpha", NULL, ELDBUS_ARGS({"d", "alpha"}), _component_get_alpha, 0 },
5274 { "SetExtents", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "width"}, {"i", "height"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_extends, 0 },
5275 { "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
5276 { "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
5278 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
5279 { "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
5280 { "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
5282 { NULL, NULL, NULL, NULL, 0 }
5285 static const Eldbus_Service_Interface_Desc component_iface_desc = {
5286 ATSPI_DBUS_INTERFACE_COMPONENT, component_methods, NULL, NULL, NULL, NULL
5290 _on_elm_atspi_bridge_app_register(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
5292 const char *errname, *errmsg;
5294 if (eldbus_message_error_get(msg, &errname, &errmsg))
5296 ERR("%s %s", errname, errmsg);
5299 DBG("Application successfuly registered at ATSPI2 bus.");
5303 _elm_atspi_bridge_app_register(Eo *bridge)
5305 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5307 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5308 ATSPI_DBUS_PATH_ROOT,
5309 ATSPI_DBUS_INTERFACE_SOCKET,
5311 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5313 _bridge_iter_object_reference_append(bridge, iter, elm_atspi_bridge_root_get(bridge));
5314 eldbus_connection_send(pd->a11y_bus, message, _on_elm_atspi_bridge_app_register, NULL, -1);
5320 _elm_atspi_bridge_app_unregister(Eo *bridge)
5323 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
5325 root = elm_atspi_bridge_root_get(bridge);
5327 Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
5328 ATSPI_DBUS_PATH_ROOT,
5329 ATSPI_DBUS_INTERFACE_SOCKET,
5331 Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
5333 _bridge_iter_object_reference_append(bridge, iter, root);
5334 eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1);
5340 _cache_register(Eo *obj)
5342 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
5343 pd->cache_interface = eldbus_service_interface_register(pd->a11y_bus, CACHE_INTERFACE_PATH, &cache_iface_desc);
5344 eldbus_service_object_data_set(pd->cache_interface, ELM_ATSPI_BRIDGE_CLASS_NAME, obj);
5348 _set_broadcast_flag(const char *event, Eo *bridge)
5351 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5353 tokens = eina_str_split(event, ":", 3);
5355 if (!tokens) return;
5357 if (!strcmp(tokens[0], "Object"))
5359 if (!tokens[1] || *tokens[1] == '\0') return; // do not handle "Object:*"
5360 else if (!strcmp(tokens[1], "StateChanged"))
5362 if (!tokens[2] || *tokens[2] == '\0')
5363 pd->object_state_broadcast_mask = -1; // broadcast all
5364 eina_str_tolower(&tokens[2]);
5365 struct atspi_state_desc *sd = eina_hash_find(pd->state_hash, tokens[2]);
5367 STATE_TYPE_SET(pd->object_state_broadcast_mask, sd->elm_state);
5369 else if (!strcmp(tokens[1], "PropertyChange"))
5371 if (!tokens[2] || *tokens[2] == '\0')
5372 pd->object_property_broadcast_mask = -1; //broadcast all
5373 else if (!strcmp(tokens[2], "AccessibleValue"))
5374 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_VALUE);
5375 else if (!strcmp(tokens[2], "AccessibleName"))
5376 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_NAME);
5377 else if (!strcmp(tokens[2], "AccessibleDescription"))
5378 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_DESCRIPTION);
5379 else if (!strcmp(tokens[2], "AccessibleParent"))
5380 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_PARENT);
5381 else if (!strcmp(tokens[2], "AccessibleRole"))
5382 STATE_TYPE_SET(pd->object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_ROLE);
5384 else if (!strcmp(tokens[1], "ChildrenChanged"))
5386 if (!tokens[2] || *tokens[2] == '\0')
5387 pd->object_children_broadcast_mask = -1; // broadcast all
5388 else if (!strcmp(tokens[2], "add"))
5389 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_ADDED);
5390 else if (!strcmp(tokens[2], "remove"))
5391 STATE_TYPE_SET(pd->object_children_broadcast_mask, ATSPI_OBJECT_CHILD_REMOVED);
5393 else if (!strcmp(tokens[1], "TextChanged"))
5394 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED);
5395 else if (!strcmp(tokens[1], "TextCaretMoved"))
5396 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED);
5397 else if (!strcmp(tokens[1], "TextBoundsChanged"))
5398 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED);
5399 else if (!strcmp(tokens[1], "TextSelectionChanged"))
5400 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED);
5401 else if (!strcmp(tokens[1], "TextAttributesChanged"))
5402 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED);
5403 else if (!strcmp(tokens[1], "VisibleDataChanged"))
5404 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED);
5405 else if (!strcmp(tokens[1], "ActiveDescendantChanged"))
5406 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED);
5407 else if (!strcmp(tokens[1], "BoundsChanged"))
5408 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_BOUNDS_CHANGED);
5409 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5410 else if (!strcmp(tokens[1], "MoveOuted"))
5411 STATE_TYPE_SET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED);
5414 else if (!strcmp(tokens[0], "Window"))
5416 if (!tokens[1] || *tokens[1] == '\0')
5417 pd->window_signal_broadcast_mask = -1; // broadcast all
5418 else if (!strcmp(tokens[1], "Create"))
5419 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_CREATE);
5420 else if (!strcmp(tokens[1], "Destroy"))
5421 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DESTROY);
5422 else if (!strcmp(tokens[1], "Activate"))
5423 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_ACTIVATE);
5424 else if (!strcmp(tokens[1], "Deactivate"))
5425 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DEACTIVATE);
5426 else if (!strcmp(tokens[1], "Maximize"))
5427 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MAXIMIZE);
5428 else if (!strcmp(tokens[1], "Minimize"))
5429 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_MINIMIZE);
5430 else if (!strcmp(tokens[1], "Resize"))
5431 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESIZE);
5432 else if (!strcmp(tokens[1], "Restore"))
5433 STATE_TYPE_SET(pd->window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_RESTORE);
5441 _registered_listeners_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
5443 const char *event, *bus;
5445 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
5446 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
5448 DBG("Updating registered ATSPI signals list.");
5449 pd->object_broadcast_mask = 0;
5450 pd->object_children_broadcast_mask = 0;
5451 pd->object_property_broadcast_mask = 0;
5452 pd->object_state_broadcast_mask = 0;
5453 pd->window_signal_broadcast_mask = 0;
5455 if (eldbus_message_error_get(msg, &event, &bus))
5457 WRN("%s %s", event, bus);
5460 Eldbus_Message_Iter *iter, *siter;
5461 if (!eldbus_message_arguments_get(msg, "a(ss)", &iter))
5463 ERR("Invalid answer type from GetRegisteredEvents method call!");
5466 while (eldbus_message_iter_get_and_next(iter, 'r', &siter))
5468 if (!eldbus_message_iter_arguments_get(siter, "ss", &bus, &event))
5470 ERR("Unable to get message arguments");
5473 _set_broadcast_flag(event, data);
5478 //TIZEN_ONLY(20170910) atspi: emit signal after atspi bridge is connected
5479 pd->connected = EINA_TRUE;
5480 eo_do(data, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_CONNECTED, NULL));
5481 _elm_win_atspi(EINA_TRUE);
5485 eo_do(data, root = elm_obj_atspi_bridge_root_get());
5486 _bridge_cache_build(data, root);
5488 // initialize pending proxy
5489 EINA_LIST_FREE(pd->socket_queue, pr)
5490 _socket_ifc_create(pd->a11y_bus, pr);
5491 EINA_LIST_FREE(pd->plug_queue, pr)
5492 _plug_connect(pd->a11y_bus, pr);
5494 pd->socket_queue = pd->plug_queue = NULL;
5499 _registered_events_list_update(Eo *bridge)
5501 Eldbus_Message *msg;
5502 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5505 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "GetRegisteredEvents");
5506 p = eldbus_connection_send(pd->a11y_bus, msg, _registered_listeners_get, bridge, -1);
5507 pd->pending_requests = eina_list_append(pd->pending_requests, p);
5511 _handle_listener_change(void *data, const Eldbus_Message *msg EINA_UNUSED)
5513 _registered_events_list_update(data);
5516 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5518 _scroll_gesture_required_is(Eo *obj)
5520 Eina_Bool ret = EINA_FALSE;
5521 Eina_List *l, *attr_list = NULL;
5522 Elm_Atspi_Attribute *attr = NULL;
5524 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5525 EINA_LIST_FOREACH(attr_list, l, attr)
5527 if (!strcmp(attr->key, "gesture_required") && !strcmp(attr->value, "scroll"))
5534 elm_atspi_attributes_list_free(attr_list);
5541 _state_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5543 Elm_Atspi_Event_State_Changed_Data *state_data = event_info;
5544 const char *type_desc;
5545 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5547 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
5548 if ((state_data->type == ELM_ATSPI_STATE_ACTIVE) && eo_isa(obj, ELM_WIN_CLASS))
5550 pd->window_activated = state_data->new_value;
5553 // TIZEN_ONLY(20161209): reduce IPC of object:state-changed:showing
5554 if ((state_data->type == ELM_ATSPI_STATE_SHOWING) ||
5555 (state_data->type == ELM_ATSPI_STATE_VISIBLE))
5557 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5558 Elm_Atspi_State_Set ss;
5560 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5561 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
5562 if (state_data->new_value) /* Showing */
5564 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5565 (role != ELM_ATSPI_ROLE_PAGE_TAB) &&
5566 (role != ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW) &&
5567 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)))
5570 else /* Not Showing */
5572 if ((role != ELM_ATSPI_ROLE_WINDOW) &&
5573 (role != ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW) &&
5574 (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MODAL)) &&
5575 (_elm_object_accessibility_currently_highlighted_get() != (void *)obj))
5581 if (!STATE_TYPE_GET(pd->object_state_broadcast_mask, state_data->type))
5584 if ((state_data->type > ELM_ATSPI_STATE_LAST_DEFINED) ||
5585 (int)state_data->type < 0)
5588 type_desc = elm_states_to_atspi_state[state_data->type].name;
5590 //TIZEN_ONLY(20170802): handle "gesture_required" attribute
5591 unsigned int det2 = 0;
5592 if (state_data->type == ELM_ATSPI_STATE_HIGHLIGHTED)
5594 if (_ee_obscured_get(obj))
5597 if (_scroll_gesture_required_is(obj))
5605 _bounds_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5607 Elm_Atspi_Event_Geometry_Changed_Data *geo_data = event_info;
5609 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5610 &_event_obj_signals[ATSPI_OBJECT_EVENT_BOUNDS_CHANGED], "", 0, 0, "(iiii)",
5611 geo_data->x, geo_data->y, geo_data->width, geo_data->height);
5616 _property_changed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5618 const char *property = event_info;
5620 enum _Atspi_Object_Property prop = ATSPI_OBJECT_PROPERTY_LAST;
5622 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5624 if (!strcmp(property, "parent"))
5626 prop = ATSPI_OBJECT_PROPERTY_PARENT;
5627 atspi_desc = "accessible-parent";
5629 else if (!strcmp(property, "name"))
5631 prop = ATSPI_OBJECT_PROPERTY_NAME;
5632 atspi_desc = "accessible-name";
5634 else if (!strcmp(property, "description"))
5636 prop = ATSPI_OBJECT_PROPERTY_DESCRIPTION;
5637 atspi_desc = "accessible-description";
5639 else if (!strcmp(property, "role"))
5641 prop = ATSPI_OBJECT_PROPERTY_ROLE;
5642 atspi_desc = "accessible-role";
5644 else if (!strcmp(property, "value"))
5646 prop = ATSPI_OBJECT_PROPERTY_VALUE;
5647 atspi_desc = "accessible-value";
5649 if (prop == ATSPI_OBJECT_PROPERTY_LAST)
5651 ERR("Unrecognized property name!");
5654 if (!STATE_TYPE_GET(pd->object_property_broadcast_mask, prop))
5656 DBG("Masking property %s changed event.", property);
5660 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5661 &_event_obj_signals[ATSPI_OBJECT_EVENT_PROPERTY_CHANGED], atspi_desc, 0, 0, NULL, NULL);
5666 _visible_data_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5668 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5670 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED))
5673 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5674 &_event_obj_signals[ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED], "",
5681 _active_descendant_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5683 Eo *child = event_info;
5686 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5688 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED))
5691 eo_do(child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5693 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5694 &_event_obj_signals[ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED], "",
5695 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), child);
5700 _children_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5702 const char *atspi_desc = NULL;
5703 Elm_Atspi_Event_Children_Changed_Data *ev_data = event_info;
5705 enum _Atspi_Object_Child_Event_Type type;
5707 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5709 type = ev_data->is_added ? ATSPI_OBJECT_CHILD_ADDED : ATSPI_OBJECT_CHILD_REMOVED;
5711 // update cached objects
5712 if (ev_data->is_added)
5713 _bridge_cache_build(data, ev_data->child);
5715 if (!STATE_TYPE_GET(pd->object_children_broadcast_mask, type))
5720 case ATSPI_OBJECT_CHILD_ADDED:
5722 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5724 case ATSPI_OBJECT_CHILD_REMOVED:
5725 atspi_desc = "remove";
5726 eo_do(ev_data->child, idx = elm_interface_atspi_accessible_index_in_parent_get());
5730 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5731 &_event_obj_signals[ATSPI_OBJECT_EVENT_CHILDREN_CHANGED], atspi_desc,
5732 idx, 0, "(so)", eldbus_connection_unique_name_get(pd->a11y_bus), ev_data->child);
5737 //TIZEN_ONLY(20160623): atspi: moved highlight when object is out of screen
5739 _move_outed_signal_send(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5741 const Elm_Atspi_Move_Outed_Type *type = event_info;
5743 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5745 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_MOVE_OUTED))
5747 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5748 &_event_obj_signals[ATSPI_OBJECT_EVENT_MOVE_OUTED], "", *type, 0, NULL, NULL);
5753 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
5755 _window_activated_detail_value_add(Eo *obj)
5757 unsigned int ret = ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED;
5758 Eina_List *l, *attr_list = NULL;
5759 Elm_Atspi_Attribute *attr = NULL;
5761 eo_do(obj, attr_list = elm_interface_atspi_accessible_attributes_get());
5762 EINA_LIST_FOREACH(attr_list, l, attr)
5764 if (!strcmp(attr->key, "default_label"))
5766 if(!strcmp(attr->value, "enabled_without_window"))
5768 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED_WITHOUT_WINDOW;
5770 else if(!strcmp(attr->value, "disabled"))
5772 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_DISABLED;
5777 elm_atspi_attributes_list_free(attr_list);
5779 Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID;
5780 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
5781 if (role == ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW)
5782 ret |= ELM_ACCESSIBLE_WINDOW_ACTIVATE_INFO_KEYBOARD;
5788 _window_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info EINA_UNUSED)
5790 enum _Atspi_Window_Signals type;
5792 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5794 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED)
5795 type = ATSPI_WINDOW_EVENT_CREATE;
5796 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED)
5797 type = ATSPI_WINDOW_EVENT_DESTROY;
5798 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DEACTIVATED)
5799 type = ATSPI_WINDOW_EVENT_DEACTIVATE;
5800 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5801 type = ATSPI_WINDOW_EVENT_ACTIVATE;
5802 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MAXIMIZED)
5803 type = ATSPI_WINDOW_EVENT_MAXIMIZE;
5804 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_MINIMIZED)
5805 type = ATSPI_WINDOW_EVENT_MINIMIZE;
5806 else if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_RESTORED)
5807 type = ATSPI_WINDOW_EVENT_RESTORE;
5811 if (!STATE_TYPE_GET(pd->window_signal_broadcast_mask, type))
5816 ERR("A11Y connection closed. Unable to send ATSPI event.");
5820 //TIZEN_ONLY(20170925) atspi: send detail value for window activated signal
5821 unsigned int det1 = 0;
5822 if (desc == ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_ACTIVATED)
5823 det1 = _window_activated_detail_value_add(obj);
5826 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_WINDOW,
5827 &_window_obj_signals[type], "", det1, 0, "i", 0);
5832 _selection_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5834 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5836 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_SELECTION_CHANGED))
5839 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5840 &_event_obj_signals[ATSPI_OBJECT_EVENT_SELECTION_CHANGED], "", 0, 0, "i", 0);
5844 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, ...)
5846 Eldbus_Message *msg;
5847 Eldbus_Message_Iter *iter , *iter_stack[64], *iter_struct;
5853 EINA_SAFETY_ON_NULL_RETURN(infc);
5854 EINA_SAFETY_ON_NULL_RETURN(signal);
5855 EINA_SAFETY_ON_NULL_RETURN(minor);
5856 EINA_SAFETY_ON_NULL_RETURN(obj);
5857 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
5859 path = _bridge_path_from_object(bridge, obj);
5861 msg = eldbus_message_signal_new(path, infc, signal->name);
5864 va_start(va, variant_sig);
5866 iter = eldbus_message_iter_get(msg);
5867 eldbus_message_iter_arguments_append(iter, "sii", minor, det1, det2);
5871 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', variant_sig);
5873 const char *tmp = variant_sig;
5879 iter_stack[top + 1] = eldbus_message_iter_container_new(iter_stack[top], 'r', NULL);
5883 eldbus_message_iter_basic_append(iter_stack[top], 's', va_arg(va, char*));
5886 eldbus_message_iter_basic_append(iter_stack[top], 'i', va_arg(va, int));
5889 atspi_obj = va_arg(va, Eo*);
5890 path = _bridge_path_from_object(bridge, atspi_obj);
5891 eldbus_message_iter_basic_append(iter_stack[top], 'o', path);
5894 eldbus_message_iter_container_close(iter_stack[top - 1], iter_stack[top]);
5898 ERR("Not supported d-bus type: %c.", *tmp);
5904 else // AT-SPI implementation forces checks on variant in signature even if not used.
5906 iter_stack[top] = eldbus_message_iter_container_new(iter, 'v', "i");
5907 eldbus_message_iter_basic_append(iter_stack[top], 'i', 0);
5912 ERR("Invalid d-bus signature: () do not match.");
5914 eldbus_message_iter_container_close(iter, iter_stack[0]);
5916 iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
5917 path = _bridge_path_from_object(bridge, elm_atspi_bridge_root_get(bridge));
5918 eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
5919 eldbus_message_iter_basic_append(iter_struct, 'o', path);
5920 eldbus_message_iter_container_close(iter, iter_struct);
5922 eldbus_connection_send(pd->a11y_bus, msg, NULL, NULL, -1);
5923 DBG("Send %s.%s[%s,%d,%d]", infc, signal->name, minor, det1, det2);
5927 _text_caret_moved_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5931 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_FALSE);
5933 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED))
5936 eo_do(obj, cursor_pos = elm_interface_atspi_text_caret_offset_get());
5938 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5939 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED], "", cursor_pos, 0, NULL, NULL);
5945 _text_text_inserted_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5947 Elm_Atspi_Text_Change_Info *info = event_info;
5949 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5951 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5956 WRN("Try to send signal with NULL value");
5960 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5961 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "insert", info->pos, info->len, "s", info->content);
5967 _text_text_removed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
5969 Elm_Atspi_Text_Change_Info *info = event_info;
5971 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5973 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_CHANGED))
5978 WRN("Try to send signal with NULL value");
5982 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5983 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_CHANGED], "delete", info->pos, info->len, "s", info->content);
5989 _text_selection_changed_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
5991 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
5993 if (!STATE_TYPE_GET(pd->object_broadcast_mask, ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED))
5996 _bridge_signal_send(data, obj, ATSPI_DBUS_INTERFACE_EVENT_OBJECT,
5997 &_event_obj_signals[ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED], "", 0, 0, NULL, NULL);
6002 //TIZEN_ONLY(20160527) - Add direct reading feature
6004 _on_reading_state_changed(void *data EINA_UNUSED, const Eldbus_Message *msg)
6007 const char *say_signal_name = "";
6008 Elm_Atspi_Say_Info *say_info;
6010 if (eldbus_message_arguments_get(msg, "is", &i, &say_signal_name))
6011 { if (read_command_id)
6013 say_info = eina_hash_find(read_command_id, &i);
6016 if (say_info->func && say_signal_name)
6017 say_info->func(say_info->data, say_signal_name);
6018 eina_hash_del(read_command_id, &i, NULL);
6027 _event_handlers_register(Eo *bridge)
6029 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6031 _registered_events_list_update(bridge);
6033 // register signal handlers in order to update list of registered listeners of ATSPI-Clients
6034 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);
6035 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);
6036 //TIZEN_ONLY(20160527) - Add direct reading feature
6037 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);
6039 pd->key_flr = ecore_event_filter_add(NULL, _elm_atspi_bridge_key_filter, NULL, bridge);
6043 _bridge_object_unregister(Eo *bridge, Eo *obj)
6045 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6047 eina_hash_del(pd->cache, &obj, obj);
6051 _on_object_add(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6053 Eldbus_Message *sig;
6054 Eldbus_Message_Iter *iter;
6056 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6058 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_ADDED);
6059 iter = eldbus_message_iter_get(sig);
6060 _cache_item_reference_append_cb(data, obj, iter);
6062 eldbus_service_signal_send(pd->cache_interface, sig);
6068 _on_object_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
6070 Eldbus_Message *sig;
6072 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6074 _bridge_object_unregister(data, obj);
6076 sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_REMOVED);
6077 Eldbus_Message_Iter *iter = eldbus_message_iter_get(sig);
6078 _bridge_iter_object_reference_append(data, iter, obj);
6079 eldbus_service_signal_send(pd->cache_interface, sig);
6085 _bridge_cache_build(Eo *bridge, void *obj)
6087 Eina_List *children;
6088 Elm_Atspi_State_Set ss;
6091 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6093 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6096 if (!eo_isa(obj, ELM_ATSPI_PROXY_CLASS))
6097 _bridge_object_register(bridge, obj);
6099 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
6100 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
6102 if (eo_isa(obj, ELM_INTERFACE_ATSPI_WINDOW_INTERFACE))
6104 if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_ACTIVE))
6106 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6107 pd->window_activated = EINA_TRUE;
6112 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6113 pd->window_activated = EINA_FALSE;
6117 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
6118 EINA_LIST_FREE(children, child)
6119 _bridge_cache_build(bridge, child);
6123 _interfaces_unregister(Eo *bridge)
6125 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6127 #define INTERFACE_SAFE_FREE(ifc) \
6129 eldbus_service_interface_unregister(ifc); \
6132 INTERFACE_SAFE_FREE(pd->interfaces.accessible);
6133 INTERFACE_SAFE_FREE(pd->interfaces.application);
6134 INTERFACE_SAFE_FREE(pd->interfaces.action);
6135 INTERFACE_SAFE_FREE(pd->interfaces.component);
6136 INTERFACE_SAFE_FREE(pd->interfaces.collection);
6137 INTERFACE_SAFE_FREE(pd->interfaces.editable_text);
6138 INTERFACE_SAFE_FREE(pd->interfaces.image);
6139 INTERFACE_SAFE_FREE(pd->interfaces.selection);
6140 INTERFACE_SAFE_FREE(pd->interfaces.text);
6141 INTERFACE_SAFE_FREE(pd->interfaces.value);
6145 _a11y_connection_shutdown(Eo *bridge)
6147 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6148 Eldbus_Pending *pending;
6151 _elm_atspi_bridge_app_unregister(bridge);
6154 eina_hash_free(pd->cache);
6157 if (pd->cache_interface)
6158 eldbus_service_object_unregister(pd->cache_interface);
6159 pd->cache_interface = NULL;
6161 _interfaces_unregister(bridge);
6163 if (pd->key_flr) ecore_event_filter_del(pd->key_flr);
6166 if (pd->register_hdl) eldbus_signal_handler_del(pd->register_hdl);
6167 pd->register_hdl = NULL;
6169 if (pd->unregister_hdl) eldbus_signal_handler_del(pd->unregister_hdl);
6170 pd->unregister_hdl = NULL;
6172 //TIZEN_ONLY(20160527) - Add direct reading feature
6173 if (pd->reading_state_changed_hdl) eldbus_signal_handler_del(pd->reading_state_changed_hdl);
6174 pd->reading_state_changed_hdl = NULL;
6177 EINA_LIST_FREE(pd->pending_requests, pending)
6178 eldbus_pending_cancel(pending);
6179 pd->pending_requests = NULL;
6181 if (pd->a11y_bus) eldbus_connection_unref(pd->a11y_bus);
6182 pd->a11y_bus = NULL;
6184 if (pd->state_hash) eina_hash_free(pd->state_hash);
6185 pd->state_hash = NULL;
6187 if (pd->event_hash) eina_hash_free(pd->event_hash);
6188 pd->event_hash = NULL;
6190 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, elm_interface_atspi_accessible_event_handler_del(pd->event_hdlr));
6191 pd->event_hdlr = NULL;
6193 eo_do(bridge, eo_event_callback_call(ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, NULL));
6194 pd->connected = EINA_FALSE;
6197 static void _disconnect_cb(void *data, Eldbus_Connection *conn EINA_UNUSED, void *event_info EINA_UNUSED)
6199 _a11y_connection_shutdown(data);
6203 _interfaces_register(Eo *bridge)
6205 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6207 pd->interfaces.accessible =
6208 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &accessible_iface_desc);
6209 eldbus_service_object_data_set(pd->interfaces.accessible, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6211 pd->interfaces.application =
6212 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &application_iface_desc);
6213 eldbus_service_object_data_set(pd->interfaces.application, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6215 pd->interfaces.action =
6216 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &action_iface_desc);
6217 eldbus_service_object_data_set(pd->interfaces.action, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6219 pd->interfaces.component =
6220 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &component_iface_desc);
6221 eldbus_service_object_data_set(pd->interfaces.component, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6223 pd->interfaces.collection =
6224 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &collection_iface_desc);
6225 eldbus_service_object_data_set(pd->interfaces.collection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6227 pd->interfaces.editable_text =
6228 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &editable_text_iface_desc);
6229 eldbus_service_object_data_set(pd->interfaces.editable_text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6231 pd->interfaces.image =
6232 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &image_iface_desc);
6233 eldbus_service_object_data_set(pd->interfaces.image, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6235 pd->interfaces.selection =
6236 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &selection_iface_desc);
6237 eldbus_service_object_data_set(pd->interfaces.selection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6239 pd->interfaces.text =
6240 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &text_iface_desc);
6241 eldbus_service_object_data_set(pd->interfaces.text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6243 pd->interfaces.value =
6244 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &value_iface_desc);
6245 eldbus_service_object_data_set(pd->interfaces.value, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
6249 _bridge_accessible_event_dispatch(void *data, Eo *accessible, const Eo_Event_Description *desc, void *event_info)
6251 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(data, pd, EINA_TRUE);
6253 _bridge_object_register(data, accessible);
6255 Eo_Event_Cb cb = eina_hash_find(pd->event_hash, &desc);
6256 return cb ? cb(data, accessible, desc, event_info) : EINA_TRUE;
6260 _a11y_bus_initialize(Eo *obj, const char *socket_addr)
6262 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
6263 pd->a11y_bus = eldbus_private_address_connection_get(socket_addr);
6267 eldbus_connection_event_callback_add(pd->a11y_bus, ELDBUS_CONNECTION_EVENT_DISCONNECTED, _disconnect_cb, obj);
6269 // init data structures
6270 pd->cache = eina_hash_pointer_new(NULL);
6271 pd->state_hash = _elm_atspi_state_hash_build();
6272 pd->event_hash = _elm_atspi_event_hash_build();
6275 _cache_register(obj);
6276 _interfaces_register(obj);
6277 _event_handlers_register(obj);
6278 if (!getenv("ELM_ATSPI_NO_EMBED"))
6279 _elm_atspi_bridge_app_register(obj);
6281 // register accesible object event listener
6282 eo_do(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, pd->event_hdlr = elm_interface_atspi_accessible_event_handler_add(_bridge_accessible_event_dispatch, obj));
6287 _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6289 const char *errname, *errmsg, *sock_addr = NULL;
6290 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6292 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6294 if (eldbus_message_error_get(msg, &errname, &errmsg))
6296 ERR("%s %s", errname, errmsg);
6300 if (!eldbus_message_arguments_get(msg, "s", &sock_addr) || !sock_addr)
6302 ERR("Could not get A11Y Bus socket address.");
6306 _a11y_socket_address = eina_stringshare_add(sock_addr);
6307 _a11y_bus_initialize((Eo*)data, sock_addr);
6310 static void _a11y_connection_init(Eo *bridge)
6312 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6313 Eina_Bool is_connected;
6315 eo_do(bridge, is_connected = elm_obj_atspi_bridge_connected_get());
6317 if (is_connected) return;
6319 // TIZEN_ONLY(20170512): send window activated event to at_spi2 only once per session
6320 pd->window_activated_broadcast_needed = EINA_TRUE;
6322 Eldbus_Message *m = eldbus_object_method_call_new(pd->bus_obj, A11Y_DBUS_INTERFACE, "GetAddress");
6323 Eldbus_Pending *p = eldbus_object_send(pd->bus_obj, m, _a11y_bus_address_get, bridge, 100);
6326 pd->pending_requests = eina_list_append(pd->pending_requests, p);
6330 _screen_reader_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6332 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6333 const char *errname, *errmsg;
6334 Eina_Bool is_enabled;
6335 Eldbus_Message_Iter *variant;
6337 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6339 if (eldbus_message_error_get(msg, &errname, &errmsg))
6341 WRN("%s %s", errname, errmsg);
6344 if (!eldbus_message_arguments_get(msg, "v", &variant))
6346 ERR("'ScreenReaderEnabled' not packed into variant.");
6349 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6351 ERR("Could not get 'ScreenReaderEnabled' boolean property");
6354 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6355 pd->screen_reader_enabled = !!is_enabled;
6357 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6358 //register/unregister access objects accordingly.
6359 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6360 _elm_win_screen_reader(is_enabled);
6365 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6367 _at_spi_client_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
6369 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd);
6370 const char *errname, *errmsg;
6371 Eina_Bool is_enabled;
6372 Eldbus_Message_Iter *variant;
6374 pd->pending_requests = eina_list_remove(pd->pending_requests, pending);
6376 if (eldbus_message_error_get(msg, &errname, &errmsg))
6378 WRN("%s %s", errname, errmsg);
6381 if (!eldbus_message_arguments_get(msg, "v", &variant))
6383 ERR("'" A11Y_DBUS_ENABLED_PROPERTY "' not packed into variant.");
6386 if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled))
6388 ERR("Could not get '" A11Y_DBUS_ENABLED_PROPERTY "' boolean property");
6392 _a11y_connection_init(data);
6395 _elm_win_atspi(EINA_FALSE);
6396 DBG("AT-SPI2 stack not enabled.");
6402 static void _bridge_object_register(Eo *bridge, Eo *obj)
6404 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6406 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6408 WRN("Unable to register class w/o Elm_Interface_Atspi_Accessible!");
6412 if (eina_hash_find(pd->cache, &obj))
6415 eina_hash_add(pd->cache, &obj, obj);
6419 _elm_atspi_bridge_init(void)
6423 _instance = eo_add(ELM_ATSPI_BRIDGE_CLASS, NULL);
6429 _elm_atspi_bridge_get(void)
6435 _elm_atspi_bridge_shutdown(void)
6442 if (_a11y_socket_address)
6443 eina_stringshare_del(_a11y_socket_address);
6444 _a11y_socket_address = NULL;
6447 static Key_Event_Info*
6448 _key_event_info_new(int event_type, const Ecore_Event_Key *data, Eo *bridge)
6450 Key_Event_Info *ret;
6451 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
6453 ret = calloc(sizeof(Key_Event_Info), 1);
6455 ret->type = event_type;
6457 ret->bridge = bridge;
6459 ret->event.keyname = eina_stringshare_add(data->keyname);
6460 ret->event.key = eina_stringshare_add(data->key);
6461 ret->event.string = eina_stringshare_add(data->string);
6462 ret->event.compose = eina_stringshare_add(data->compose);
6464 // not sure why it is here, but explicite keep it NULLed.
6465 ret->event.data = NULL;
6471 _key_event_info_free(Key_Event_Info *data)
6473 EINA_SAFETY_ON_NULL_RETURN(data);
6475 eina_stringshare_del(data->event.keyname);
6476 eina_stringshare_del(data->event.key);
6477 eina_stringshare_del(data->event.string);
6478 eina_stringshare_del(data->event.compose);
6484 _iter_marshall_key_event(Eldbus_Message_Iter *iter, Key_Event_Info *data)
6486 Eldbus_Message_Iter *struct_iter;
6487 EINA_SAFETY_ON_NULL_RETURN(data);
6489 struct_iter = eldbus_message_iter_container_new(iter, 'r', NULL);
6491 const char *str = data->event.keyname ? data->event.keyname : "";
6492 int is_text = data->event.keyname ? 1 : 0;
6494 if (data->type == ECORE_EVENT_KEY_DOWN)
6495 type = ATSPI_KEY_PRESSED_EVENT;
6497 type = ATSPI_KEY_RELEASED_EVENT;
6499 eldbus_message_iter_arguments_append(struct_iter, "uiiiisb", type, 0, data->event.keycode, 0, data->event.timestamp, str, is_text);
6500 eldbus_message_iter_container_close(iter, struct_iter);
6504 _on_event_del(void *user_data, void *func_data EINA_UNUSED)
6506 Key_Event_Info *info = user_data;
6507 _key_event_info_free(info);
6511 _on_listener_answer(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6513 Key_Event_Info *info = data;
6514 const char *errname, *errmsg;
6515 Eina_Bool ret = EINA_TRUE;
6517 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(info->bridge, pd);
6519 if (eldbus_message_error_get(msg, &errname, &errmsg))
6521 ERR("%s %s", errname, errmsg);
6524 if (!eldbus_message_arguments_get(msg, "b", &ret))
6526 ERR("Return message doen not contian return value");
6531 _key_event_info_free(info);
6535 ecore_event_add(info->type, &info->event, _on_event_del, info);
6536 pd->reemited_events = eina_list_append(pd->reemited_events, &info->event);
6540 _elm_atspi_bridge_key_filter(void *data, void *loop EINA_UNUSED, int type, void *event)
6542 Eldbus_Message *msg;
6543 Eldbus_Message_Iter *iter;
6544 Ecore_Event_Key *key_event = event;
6548 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_TRUE);
6550 // TIZEN_ONLY(20160802): do not handle events if the window is not activated
6551 if (!pd->window_activated) return EINA_TRUE;
6554 if ((type != ECORE_EVENT_KEY_DOWN) && (type != ECORE_EVENT_KEY_UP)) return EINA_TRUE;
6556 // check if reemited
6557 if (eina_list_data_find(pd->reemited_events, event))
6559 pd->reemited_events = eina_list_remove(pd->reemited_events, event);
6563 // TIZEN_ONLY(20170118): Not handle events if keyboard is on
6566 Eina_List *children, *l;
6568 eo_do(pd->root, children = elm_interface_atspi_accessible_children_get());
6570 EINA_LIST_FOREACH(children, l, child)
6572 if (elm_widget_focus_get(child)) break;
6574 eina_list_free(children);
6576 Elm_Win_Keyboard_Mode mode;
6577 mode = elm_win_keyboard_mode_get(child);
6578 if (mode == ELM_WIN_KEYBOARD_ON) return EINA_TRUE;
6582 ke = _key_event_info_new(type, key_event, bridge);
6583 if (!ke) return EINA_TRUE;
6585 msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_DEC,
6586 ATSPI_DBUS_INTERFACE_DEC, "NotifyListenersSync");
6587 iter = eldbus_message_iter_get(msg);
6588 _iter_marshall_key_event(iter, ke);
6590 // timeout should be kept reasonaby low to avoid delays
6591 if (!eldbus_connection_send(pd->a11y_bus, msg, _on_listener_answer, ke, 100))
6598 _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6600 return pd->connected;
6604 _elm_atspi_bridge_root_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
6608 pd->root = eo_add(ELM_ATSPI_APP_OBJECT_CLASS, NULL);
6609 elm_interface_atspi_accessible_added(pd->root);
6616 _properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
6618 Eldbus_Proxy_Event_Property_Changed *ev = event;
6621 const char *ifc = eldbus_proxy_interface_get(ev->proxy);
6622 if (ev->name && !strcmp(ev->name, "ScreenReaderEnabled" ) &&
6623 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6625 if (!eina_value_get(ev->value, &val))
6627 ERR("Unable to get ScreenReaderEnabled property value");
6630 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
6631 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6632 pd->screen_reader_enabled = !!val;
6634 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
6635 //register/unregister access objects accordingly.
6636 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6637 _elm_win_screen_reader(val);
6641 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6642 if (ev->name && !strcmp(ev->name, A11Y_DBUS_ENABLED_PROPERTY) &&
6643 ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc))
6645 if (!eina_value_get(ev->value, &val))
6647 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6648 ERR("Unable to get " A11Y_DBUS_ENABLED_PROPERTY " property value");
6654 _a11y_connection_init(bridge);
6657 _elm_win_atspi(EINA_FALSE);
6658 _a11y_connection_shutdown(bridge);
6665 _elm_atspi_bridge_eo_base_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6667 Eldbus_Proxy *proxy;
6668 Eldbus_Pending *req;
6670 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_constructor());
6674 if (!(pd->session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION)))
6676 ERR("Unable to connect to Session Bus");
6679 if (!(pd->bus_obj = eldbus_object_get(pd->session_bus, A11Y_DBUS_NAME, A11Y_DBUS_PATH)))
6681 ERR("Could not get /org/a11y/bus object");
6684 if (!(proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE)))
6686 ERR("Could not get proxy object for %s interface", A11Y_DBUS_STATUS_INTERFACE);
6689 if (!(req = eldbus_proxy_property_get(proxy, "ScreenReaderEnabled", _screen_reader_enabled_get, obj)))
6691 ERR("Could not send PropertyGet request");
6694 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6696 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
6697 if (!(req = eldbus_proxy_property_get(proxy, A11Y_DBUS_ENABLED_PROPERTY, _at_spi_client_enabled_get, obj)))
6699 ERR("Could not send PropertyGet request");
6703 pd->pending_requests = eina_list_append(pd->pending_requests, req);
6706 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
6707 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
6708 _properties_changed_cb, obj);
6713 eldbus_object_unref(pd->bus_obj);
6716 eldbus_connection_unref(pd->session_bus);
6717 pd->session_bus = NULL;
6722 _elm_atspi_bridge_eo_base_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
6724 _a11y_connection_shutdown(obj);
6726 if (pd->bus_obj) eldbus_object_unref(pd->bus_obj);
6727 if (pd->session_bus) eldbus_connection_unref(pd->session_bus);
6728 if (pd->root) eo_del(pd->root);
6730 eo_do_super(obj, ELM_ATSPI_BRIDGE_CLASS, eo_destructor());
6734 elm_atspi_bridge_object_address_get(Eo *obj, char **bus, char **path)
6736 Eo *bridge = _elm_atspi_bridge_get();
6739 ERR("Connection with accessibility bus not established.");
6742 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
6743 if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6745 ERR("Connection with accessibility bus not established.");
6748 if (bus) *bus = strdup(eldbus_connection_unique_name_get(pd->a11y_bus));
6749 if (path) *path = strdup(_bridge_path_from_object(bridge, obj));
6755 _proxy_property_get(const Eldbus_Service_Interface *interface, const char *property,
6756 Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED,
6757 Eldbus_Message **error EINA_UNUSED)
6760 Eo *obj = eldbus_service_object_data_get(interface, "_atspi_obj");
6761 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6763 if (!strcmp(property, "Object"))
6766 eo_do(obj, parent = eo_parent_get());
6767 if (!elm_atspi_bridge_object_address_get(parent, &bus, &path))
6770 Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
6773 eldbus_message_iter_basic_append(iter_struct, 's', bus);
6774 eldbus_message_iter_basic_append(iter_struct, 'o', path);
6775 eldbus_message_iter_container_close(iter, iter_struct);
6784 static const Eldbus_Property proxy_properties[] = {
6785 { "Object", "(so)", _proxy_property_get, NULL, 0 },
6786 { NULL, NULL, NULL, NULL, 0 }
6789 static const Eldbus_Service_Interface_Desc _proxy_iface_desc = {
6790 ELM_ATSPI_DBUS_INTERFACE_PROXY, socket_methods, NULL, proxy_properties, NULL, NULL
6793 static void _embedded_reply_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6795 Eo *parent, *proxy = data;
6796 const char *err, *txt;
6798 if (eldbus_message_error_get(msg, &err, &txt))
6800 ERR("AT-SPI: Embedded method call failed: %s %s", err, txt);
6801 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6804 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_CONNECTED, NULL));
6806 eo_do(proxy, parent = eo_parent_get());
6808 elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, proxy);
6812 _plug_embedded_send(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
6814 char *obj_path = NULL;
6816 Eldbus_Message *msg = NULL;
6818 eo_do(proxy, parent = eo_parent_get());
6819 if (!parent) goto fail;
6821 msg = eldbus_message_method_call_new(bus, path, ATSPI_DBUS_INTERFACE_SOCKET, "Embedded");
6822 if (!msg) goto fail;
6824 if (!elm_atspi_bridge_object_address_get(parent, NULL, &obj_path))
6827 if (!eldbus_message_arguments_append(msg, "s", obj_path))
6830 if (!eldbus_connection_send(conn, msg, _embedded_reply_cb, proxy, 100))
6833 ELM_SAFE_FREE(obj_path, free);
6837 ERR("AT-SPI: Unable to send Embedded request.");
6838 if (msg) eldbus_message_unref(msg);
6839 ELM_SAFE_FREE(obj_path, free);
6840 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6843 static void _socket_addr_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
6846 const char *bus, *path, *err, *txt;
6847 Eldbus_Message_Iter *iter, *iter_variant, *iter_struct;
6849 Eo *bridge = _elm_atspi_bridge_get();
6852 ERR("AT-SPI: Atspi bridge is not enabled.");
6855 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6857 if (eldbus_message_error_get(msg, &err, &txt))
6859 ERR("Unable to connect to socket: %s %s", err, txt);
6863 iter = eldbus_message_iter_get(msg);
6864 if (!eldbus_message_iter_arguments_get(iter, "v", &iter_variant))
6866 ERR("Unable to get variant parameter");
6870 if (!eldbus_message_iter_arguments_get(iter_variant, "(so)", &iter_struct))
6872 ERR("Unable to get so parameters");
6876 if (!eldbus_message_iter_arguments_get(iter_struct, "so", &bus, &path))
6878 ERR("Unable to get so parameters");
6882 eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path));
6884 _plug_embedded_send(pd->a11y_bus, proxy, bus, path);
6889 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6893 eo_do(proxy, elm_obj_atspi_proxy_address_get_retry_timer_add());
6897 _plug_address_discover(Eldbus_Connection *conn, Eo *proxy, const char *svc_bus, const char *svc_path)
6899 Eldbus_Object *dobj;
6900 dobj = eldbus_object_get(conn, svc_bus, svc_path);
6903 ERR("Unable to get eldbus object from: %s %s", svc_bus, svc_path);
6907 Eldbus_Message *msg = eldbus_object_method_call_new(dobj, ELDBUS_FDO_INTERFACE_PROPERTIES, "Get");
6908 eldbus_message_arguments_append(msg, "ss", ELM_ATSPI_DBUS_INTERFACE_PROXY, "Object");
6909 eldbus_object_send(dobj, msg, _socket_addr_get_cb, proxy, 100);
6912 static void _plug_connect(Eldbus_Connection *conn, Eo *proxy)
6914 const char *bus, *path;
6916 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
6917 eo_do(proxy, path = eo_key_data_get("__svc_path"));
6921 _plug_address_discover(conn, proxy, bus, path);
6926 eo_do(proxy, elm_obj_atspi_proxy_address_get(&bus, &path));
6929 ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set. Unable to connect");
6930 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6933 _plug_embedded_send(conn, proxy, bus, path);
6938 static Eina_Bool _from_list_remove(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6940 Eina_List **list = data;
6941 *list = eina_list_remove(*list, obj);
6945 EAPI void elm_atspi_bridge_utils_proxy_connect(Eo *proxy)
6947 Eo *bridge = _elm_atspi_bridge_get();
6951 ERR("AT-SPI: Atspi bridge is not enabled.");
6952 eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL));
6955 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
6959 if (!eina_list_data_find(pd->plug_queue, proxy))
6961 pd->plug_queue = eina_list_append(pd->plug_queue, proxy);
6962 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->plug_queue));
6966 _plug_connect(pd->a11y_bus, proxy);
6970 * @brief Service name sanitizer according to specs:
6971 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
6972 * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
6974 char *_sanitize_service_name(const char *name)
6976 char ret[256] = "\0";
6978 if (!name) return NULL;
6980 const char *tmp = name;
6983 // name element should not begin with digit. Swallow non-charater prefix
6984 while ((*tmp != '\0') && !isalpha(*tmp)) tmp++;
6986 // append rest of character valid charactes [A-Z][a-z][0-9]_
6987 while ((*tmp != '\0') && (dst < &ret[sizeof(ret) - 1]))
6989 if (isalpha(*tmp) || isdigit(*tmp) || (*tmp == '_'))
6998 Eo* _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type)
7001 char bus[256], path[256], *name;
7004 name = _sanitize_service_name(svcname);
7005 if (!name) return NULL;
7007 res = snprintf(bus, sizeof(bus), "elm.atspi.proxy.socket.%s-%d", name, svcnum);
7008 if (res < 0 || (res >= (int)sizeof(bus)))
7014 res = snprintf(path, sizeof(path), "/elm/atspi/proxy/socket/%s/%d", name, svcnum);
7015 if (res < 0 || (res >= (int)sizeof(path)))
7023 ret = eo_add(ELM_ATSPI_PROXY_CLASS, parent, elm_obj_atspi_proxy_constructor(type));
7024 if (!ret) return NULL;
7026 eo_do(ret, eo_key_data_set("__svc_bus", eina_stringshare_add(bus)));
7027 eo_do(ret, eo_key_data_set("__svc_path", eina_stringshare_add(path)));
7033 _on_socket_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED)
7035 Eldbus_Service_Interface *ifc = data;
7037 Eldbus_Connection *conn = eldbus_service_connection_get(ifc);
7038 eo_do(obj, bus = eo_key_data_get("__svc_bus"));
7039 eldbus_name_release(conn, bus, NULL, NULL);
7040 eldbus_service_interface_unregister(ifc);
7045 _proxy_interface_register(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
7047 Eldbus_Service_Interface *proxy_infc;
7048 Eo *bridge = _elm_atspi_bridge_get();
7051 ERR("AT-SPI: Atspi bridge is not enabled.");
7054 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7056 eldbus_name_request(conn, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, NULL, NULL);
7057 proxy_infc = eldbus_service_interface_register(pd->a11y_bus, path, &_proxy_iface_desc);
7059 ERR("AT-SPI: Proxy interface registration failed");
7060 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _on_socket_del, proxy_infc));
7061 eldbus_service_object_data_set(proxy_infc, "_atspi_obj", proxy);
7064 static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy)
7066 const char *bus, *path;
7067 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7068 Eo *bridge = _elm_atspi_bridge_get();
7069 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7072 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7073 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7076 _proxy_interface_register(conn, proxy, bus, path);
7078 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7079 pd->interfaces.socket =
7080 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &socket_iface_desc);
7084 EAPI void elm_atspi_bridge_utils_proxy_listen(Eo *proxy)
7086 Eo *bridge = _elm_atspi_bridge_get();
7089 ERR("AT-SPI: Atspi bridge is not enabled.");
7092 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7095 if (!eina_list_data_find(pd->socket_queue, proxy))
7097 pd->socket_queue = eina_list_append(pd->socket_queue, proxy);
7098 eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &pd->socket_queue));
7102 _socket_ifc_create(pd->a11y_bus, proxy);
7105 //TIZEN_ONLY(20160527) - Add direct reading feature
7107 _on_read_command_call(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7109 const char *errname, *errmsg;
7113 Elm_Atspi_Say_Info *say_info = data;
7115 if (eldbus_message_error_get(msg, &errname, &errmsg))
7117 ERR("%s %s", errname, errmsg);
7123 // get read command id and map it to obj
7124 if (eldbus_message_arguments_get(msg, "sbi", &s, &b, &i))
7126 if (!read_command_id)
7127 read_command_id = eina_hash_int32_new(NULL);
7129 if (!read_command_id) {
7130 ERR("eina_hash_int32_new() failed to create new map to store callbacks for direct reading commands");
7134 eina_hash_add(read_command_id, &i, say_info);
7140 elm_atspi_bridge_utils_say(const char* text,
7141 Eina_Bool discardable,
7142 const Elm_Atspi_Say_Signal_Cb func,
7145 Eldbus_Message *msg;
7146 Eldbus_Message_Iter *iter;
7147 Elm_Atspi_Say_Info *say_info = NULL;
7148 Eo *bridge = _elm_atspi_bridge_get();
7151 ERR("AT-SPI: Atspi bridge is not enabled.");
7154 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7157 ERR("AT-SPI: a11y bus is not set.");
7161 msg = eldbus_message_method_call_new(ELM_ATSPI_DIRECT_READ_BUS,
7162 ELM_ATSPI_DIRECT_READ_PATH,
7163 ELM_ATSPI_DIRECT_READ_INTERFACE,
7165 iter = eldbus_message_iter_get(msg);
7166 eldbus_message_iter_arguments_append(iter, "sb", text, discardable);
7168 say_info = calloc(1, sizeof(Elm_Atspi_Say_Info));
7170 say_info->func = func;
7171 say_info->data = (void *)data;
7174 eldbus_connection_send(pd->a11y_bus, msg, _on_read_command_call, say_info, -1);
7178 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7180 _offset_set_reply_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
7182 const char *err, *txt;
7184 if (eldbus_message_error_get(msg, &err, &txt))
7186 ERR("AT-SPI: SetOffset method call failed: %s %s", err, txt);
7191 void elm_atspi_bridge_utils_proxy_offset_set(Eo *proxy, int x, int y)
7193 const char *bus, *path;
7194 Eo *bridge = _elm_atspi_bridge_get();
7195 if (!bridge) return;
7197 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
7199 if (!pd->a11y_bus) return;
7201 eo_do(proxy, bus = eo_key_data_get("__svc_bus"));
7202 eo_do(proxy, path = eo_key_data_get("__svc_path"));
7204 Eldbus_Message *msg = NULL;
7206 msg = eldbus_message_method_call_new(bus, path, ELM_ATSPI_DBUS_INTERFACE_PROXY, "SetOffset");
7207 if (!msg) goto fail;
7209 if (!eldbus_message_arguments_append(msg, "i", x))
7212 if (!eldbus_message_arguments_append(msg, "i", y))
7215 if (!eldbus_connection_send(pd->a11y_bus, msg, _offset_set_reply_cb, NULL, 100))
7221 ERR("AT-SPI: Unable to send SetOffset request.");
7222 if (msg) eldbus_message_unref(msg);
7225 //TIZEN_ONLY(20161027) - Export elm_atspi_bridge_utils_is_screen_reader_enabled
7226 EAPI Eina_Bool elm_atspi_bridge_utils_is_screen_reader_enabled(void)
7228 Eo *bridge = _elm_atspi_bridge_get();
7231 ERR("AT-SPI: Atspi bridge is not enabled.");
7234 ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
7235 return pd->screen_reader_enabled;
7238 #include "elm_atspi_bridge.eo.c"