atspi: event broadcast added. Orca screen reader now ables to read UI.
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Fri, 7 Feb 2014 14:03:07 +0000 (23:03 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Fri, 7 Feb 2014 14:03:07 +0000 (23:03 +0900)
Summary:
added broadcast of focus, window activate/deactivate events on a11y bus
Orca screen reader is now able to read elementary application.

Reviewers: raster, seoz, z.kosinski, kimcinoo

Reviewed By: raster

Differential Revision: https://phab.enlightenment.org/D508

src/lib/elm_atspi_bridge.c
src/lib/elm_atspi_object.c
src/lib/elm_atspi_object_common.h
src/lib/elm_atspi_object_eo.h
src/lib/elm_atspi_object_legacy.h
src/lib/elm_widget.c

index 5963e6a..cbede6c 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdint.h>
 #include <Elementary.h>
 #include "elm_priv.h"
+#include <assert.h>
 
 #include "atspi/atspi-constants.h"
 
@@ -14,6 +15,7 @@
 #define A11Y_DBUS_NAME "org.a11y.Bus"
 #define A11Y_DBUS_PATH "/org/a11y/bus"
 #define A11Y_DBUS_INTERFACE "org.a11y.Bus"
+#define ATSPI_DBUS_INTERFACE_EVENT_WINDOW "org.a11y.atspi.Event.Window"
 
 #define CACHE_ITEM_SIGNATURE "((so)(so)(so)a(so)assusau)"
 #define CACHE_INTERFACE_PATH "/org/a11y/atspi/cache"
 #define ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE ELM_ACCESS_OBJECT_PATH_PREFIX "%llu"
 
 static int _init_count = 0;
+
 static Eldbus_Connection *_a11y_bus = NULL;
 static Elm_Atspi_Object *_root;
 static Eina_Hash *_cache;
 static Eldbus_Service_Interface *_cache_interface = NULL;
+static Eldbus_Signal_Handler *_register_hdl;
+static Eldbus_Signal_Handler *_unregister_hdl;
+static unsigned short _object_property_broadcast_mask;
+static unsigned short _object_children_broadcast_mask;
+static unsigned long long _object_state_broadcast_mask;
+static unsigned long long _window_signal_broadcast_mask;
+
+static void _cache_update(void);
 static Elm_Atspi_Object * _access_object_from_path(const char *path);
 static char * _path_from_access_object(Elm_Atspi_Object *eo);
 static void object_append_reference(Eldbus_Message_Iter *iter,  Elm_Atspi_Object *obj);
 static void object_append_desktop_reference(Eldbus_Message_Iter *iter);
 static const Eldbus_Service_Interface_Desc accessible_iface_desc;
+static void _cache_object_register(Elm_Atspi_Object *node, Eina_Bool rec);
+
+
+enum _Atspi_Object_Child_Event_Type
+{
+   ATSPI_OBJECT_CHILD_ADDED = 0,
+   ATSPI_OBJECT_CHILD_REMOVED
+};
+
+enum _Atspi_Object_Property
+{
+   ATSPI_OBJECT_PROPERTY_NAME = 0,
+   ATSPI_OBJECT_PROPERTY_DESCRIPTION,
+   ATSPI_OBJECT_PROPERTY_VALUE,
+   ATSPI_OBJECT_PROPERTY_ROLE,
+   ATSPI_OBJECT_PROPERTY_PARENT,
+};
+
+enum _Atspi_Object_Signals {
+   ATSPI_OBJECT_EVENT_PROPERTY_CHANGED,
+   ATSPI_OBJECT_EVENT_BOUNDS_CHANGED,
+   ATSPI_OBJECT_EVENT_LINK_SELECTED,
+   ATSPI_OBJECT_EVENT_STATE_CHANGED,
+   ATSPI_OBJECT_EVENT_CHILDREN_CHANGED,
+   ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED,
+   ATSPI_OBJECT_EVENT_SELECTION_CHANGED,
+   ATSPI_OBJECT_EVENT_MODEL_CHANGED,
+   ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED,
+   ATSPI_OBJECT_EVENT_ROW_INSERTED,
+   ATSPI_OBJECT_EVENT_ROW_REORDERED,
+   ATSPI_OBJECT_EVENT_ROW_DELETED,
+   ATSPI_OBJECT_EVENT_COLUMN_INSERTED,
+   ATSPI_OBJECT_EVENT_COLUMN_REORDERED,
+   ATSPI_OBJECT_EVENT_COLUMN_DELETED,
+   ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED,
+   ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED,
+   ATSPI_OBJECT_EVENT_TEXT_CHANGED,
+   ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED,
+   ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED,
+   ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED,
+};
 
-enum
+enum _Atspi_Window_Signals
 {
-  ADD_ACCESSIBLE = 0,
-  REMOVE_ACCESSIBLE
+   ATSPI_WINDOW_EVENT_PROPERTY_CHANGE,
+   ATSPI_WINDOW_EVENT_MINIMIZE,
+   ATSPI_WINDOW_EVENT_MAXIMIZE,
+   ATSPI_WINDOW_EVENT_RESTORE,
+   ATSPI_WINDOW_EVENT_CLOSE,
+   ATSPI_WINDOW_EVENT_CREATE,
+   ATSPI_WINDOW_EVENT_REPARENT,
+   ATSPI_WINDOW_EVENT_DESKTOPCREATE,
+   ATSPI_WINDOW_EVENT_DESKTOPDESTROY,
+   ATSPI_WINDOW_EVENT_DESTROY,
+   ATSPI_WINDOW_EVENT_ACTIVATE,
+   ATSPI_WINDOW_EVENT_DEACTIVATE,
+   ATSPI_WINDOW_EVENT_RAISE,
+   ATSPI_WINDOW_EVENT_LOWER,
+   ATSPI_WINDOW_EVENT_MOVE,
+   ATSPI_WINDOW_EVENT_RESIZE,
+   ATSPI_WINDOW_EVENT_SHADE,
+   ATSPI_WINDOW_EVENT_UUSHADE,
+   ATSPI_WINDOW_EVENT_RESTYLE,
+};
+
+static const Eldbus_Signal _event_obj_signals[] = {
+   [ATSPI_OBJECT_EVENT_PROPERTY_CHANGED] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_BOUNDS_CHANGED] = {"BoundsChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_LINK_SELECTED] = {"LinkSelected", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_STATE_CHANGED] = {"StateChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_CHILDREN_CHANGED] = {"ChildrenChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_VISIBLE_DATA_CHANGED] = {"VisibleDataChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_SELECTION_CHANGED] = {"SelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_MODEL_CHANGED] = {"ModelChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_ACTIVE_DESCENDANT_CHANGED] = {"ActiveDescendantsChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_ROW_INSERTED] = {"RowInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_ROW_REORDERED] = {"RowReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_ROW_DELETED] = {"RowDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_COLUMN_INSERTED] = {"ColumnInserted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_COLUMN_REORDERED] = {"ColumnReordered", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_COLUMN_DELETED] = {"ColumnDeleted", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_TEXT_BOUNDS_CHANGED] = {"TextBoundsChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_TEXT_SELECTION_CHANGED] = {"SelectionChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_TEXT_CHANGED] = {"TextChaged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_TEXT_ATTRIBUTES_CHANGED] = {"TextAttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_TEXT_CARET_MOVED] = {"TextCaretMoved", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_OBJECT_EVENT_ATTRIBUTES_CHANGED] = {"AttributesChanged", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+};
+
+static const Eldbus_Signal _window_obj_signals[] = {
+   [ATSPI_WINDOW_EVENT_PROPERTY_CHANGE] = {"PropertyChange", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_MINIMIZE] = {"Minimize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_MAXIMIZE] = {"Maximize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_RESTORE] = {"Restore", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_CLOSE] = {"Close", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_CREATE] = {"Create", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_REPARENT] = {"Reparent", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_DESKTOPCREATE] = {"DesktopCreate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_DESKTOPDESTROY] = {"DesktopDestroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_DESTROY] = {"Destroy", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_ACTIVATE] = {"Activate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_DEACTIVATE] = {"Deactivate", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_RAISE] = {"Raise", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_LOWER] = {"Lower", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_MOVE] = {"Move", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_RESIZE] = {"Resize", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_SHADE] = {"Shade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_UUSHADE] = {"uUshade", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
+   [ATSPI_WINDOW_EVENT_RESTYLE] = {"Restyle", ELDBUS_ARGS({"siiv(so)", NULL}), 0},
 };
 
 static Eldbus_Message *
-_accessible_get_role(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+_accessible_get_role(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
 {
    const char *obj_path = eldbus_service_object_path_get(iface);
    Elm_Atspi_Object *obj = _access_object_from_path(obj_path);
@@ -48,64 +163,77 @@ _accessible_get_role(const Eldbus_Service_Interface *iface EINA_UNUSED, const El
 
    eo_do(obj, elm_atspi_obj_role_get(&role));
    Eldbus_Message *ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
    eldbus_message_arguments_append(ret, "u", role);
    return ret;
 }
 
 static Eldbus_Message *
-_accessible_get_role_name(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+_accessible_get_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
 {
    const char *role_name, *obj_path = eldbus_service_object_path_get(iface);
    Elm_Atspi_Object *obj = _access_object_from_path(obj_path);
 
    eo_do(obj, elm_atspi_obj_role_name_get(&role_name));
    Eldbus_Message *ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
    eldbus_message_arguments_append(ret, "s", role_name);
 
    return ret;
 }
 
 static Eldbus_Message *
-_accessible_get_localized_role_name(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+_accessible_get_localized_role_name(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
 {
    const char *l_role_name, *obj_path = eldbus_service_object_path_get(iface);
    Elm_Atspi_Object *obj = _access_object_from_path(obj_path);
 
    eo_do(obj, elm_atspi_obj_localized_role_name_get(&l_role_name));
    Eldbus_Message *ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
    eldbus_message_arguments_append(ret, "s", l_role_name);
 
    return ret;
 }
 
 static Eldbus_Message *
-_accessible_get_children(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+_accessible_get_children(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
 {
    const char *obj_path = eldbus_service_object_path_get(iface);
    Elm_Atspi_Object *obj = _access_object_from_path(obj_path);
    Eina_List *children_list = NULL, *l;
    Eldbus_Message *ret;
+
    Eldbus_Message_Iter *iter, *iter_array;
    Elm_Atspi_Object *children;
 
    eo_do(obj, elm_atspi_obj_children_get(&children_list));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    iter = eldbus_message_iter_get(ret);
    iter_array = eldbus_message_iter_container_new(iter, 'a', "(so)");
+   EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
 
    EINA_LIST_FOREACH(children_list, l, children)
       object_append_reference(iter_array, children);
 
    eldbus_message_iter_container_close(iter, iter_array);
    eina_list_free(children_list);
+
    return ret;
+
+fail:
+   if (ret) eldbus_message_unref(ret);
+   return NULL;
 }
 
 static Eldbus_Message *
 _accessible_get_application(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
 {
    Eldbus_Message *ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
    Eldbus_Message_Iter *iter = eldbus_message_iter_get(ret);
    object_append_reference(iter, _root);
 
@@ -113,17 +241,42 @@ _accessible_get_application(const Eldbus_Service_Interface *iface EINA_UNUSED, c
 }
 
 static Eldbus_Message *
-_accessible_get_state(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+_accessible_get_state(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
 {
-   Eldbus_Message *ret = eldbus_message_method_return_new(msg);
-   Eldbus_Message_Iter *iter = eldbus_message_iter_get(ret);
-   Eldbus_Message_Iter *iter_array;
+   Eldbus_Message *ret;
+   Eldbus_Message_Iter *iter, *iter_array;
+   Elm_Atspi_State states;
+
+   const char *obj_path = eldbus_service_object_path_get(iface);
+   Elm_Atspi_Object *obj = _access_object_from_path(obj_path);
+
+   if (!obj)
+     {
+        ERR("Atspi Object %s not found in cache!", obj_path);
+        return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid object path.");
+     }
 
+   ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
+   iter = eldbus_message_iter_get(ret);
    iter_array = eldbus_message_iter_container_new(iter, 'a', "u");
-   /* TODO: states are not implemented yet*/
+   EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
+
+   eo_do(obj, elm_atspi_obj_state_get(&states));
+
+   unsigned int s1 = states & 0xFFFFFFFF;
+   unsigned int s2 = (states >> 32) & 0xFFFFFFFF;
+
+   eldbus_message_iter_basic_append(iter_array, 'u', s1);
+   eldbus_message_iter_basic_append(iter_array, 'u', s2);
    eldbus_message_iter_container_close(iter, iter_array);
 
    return ret;
+
+fail:
+   if (ret) eldbus_message_unref(ret);
+   return NULL;
 }
 
 static Eldbus_Message *
@@ -131,9 +284,12 @@ _accessible_get_index_in_parent(const Eldbus_Service_Interface *iface EINA_UNUSE
 {
    const char *obj_path = eldbus_service_object_path_get(iface);
    Elm_Atspi_Object *obj = _access_object_from_path(obj_path);
-   Eldbus_Message *ret = eldbus_message_method_return_new(msg);
+   Eldbus_Message *ret;
    int idx;
 
+   ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eo_do(obj, elm_atspi_obj_index_in_parent_get(&idx));
    eldbus_message_arguments_append(ret, "i", idx);
 
@@ -154,6 +310,8 @@ _accessible_child_at_index(const Eldbus_Service_Interface *iface EINA_UNUSED, co
      return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    iter = eldbus_message_iter_get(ret);
    eo_do(obj, elm_atspi_obj_child_at_index_get(idx, &child));
    object_append_reference(iter, child);
@@ -161,11 +319,17 @@ _accessible_child_at_index(const Eldbus_Service_Interface *iface EINA_UNUSED, co
    return ret;
 }
 
+static Eldbus_Message *
+_accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+   return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.NotSupported", "Relation states not implemented.");
+}
+
 static const Eldbus_Method accessible_methods[] = {
    { "GetChildAtIndex", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"(so)", "Accessible"}), _accessible_child_at_index, 0 },
    { "GetChildren", NULL, ELDBUS_ARGS({"a(so)", "children"}), _accessible_get_children, 0 },
    { "GetIndexInParent", NULL, ELDBUS_ARGS({"i", "index"}), _accessible_get_index_in_parent, 0 },
-   { "GetRelationSet", NULL, ELDBUS_ARGS({"a(ua(so))", NULL}), _accessible_get_state, 0 },
+   { "GetRelationSet", NULL, ELDBUS_ARGS({"a(ua(so))", NULL}), _accessible_get_relation_set, 0 },
    { "GetRole", NULL, ELDBUS_ARGS({"u", "Role"}), _accessible_get_role, 0 },
    { "GetRoleName", NULL, ELDBUS_ARGS({"s", "Name"}), _accessible_get_role_name, 0 },
    { "GetLocalizedRoleName", NULL, ELDBUS_ARGS({"s", "LocalizedName"}), _accessible_get_localized_role_name, 0},
@@ -216,9 +380,7 @@ _accessible_property_get(const Eldbus_Service_Interface *interface, const char *
                          Eldbus_Message **error EINA_UNUSED)
 {
    const char *ret, *obj_path = eldbus_service_object_path_get(interface);
-
    Elm_Atspi_Object *ret_obj = NULL, *obj = _access_object_from_path(obj_path);
-
    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
 
    if (!strcmp(property, "Name"))
@@ -260,10 +422,10 @@ _accessible_property_get(const Eldbus_Service_Interface *interface, const char *
 }
 
 static const Eldbus_Property accessible_properties[] = {
-   { "Name", "s", NULL, NULL, 0 },
-   { "Description", "s", NULL, NULL, 0 },
-   { "Parent", "(so)", NULL, NULL, 0 },
-   { "ChildCount", "i", NULL, NULL, 0 },
+   { "Name", "s", _accessible_property_get, NULL, 0 },
+   { "Description", "s", _accessible_property_get, NULL, 0 },
+   { "Parent", "(so)", _accessible_property_get, NULL, 0 },
+   { "ChildCount", "i", _accessible_property_get, NULL, 0 },
    { NULL, NULL, NULL, NULL, 0 }
 };
 
@@ -271,10 +433,19 @@ static const Eldbus_Service_Interface_Desc accessible_iface_desc = {
    ATSPI_DBUS_INTERFACE_ACCESSIBLE, accessible_methods, NULL, accessible_properties, _accessible_property_get, NULL
 };
 
-static void
-object_append_reference(Eldbus_Message_Iter *iter, Elm_Atspi_Object *obj){
+static const Eldbus_Service_Interface_Desc event_iface_desc = {
+   ATSPI_DBUS_INTERFACE_EVENT_OBJECT, NULL, _event_obj_signals, NULL, NULL, NULL
+};
+
+static const Eldbus_Service_Interface_Desc window_iface_desc = {
+   ATSPI_DBUS_INTERFACE_EVENT_WINDOW, NULL, _window_obj_signals, NULL, NULL, NULL
+};
 
+static void
+object_append_reference(Eldbus_Message_Iter *iter, Elm_Atspi_Object *obj)
+{
   Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
+  EINA_SAFETY_ON_NULL_RETURN(iter);
   char *path = _path_from_access_object(obj);
   eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(_a11y_bus));
   eldbus_message_iter_basic_append(iter_struct, 'o', path);
@@ -283,9 +454,10 @@ object_append_reference(Eldbus_Message_Iter *iter, Elm_Atspi_Object *obj){
 }
 
 static void
-object_append_desktop_reference(Eldbus_Message_Iter *iter){
-
+object_append_desktop_reference(Eldbus_Message_Iter *iter)
+{
   Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
+  EINA_SAFETY_ON_NULL_RETURN(iter);
 
   eldbus_message_iter_basic_append(iter_struct, 's', ATSPI_DBUS_NAME_REGISTRY);
   eldbus_message_iter_basic_append(iter_struct, 'o', ATSPI_DBUS_PATH_ROOT);
@@ -295,17 +467,19 @@ object_append_desktop_reference(Eldbus_Message_Iter *iter){
 static Eina_Bool
 _append_item_fn(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
 {
-
   if (!eo_ref_get(data) || eo_destructed_is(data))
     return EINA_TRUE;
 
   Eldbus_Message_Iter *iter_struct, *iter_sub_array;
   Eldbus_Message_Iter *iter_array = fdata;
-
+  Elm_Atspi_State states;
   AtspiRole role;
+
   eo_do(data, elm_atspi_obj_role_get(&role));
 
   iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(iter_struct, EINA_TRUE);
+
   /* Marshall object path */
   object_append_reference(iter_struct, data);
 
@@ -326,6 +500,8 @@ _append_item_fn(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
 
   eo_do(data, elm_atspi_obj_children_get(&children_list));
   iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "(so)");
+  EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
+
   EINA_LIST_FOREACH(children_list, l, child)
      object_append_reference(iter_sub_array, child);
 
@@ -334,6 +510,7 @@ _append_item_fn(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
 
   /* Marshall interfaces */
   iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "s");
+  EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
 
   eldbus_message_iter_basic_append(iter_sub_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE);
   if (eo_isa(data, ELM_ATSPI_COMPONENT_INTERFACE))
@@ -360,24 +537,44 @@ _append_item_fn(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
 
   /* Marshall state set */
   iter_sub_array = eldbus_message_iter_container_new(iter_struct, 'a', "u");
-  /* TODO: states are not implemented yet*/
-  eldbus_message_iter_container_close(iter_struct, iter_sub_array);
+  EINA_SAFETY_ON_NULL_GOTO(iter_sub_array, fail);
 
+  eo_do(data, elm_atspi_obj_state_get(&states));
+  unsigned int s1 = states & 0xFFFFFFFF;
+  unsigned int s2 = (states >> 32) & 0xFFFFFFFF;
+  eldbus_message_iter_basic_append(iter_sub_array, 'u', s1);
+  eldbus_message_iter_basic_append(iter_sub_array, 'u', s2);
+
+  eldbus_message_iter_container_close(iter_struct, iter_sub_array);
   eldbus_message_iter_container_close(iter_array, iter_struct);
 
   return EINA_TRUE;
+
+fail:
+  if (iter_struct) eldbus_message_iter_del(iter_struct);
+  return EINA_TRUE;
 }
 
 static Eldbus_Message *
 _cache_get_items(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
 {
-   Eldbus_Message *ret = eldbus_message_method_return_new(msg);
    Eldbus_Message_Iter *iter, *iter_array;
+   Eldbus_Message *ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
+   _cache_update();
+
    iter = eldbus_message_iter_get(ret);
    iter_array = eldbus_message_iter_container_new(iter, 'a', CACHE_ITEM_SIGNATURE);
+   EINA_SAFETY_ON_NULL_GOTO(iter_array, fail);
+
    eina_hash_foreach(_cache, _append_item_fn, iter_array);
    eldbus_message_iter_container_close(iter, iter_array);
+
    return ret;
+fail:
+   if (ret) eldbus_message_unref(ret);
+   return NULL;
 }
 
 static const Eldbus_Method cache_methods[] = {
@@ -386,8 +583,8 @@ static const Eldbus_Method cache_methods[] = {
 };
 
 static const Eldbus_Signal cache_signals[] = {
-  [ADD_ACCESSIBLE] = { "AddAccessible", ELDBUS_ARGS({"((so)(so)a(so)assusau)", "added"}), 0},
-  [REMOVE_ACCESSIBLE] = { "RemoveAccessible", ELDBUS_ARGS({ "(so)", "removed" }), 0},
+  [ATSPI_OBJECT_CHILD_ADDED] = { "AddAccessible", ELDBUS_ARGS({"((so)(so)a(so)assusau)", "added"}), 0},
+  [ATSPI_OBJECT_CHILD_REMOVED] = { "RemoveAccessible", ELDBUS_ARGS({ "(so)", "removed" }), 0},
   {NULL, NULL, 0}
 };
 
@@ -412,6 +609,8 @@ _component_contains(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eld
    eo_do(obj, elm_atspi_component_interface_contains(x, y, coord_type, &contains));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "b", contains);
 
    return ret;
@@ -432,6 +631,8 @@ _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UN
      return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    iter = eldbus_message_iter_get(ret);
    eo_do(obj, elm_atspi_component_interface_accessible_at_point_get(x, y, coord_type, &accessible));
    object_append_reference(iter, accessible);
@@ -447,23 +648,30 @@ _component_get_extents(const Eldbus_Service_Interface *iface EINA_UNUSED, const
    int x, y, w, h;
    AtspiCoordType coord_type;
    Eldbus_Message *ret;
-   Eldbus_Message_Iter *iter, *iter_struct;
-
+   Eldbus_Message_Iter *iter, *iter_struct; 
    if (!eldbus_message_arguments_get(msg, "u", &coord_type))
      return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    iter = eldbus_message_iter_get(ret);
 
    eo_do(obj, elm_atspi_component_interface_extents_get(&x, &y, &w, &h, coord_type));
    iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
+   EINA_SAFETY_ON_NULL_GOTO(iter_struct, fail);
+
    eldbus_message_iter_basic_append(iter_struct, 'i', x);
    eldbus_message_iter_basic_append(iter_struct, 'i', y);
    eldbus_message_iter_basic_append(iter_struct, 'i', w);
    eldbus_message_iter_basic_append(iter_struct, 'i', h);
+
    eldbus_message_iter_container_close(iter, iter_struct);
 
    return ret;
+fail:
+   if (iter_struct) eldbus_message_iter_del(iter_struct);
+   return NULL;
 }
 
 static Eldbus_Message *
@@ -481,6 +689,8 @@ _component_get_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const
    eo_do(obj, elm_atspi_component_interface_position_get(&x, &y, coord_type));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "i", x);
    eldbus_message_arguments_append(ret, "i", y);
 
@@ -498,6 +708,8 @@ _component_get_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eld
    eo_do(obj, elm_atspi_component_interface_size_get(&x, &y));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "i", x);
    eldbus_message_arguments_append(ret, "i", y);
 
@@ -515,6 +727,8 @@ _component_get_layer(const Eldbus_Service_Interface *iface EINA_UNUSED, const El
    eo_do(obj, elm_atspi_component_interface_layer_get(&layer));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "u", layer);
 
    return ret;
@@ -531,6 +745,8 @@ _component_grab_focus(const Eldbus_Service_Interface *iface EINA_UNUSED, const E
    eo_do(obj, elm_atspi_component_interface_focus_grab(&focus));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "b", focus);
 
    return ret;
@@ -547,6 +763,8 @@ _component_get_alpha(const Eldbus_Service_Interface *iface EINA_UNUSED, const El
    eo_do(obj, elm_atspi_component_interface_alpha_get(&alpha));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "d", alpha);
 
    return ret;
@@ -568,6 +786,8 @@ _component_set_extends(const Eldbus_Service_Interface *iface EINA_UNUSED, const
    eo_do(obj, elm_atspi_component_interface_extents_set(x, y, w, h, coord_type, &result));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "b", result);
 
    return ret;
@@ -589,6 +809,8 @@ _component_set_position(const Eldbus_Service_Interface *iface EINA_UNUSED, const
    eo_do(obj, elm_atspi_component_interface_position_set(x, y, coord_type, &result));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "b", result);
 
    return ret;
@@ -609,6 +831,8 @@ _component_set_size(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eld
    eo_do(obj, elm_atspi_component_interface_size_set(w, h, &result));
 
    ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
    eldbus_message_arguments_append(ret, "b", result);
 
    return ret;
@@ -635,19 +859,17 @@ static const Eldbus_Service_Interface_Desc component_iface_desc = {
 };
 
 static Eina_Bool
-_atspi_object_del_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+_cache_object_del_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Eldbus_Message *msg;
    Eldbus_Message_Iter *iter;
    char* path;
 
-   msg = eldbus_service_signal_new(_cache_interface, REMOVE_ACCESSIBLE);
+   msg = eldbus_service_signal_new(_cache_interface, ATSPI_OBJECT_CHILD_REMOVED);
    iter = eldbus_message_iter_get(msg);
    object_append_reference(iter, obj);
    path = _path_from_access_object(obj);
 
-   //ERR("_atspi_object_del_cbi: %d", eo_ref_get(obj));
-
    eldbus_service_signal_send(_cache_interface, msg);
    eina_hash_del(_cache, path, obj);
 
@@ -658,37 +880,50 @@ _atspi_object_del_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_
 }
 
 static void
-_atspi_object_register_interfaces(const char* path, Elm_Atspi_Object *node)
+_cache_object_register_interfaces(const char *path, Elm_Atspi_Object *node)
 {
    Eldbus_Service_Interface *accessible = NULL;
+   Eldbus_Service_Interface *events = NULL;
+   Eldbus_Service_Interface *window = NULL;
 
-   if (eo_isa(node, ELM_ATSPI_CLASS))
-     {
-        accessible = eldbus_service_interface_register(_a11y_bus, path, &accessible_iface_desc);
-        eo_do(node, eo_event_callback_add(EO_EV_DEL, _atspi_object_del_cb, accessible));
-     }
+   if (eina_hash_find(_cache, path))
+     return;
+   else
+     eina_hash_add(_cache, path, node);
+
+   if (!eo_isa(node, ELM_ATSPI_CLASS)) return;
+
+   accessible = eldbus_service_interface_register(_a11y_bus, path, &accessible_iface_desc);
+   events = eldbus_service_interface_register(_a11y_bus, path, &event_iface_desc);
+   eo_do(node, eo_base_data_set("atspi_event_interface", events, NULL));
+   eo_do(node, eo_event_callback_add(EO_EV_DEL, _cache_object_del_cb, accessible));
 
    if (eo_isa(node, ELM_ATSPI_COMPONENT_INTERFACE))
      eldbus_service_interface_register(_a11y_bus, path, &component_iface_desc);
+
+   if (eo_isa(node, ELM_ATSPI_WINDOW_INTERFACE))
+     {
+        window = eldbus_service_interface_register(_a11y_bus, path, &window_iface_desc);
+        eo_do(node, eo_base_data_set("window_event_interface", window, NULL));
+     }
 }
 
 static void
-_atspi_objects_register_rec(Elm_Atspi_Object *node)
+_cache_object_register(Elm_Atspi_Object *node, Eina_Bool rec)
 {
    EINA_SAFETY_ON_NULL_RETURN(node);
    Eina_List *children_list = NULL, *l;
    Elm_Atspi_Object *child;
    char* path = _path_from_access_object(node);
 
-   // register in cache
-   eina_hash_add(_cache, path, node);
-
-   _atspi_object_register_interfaces(path, node);
+   _cache_object_register_interfaces(path, node);
    free(path);
 
+   if (!rec) return;
+
    eo_do(node, elm_atspi_obj_children_get(&children_list));
    EINA_LIST_FOREACH(children_list, l, child)
-      _atspi_objects_register_rec(child);
+      _cache_object_register(child, rec);
 
    eina_list_free(children_list);
 }
@@ -707,7 +942,7 @@ _on_app_register(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pendi
 }
 
 static Eina_Bool
-_app_register(Eldbus_Connection *a11y_bus)
+_app_register(void)
 {
    Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY,
                                     ATSPI_DBUS_PATH_ROOT,
@@ -716,27 +951,381 @@ _app_register(Eldbus_Connection *a11y_bus)
    Eldbus_Message_Iter *iter = eldbus_message_iter_get(message);
 
    object_append_reference(iter, _root);
+   eldbus_connection_send(_a11y_bus, message, _on_app_register, NULL, -1);
+
+   return EINA_TRUE;
+}
 
-   eldbus_connection_send(a11y_bus, message, _on_app_register, NULL, -1);
+static void
+_cache_update(void)
+{
+   _cache_object_register(_root, EINA_TRUE);
+}
+
+static void
+_bus_objects_register(void)
+{
+   _cache_interface = eldbus_service_interface_register(_a11y_bus, CACHE_INTERFACE_PATH, &cache_iface_desc);
+}
+
+static void
+_set_broadcast_flag(const char *event)
+{
+   char **tokens;
+
+   tokens = eina_str_split(event, ":", 3);
+
+   if (!tokens) return;
+
+   if (!strcmp(tokens[0], "Object"))
+     {
+        if (!tokens[1] || *tokens[1] == '\0') return; // do not handle "Object:*"
+        else if (!strcmp(tokens[1], "StateChanged"))
+          {
+             if (!tokens[2] || *tokens[2] == '\0')
+               _object_state_broadcast_mask = -1; // broadcast all
+             else if (!strcmp(tokens[2], "Focused"))
+               BIT_FLAG_SET(_object_state_broadcast_mask, ATSPI_STATE_FOCUSED);
+             else if (!strcmp(tokens[2], "Showing"))
+               BIT_FLAG_SET(_object_state_broadcast_mask, ATSPI_STATE_SHOWING);
+          }
+        else if (!strcmp(tokens[1], "PropertyChange"))
+          {
+             if (!tokens[2] || *tokens[2] == '\0')
+               _object_property_broadcast_mask = -1; //broadcast all
+             else if (!strcmp(tokens[2], "AccessibleValue"))
+               BIT_FLAG_SET(_object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_VALUE);
+             else if (!strcmp(tokens[2], "AccessibleName"))
+               BIT_FLAG_SET(_object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_NAME);
+             else if (!strcmp(tokens[2], "AccessibleDescription"))
+               BIT_FLAG_SET(_object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_DESCRIPTION);
+             else if (!strcmp(tokens[2], "AccessibleParent"))
+               BIT_FLAG_SET(_object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_PARENT);
+             else if (!strcmp(tokens[2], "AccessibleRole"))
+               BIT_FLAG_SET(_object_property_broadcast_mask, ATSPI_OBJECT_PROPERTY_ROLE);
+          }
+        else if (!strcmp(tokens[1], "ChildrenChanged"))
+          {
+             if (!tokens[2] || *tokens[2] == '\0')
+               _object_children_broadcast_mask = -1; // broadcast all
+             else if (!strcmp(tokens[2], "add"))
+               BIT_FLAG_SET(_object_children_broadcast_mask, ATSPI_OBJECT_CHILD_ADDED);
+             else if (!strcmp(tokens[2], "remove"))
+               BIT_FLAG_SET(_object_children_broadcast_mask, ATSPI_OBJECT_CHILD_ADDED);
+          }
+     }
+   else if (!strcmp(tokens[0], "Window"))
+     {
+        if (!tokens[1] || *tokens[1] == '\0')
+          _window_signal_broadcast_mask = -1; // broadcast all
+        else if (!strcmp(tokens[1], "Create"))
+          BIT_FLAG_SET(_window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_CREATE);
+        else if (!strcmp(tokens[1], "Activate"))
+          BIT_FLAG_SET(_window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_ACTIVATE);
+        else if (!strcmp(tokens[1], "Deactivate"))
+          BIT_FLAG_SET(_window_signal_broadcast_mask, ATSPI_WINDOW_EVENT_DEACTIVATE);
+     }
+
+   free(tokens[0]);
+   free(tokens);
+}
+
+static void
+_registered_listeners_get(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   DBG("Updating ATSPI2 clients registered events list.");
+   _object_children_broadcast_mask = 0;
+   _object_property_broadcast_mask = 0;
+   _object_state_broadcast_mask = 0;
+   _window_signal_broadcast_mask = 0;
+
+   const char *event, *bus;
+   Eldbus_Message_Iter *iter, *siter;
+   if (!eldbus_message_arguments_get(msg, "a(ss)", &iter))
+     {
+        ERR("Invalid answer type from GetRegisteredEvents method call!");
+        return;
+     }
+   while (eldbus_message_iter_get_and_next(iter, 'r', &siter))
+     {
+        eldbus_message_iter_arguments_get(siter, "ss", &bus, &event);
+        _set_broadcast_flag(event);
+     }
+}
+
+static void
+_registered_events_list_update(void)
+{
+   Eldbus_Message *msg;
+   msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "GetRegisteredEvents");
+   eldbus_connection_send(_a11y_bus, msg, _registered_listeners_get, NULL, -1);
+}
+
+static void
+_handle_listener_change(void *data EINA_UNUSED, const Eldbus_Message *msg)
+{
+   const char *bus, *event;
+   if (!eldbus_message_arguments_get(msg, "ss", &bus, &event))
+     {
+        ERR("Invalid org.a11y.Registry signal message args.");
+        return;
+     }
+   _registered_events_list_update();
+}
+
+static void
+_send_signal_state_changed(Elm_Atspi_Object *obj, AtspiStateType type, Eina_Bool new_value)
+{
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter, *viter;
+   Eldbus_Service_Interface *events = NULL;
+   char *desc;
+
+   if (!BIT_FLAG_GET(_object_state_broadcast_mask, type))
+     {
+        DBG("Masking event: %d", type);
+        return;
+     }
+
+   switch (type) {
+        case ATSPI_STATE_FOCUSED:
+         desc = "focused";
+         break;
+        case ATSPI_STATE_SHOWING:
+         desc = "showing";
+         break;
+        case ATSPI_STATE_VISIBLE:
+         desc = "visible";
+         break;
+        default:
+         desc = NULL;
+   }
+
+   eo_do(obj, eo_base_data_get("atspi_event_interface", (void **)&events));
+   if (!events)
+     {
+        ERR("Atspi object does not have event interface!");
+        return;
+     }
+   msg = eldbus_service_signal_new(events, ATSPI_OBJECT_EVENT_STATE_CHANGED);
+   iter = eldbus_message_iter_get(msg);
+
+   eldbus_message_iter_arguments_append(iter, "sii", desc, new_value, 0);
+
+   viter = eldbus_message_iter_container_new(iter, 'v', "i");
+   EINA_SAFETY_ON_NULL_RETURN(viter);
+
+   eldbus_message_iter_arguments_append(viter, "i", 0);
+   eldbus_message_iter_container_close(iter, viter);
+
+   object_append_reference(iter, obj);
+
+   eldbus_service_signal_send(events, msg);
+   DBG("signal sent StateChanged:%s:%d", desc, new_value);
+}
+
+static void
+_send_signal_property_changed(Elm_Atspi_Object *ao, enum _Atspi_Object_Property prop)
+{
+   const char *desc;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter, *siter, *viter;
+   Eldbus_Service_Interface *events = NULL;
+
+   if (!BIT_FLAG_GET(_object_property_broadcast_mask, prop))
+     return;
+
+   switch(prop)
+    {
+     case ATSPI_OBJECT_PROPERTY_NAME:
+        desc = "accessible-name";
+        break;
+     case ATSPI_OBJECT_PROPERTY_DESCRIPTION:
+        desc = "accessible-description";
+        break;
+     case ATSPI_OBJECT_PROPERTY_ROLE:
+        desc = "accessible-role";
+        break;
+     case ATSPI_OBJECT_PROPERTY_PARENT:
+        desc = "accessible-parent";
+        break;
+     case ATSPI_OBJECT_PROPERTY_VALUE:
+        desc = "accessible-value";
+        break;
+     default:
+        desc = NULL;
+    }
+   eo_do(ao, eo_base_data_get("atspi_event_interface", (void**)&events));
+   if (!events)
+     {
+        ERR("Atspi object does not have event interface!");
+        return;
+     }
+   msg = eldbus_service_signal_new(events, ATSPI_OBJECT_EVENT_PROPERTY_CHANGED);
+   EINA_SAFETY_ON_NULL_RETURN(msg);
+
+   iter = eldbus_message_iter_get(msg);
+   siter = eldbus_message_iter_container_new(iter, 'r', NULL);
+   EINA_SAFETY_ON_NULL_RETURN(siter);
+
+   eldbus_message_iter_arguments_append(siter, "suu", desc, 0, 0);
+
+   viter = eldbus_message_iter_container_new(siter, 'v', "s");
+   EINA_SAFETY_ON_NULL_RETURN(viter);
+
+   eldbus_message_iter_arguments_append(viter, "s", _path_from_access_object(ao));
+
+   eldbus_message_iter_arguments_append(siter, "v", viter);
+   eldbus_message_iter_container_close(siter, viter);
+
+   eldbus_message_iter_container_close(iter, siter);
+   eldbus_service_signal_send(events, msg);
+   DBG("signal sent PropertyChanged:%s", desc);
+}
+
+static void
+_send_signal_children_changed(Elm_Atspi_Object *parent, Elm_Atspi_Object *child, enum _Atspi_Object_Child_Event_Type type)
+{
+   Eldbus_Service_Interface *events = NULL;
+   Eldbus_Message_Iter *iter, *viter;
+   Eldbus_Message *msg;
+   const char *desc = NULL;
+   int idx;
+
+   if (!BIT_FLAG_GET(_object_children_broadcast_mask, type))
+     return;
+
+   _cache_object_register(parent, EINA_FALSE);
+   _cache_object_register(child, EINA_FALSE);
+
+   eo_do(parent, eo_base_data_get("atspi_event_interface", (void **)&events));
+   if (!events)
+     {
+        ERR("Atspi object does not have event interface! %p %p %s", parent, _root, eo_class_name_get(eo_class_get(parent)));
+        return;
+     }
+
+   switch(type)
+    {
+     case ATSPI_OBJECT_CHILD_ADDED:
+        desc = "add";
+        eo_do(child, elm_atspi_obj_index_in_parent_get(&idx));
+        break;
+     case ATSPI_OBJECT_CHILD_REMOVED:
+        desc = "remove";
+        idx = -1;
+        break;
+    }
+   msg = eldbus_service_signal_new(events, ATSPI_OBJECT_EVENT_CHILDREN_CHANGED);
+   EINA_SAFETY_ON_NULL_RETURN(msg);
+
+   iter = eldbus_message_iter_get(msg);
+   eldbus_message_iter_arguments_append(iter, "sii", desc, idx, 0);
+
+   viter = eldbus_message_iter_container_new(iter, 'v', "(so)");
+   EINA_SAFETY_ON_NULL_RETURN(viter);
+
+   object_append_reference(viter, child);
+   eldbus_message_iter_container_close(iter, viter);
+
+   object_append_reference(iter, _root);
+
+   eldbus_service_signal_send(events, msg);
+   DBG("signal sent childrenChanged:%s:%d", desc, idx);
+}
+
+static void
+_send_signal_window(Elm_Atspi_Object *eo, enum _Atspi_Window_Signals type)
+{
+   const char *desc;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter, *viter;
+   Eldbus_Service_Interface *window = NULL;
+
+   if (!BIT_FLAG_GET(_window_signal_broadcast_mask, type))
+     return;
+
+   eo_do(eo, eo_base_data_get("window_event_interface", (void**)&window));
+   if (!window)
+     {
+        ERR("Atspi object does not have window interface!");
+        return;
+     }
+
+   switch(type)
+     {
+      case ATSPI_WINDOW_EVENT_DEACTIVATE:
+         desc = "Deactivate";
+         break;
+      case ATSPI_WINDOW_EVENT_ACTIVATE:
+         desc = "Activate";
+         break;
+      default:
+         desc = "";
+     }
+
+   msg = eldbus_service_signal_new(window, type);
+   EINA_SAFETY_ON_NULL_RETURN(msg);
+
+   iter = eldbus_message_iter_get(msg);
+   eldbus_message_iter_arguments_append(iter, "sii", desc, 0, 0);
+
+   viter = eldbus_message_iter_container_new(iter, 'v', "i");
+   EINA_SAFETY_ON_NULL_RETURN(viter);
+
+   eldbus_message_iter_arguments_append(viter, "i", 0);
+   eldbus_message_iter_container_close(iter, viter);
+
+   object_append_reference(iter, eo);
+
+   eldbus_service_signal_send(window, msg);
+   DBG("signal sent Window:%s", desc);
+}
+
+static Eina_Bool
+_handle_atspi_event(void *data EINA_UNUSED, Elm_Atspi_Object *ao, const Eo_Event_Description *desc, void *event_info)
+{
+   if (desc == EV_ATSPI_OBJ_NAME_CHANGED)
+     _send_signal_property_changed(ao, ATSPI_OBJECT_PROPERTY_NAME);
+   else if (desc == EV_ATSPI_OBJ_STATE_CHANGED)
+     {
+        int *event_data = event_info;
+        _send_signal_state_changed(ao, (AtspiStateType)event_data[0], (Eina_Bool)event_data[1]);
+     }
+   else if (desc == EV_ATSPI_OBJ_CHILD_ADD)
+     _send_signal_children_changed(ao, event_info, ATSPI_OBJECT_CHILD_ADDED);
+   else if (desc == EV_ATSPI_OBJ_CHILD_DEL)
+     _send_signal_children_changed(ao, event_info, ATSPI_OBJECT_CHILD_REMOVED);
+   else if (desc == EV_ATSPI_OBJ_WINDOW_ACTIVATED)
+     _send_signal_window(ao, ATSPI_WINDOW_EVENT_ACTIVATE);
+   else if (desc == EV_ATSPI_OBJ_WINDOW_DEACTIVATED)
+     _send_signal_window(ao, ATSPI_WINDOW_EVENT_DEACTIVATE);
 
    return EINA_TRUE;
 }
 
 static void
-_bus_objects_register(Eldbus_Connection *a11y_bus)
+_event_handlers_register(void)
 {
-   _cache_interface = eldbus_service_interface_register(a11y_bus, CACHE_INTERFACE_PATH, &cache_iface_desc);
-   _atspi_objects_register_rec(_root);
-   DBG("%d elements registered in cache", eina_hash_population(_cache));
+   _registered_events_list_update();
+
+   // register signal handlers in order to update list of registered listeners of ATSPI-Clients
+   _register_hdl = eldbus_signal_handler_add(_a11y_bus, ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "EventListenerRegistered", _handle_listener_change, NULL);
+   _unregister_hdl = eldbus_signal_handler_add(_a11y_bus, ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "EventListenerDeregistered", _handle_listener_change, NULL);
+
+   // handle incoming events from Elm_Atspi_Objects
+   _elm_atspi_object_global_callback_add(_handle_atspi_event, NULL);
 }
 
 static void
 _a11y_bus_initialize(const char *socket_addr)
 {
-   Eldbus_Connection *a11y_bus = eldbus_address_connection_get(socket_addr);
-   _a11y_bus = a11y_bus;
-   _bus_objects_register(a11y_bus);
-   _app_register(a11y_bus);
+   _a11y_bus = eldbus_address_connection_get(socket_addr);
+
+   _cache_update();
+   _bus_objects_register();
+   _app_register();
+   _event_handlers_register();
 }
 
 static void
@@ -771,11 +1360,18 @@ _elm_atspi_bridge_init(void)
 
    if (!_init_count && _elm_config->access_mode == ELM_ACCESS_MODE_ON)
      {
+        _elm_atspi_object_init();
         session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+               EINA_SAFETY_ON_NULL_RETURN(session_bus);
         msg = eldbus_message_method_call_new(A11Y_DBUS_NAME, A11Y_DBUS_PATH, A11Y_DBUS_INTERFACE, "GetAddress");
+               if (!msg)
+                 {
+                        eldbus_connection_unref(session_bus);
+                        return;
+                 }
         eldbus_connection_send(session_bus, msg, _a11y_bus_address_get, session_bus, -1);
         _cache = eina_hash_string_superfast_new(NULL);
-        _root = elm_atspi_root_object_get();
+        _root = _elm_atspi_root_object_get();
         _init_count = 1;
      }
 }
@@ -785,7 +1381,15 @@ _elm_atspi_bridge_shutdown(void)
 {
    if (_init_count)
      {
-        eo_unref(_root);
+        _elm_atspi_object_shutdown();
+
+        if (_register_hdl)
+          eldbus_signal_handler_del(_register_hdl);
+        _register_hdl = NULL;
+
+        if (_unregister_hdl)
+          eldbus_signal_handler_del(_unregister_hdl);
+        _unregister_hdl = NULL;
 
         if (_cache_interface)
           eldbus_service_object_unregister(_cache_interface);
index 612130a..790d3d2 100644 (file)
@@ -5,9 +5,21 @@
 #include <Elementary.h>
 #include "elm_widget.h"
 #include "elm_priv.h"
+#include "assert.h"
 
 #include "atspi/atspi-constants.h"
 
+static Elm_Atspi_Object *_app;
+static Eina_List *_global_callbacks;
+
+typedef struct _Elm_Atspi_Global_Callback_Info Elm_Atspi_Global_Callback_Info;
+
+struct _Elm_Atspi_Global_Callback_Info
+{
+   Eo_Event_Cb cb;
+   void *user_data;
+};
+
 const char* Atspi_Name[] = {
     "invalid",
     "accelerator label",
@@ -115,177 +127,313 @@ const char* Atspi_Name[] = {
     "last defined"
 };
 
-#define ARG_GET(valist, type) va_arg(*valist, type)
+extern Eina_List *_elm_win_list;
 
-static Elm_Atspi_Object * _elm_atspi_factory_construct(Evas_Object *obj, Elm_Atspi_Object *);
+EAPI Eo_Op ELM_ATSPI_OBJ_BASE_ID = EO_NOOP;
 
-extern Eina_List *_elm_win_list;
+EAPI const Eo_Event_Description _EV_ATSPI_OBJ_NAME_CHANGED =
+        EO_EVENT_DESCRIPTION("name,changed", "Called when accessible object text has changed.");
 
-typedef struct _Atspi_Object_Data Atspi_Object_Data;
+EAPI const Eo_Event_Description _EV_ATSPI_OBJ_CHILD_ADD = 
+        EO_EVENT_DESCRIPTION("child,added", "Called when accessible object children was created.");
 
-struct _Atspi_Object_Data
-{
-   const char *name;
-   const char *description;
-   AtspiRole role;
-};
+EAPI const Eo_Event_Description _EV_ATSPI_OBJ_CHILD_DEL = 
+        EO_EVENT_DESCRIPTION("child,removed", "Called when accessible object children was destroyed.");
 
-EAPI Eo_Op ELM_ATSPI_OBJ_BASE_ID = EO_NOOP;
+EAPI const Eo_Event_Description _EV_ATSPI_OBJ_STATE_CHANGED =
+        EO_EVENT_DESCRIPTION("state,changed", "Called when accessible object state has changed.");
+
+EAPI const Eo_Event_Description _EV_ATSPI_OBJ_WINDOW_ACTIVATED =
+        EO_EVENT_DESCRIPTION("widnow,created", "Called when new window has been activated. (unfocuesed)");
+
+EAPI const Eo_Event_Description _EV_ATSPI_OBJ_WINDOW_DEACTIVATED =
+        EO_EVENT_DESCRIPTION("widnow,created", "Called when new window has been deactivated (unfocused).");
+
+static void
+_eo_emit_state_changed_event(void *data, Evas *e EINA_UNUSED, Evas_Object *eo EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_Atspi_Object *ao = data;
+   int event_data[2] = {ATSPI_STATE_VISIBLE, 1};
+   eo_do(ao, eo_event_callback_call(EV_ATSPI_OBJ_STATE_CHANGED, &event_data[0], NULL));
+}
 
 static void
-_description_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
 {
-   const char **ret = ARG_GET(list, const char **);
-   Atspi_Object_Data *ad = _pd;
+   Evas_Object *internal_obj = NULL;
+   eo_do_super(obj, ELM_ATSPI_CLASS, eo_constructor());
+
+   eo_do(obj, eo_parent_get(&internal_obj));
 
-   *ret = ad->description;
+   /* Evas_Object can only hold refs to atspi-object */
+   assert(eo_isa(internal_obj, EVAS_OBJ_SMART_CLASS));
+
+   evas_object_data_set(internal_obj, "_atspi_object", obj);
+   evas_object_event_callback_add(internal_obj, EVAS_CALLBACK_SHOW, _eo_emit_state_changed_event, obj);
+}
+
+static void
+_destructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   eo_do_super(obj, ELM_ATSPI_CLASS, eo_destructor());
 }
 
 static void
-_description_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+_child_at_index_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   const char *desc = ARG_GET(list, const char *);
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(int, idx, list);
+   EO_PARAMETER_GET(Elm_Atspi_Object**, ao, list);
+   Eina_List *children = NULL;
 
-   if (ad->description)
-     eina_stringshare_del(ad->description);
+   eo_do(obj, elm_atspi_obj_children_get(&children));
+   if (!children) return;
 
-   ad->description = eina_stringshare_add(desc);
+   if (ao) *ao = eina_list_nth(children, idx);
+   eina_list_free(children);
 }
 
 static void
-_parent_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
+_object_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   Elm_Atspi_Object **ret = ARG_GET(list, Elm_Atspi_Object**);
+   EO_PARAMETER_GET(Evas_Object**, ret, list);
    eo_do(obj, eo_parent_get(ret));
 }
 
 static void
-_name_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_index_in_parent_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   const char **ret = ARG_GET(list, const char **);
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(unsigned int*, idx, list);
+   Elm_Atspi_Object *chld, *parent = NULL;
+   Eina_List *l, *children = NULL;
+   unsigned int tmp = 0;
+
+   eo_do(obj, elm_atspi_obj_parent_get(&parent));
+   if (!parent) return;
+   eo_do(parent, elm_atspi_obj_children_get(&children));
 
-   *ret = ad->name;
+   EINA_LIST_FOREACH(children, l, chld)
+     {
+        if (chld == obj)
+          {
+             if (idx) *idx = tmp;
+             break;
+          }
+        tmp++;
+     }
+   if (tmp == eina_list_count(children))
+      ERR("Access object not present in parent's children list!");
+
+   eina_list_free(children);
 }
 
 static void
-_name_set(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_role_name_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   const char *name = ARG_GET(list, const char *);
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(const char **, ret, list);
+   AtspiRole role = ATSPI_ROLE_INVALID;
+
+   eo_do(obj, elm_atspi_obj_role_get(&role));
+
+   if (role >= ATSPI_ROLE_LAST_DEFINED)
+     {
+        ERR("Invalid role enum for atspi-object: %d.", role);
+        return;
+     }
 
-   if (ad->name)
-     eina_stringshare_del(ad->name);
+   if (ret) *ret = Atspi_Name[role];
+}
 
-   ad->name = eina_stringshare_add(name);
+static void
+_description_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   EO_PARAMETER_GET(const char **, ret, list);
+   *ret = NULL;
 }
 
 static void
-_role_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_localized_role_name_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   AtspiRole *ret = ARG_GET(list, AtspiRole *);
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(const char **, ret, list);
+   const char *name = NULL;
 
-   *ret = ad->role;
+   eo_do(obj, elm_atspi_obj_role_name_get(&name));
+   if (!name) return;
+#ifdef ENABLE_NLS
+   if (ret) *ret = gettext(name);
+#else
+   if (ret) *ret = name;
+#endif
 }
 
 static void
-_role_set(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_state_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   AtspiRole role = ARG_GET(list, int);
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(Elm_Atspi_State *, ret, list);
+   Evas_Object *evobj = NULL;
+   Elm_Atspi_State states = 0;
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
 
-   ad->role = role;
+   if (evas_object_visible_get(evobj))
+     BIT_FLAG_SET(states, ATSPI_STATE_VISIBLE);
+
+   if (ret) *ret = states;
 }
 
 static void
-_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_comp_access_at_point_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   eo_do_super(obj, ELM_ATSPI_CLASS, eo_constructor());
-   Atspi_Object_Data *ad = _pd;
-   ad->name = ad->description = NULL;
+   EO_PARAMETER_GET(int, x, list);
+   EO_PARAMETER_GET(int, y, list);
+   EO_PARAMETER_GET(AtspiCoordType, type, list);
+   EO_PARAMETER_GET(Evas_Object **, ret, list);
+   int ee_x, ee_y;
+   Eina_List *l, *objs;
+   Evas_Object *evobj = NULL;
+
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+
+   if (!evobj) return;
+   if (type == ATSPI_COORD_TYPE_SCREEN)
+     {
+        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(evobj));
+               if (!ee) return;
+        ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
+        x -= ee_x;
+        y -= ee_y;
+     }
+     objs = evas_objects_at_xy_get(evas_object_evas_get(evobj), x, y, EINA_TRUE, EINA_TRUE);
+     EINA_LIST_FOREACH(objs, l, evobj)
+       {
+          // return first only, test if there is atspi interface for eo
+          Elm_Atspi_Object *acc = _elm_atspi_factory_construct(evobj);
+          if (acc)
+            {
+               *ret = evobj;
+               break;
+            }
+       }
+     eina_list_free(objs);
 }
 
 static void
-_destructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_comp_extents_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(int *, x, list);
+   EO_PARAMETER_GET(int*, y, list);
+   EO_PARAMETER_GET(int*, w, list);
+   EO_PARAMETER_GET(int*, h, list);
+   EO_PARAMETER_GET(AtspiCoordType, type, list);
+   int ee_x, ee_y;
+   Evas_Object *evobj = NULL;
 
-   eina_stringshare_del(ad->name);
-   eina_stringshare_del(ad->description);
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+   if (!evobj) return;
 
-   eo_do_super(obj, ELM_ATSPI_CLASS, eo_destructor());
+   evas_object_geometry_get(evobj, x, y, w, h);
+   if (type == ATSPI_COORD_TYPE_SCREEN)
+     {
+        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(evobj));
+               if (!ee) return;
+        ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
+        if (x) *x += ee_x;
+        if (y) *y += ee_y;
+     }
 }
 
 static void
-_role_name_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_comp_extents_set(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   const char **ret = ARG_GET(list, const char **);
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(int, x, list);
+   EO_PARAMETER_GET(int, y, list);
+   EO_PARAMETER_GET(int, w, list);
+   EO_PARAMETER_GET(int, h, list);
+   EO_PARAMETER_GET(AtspiCoordType, type, list);
+   EO_PARAMETER_GET(Eina_Bool *, ret, list);
+   int wx, wy;
+   Evas_Object *evobj = NULL;
+
+   if (ret) *ret = EINA_FALSE;
+   if ((x < 0) || (y < 0) || (w < 0) || (h < 0)) return;
+
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+   if (!evobj) return;
+
+   if (type == ATSPI_COORD_TYPE_SCREEN)
+     {
+        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(evobj));
+               if (!ee) return;
+        evas_object_geometry_get(evobj, &wx, &wy, NULL, NULL);
+        ecore_evas_move(ee, x - wx, y - wy);
+     }
+   else
+     evas_object_move(evobj, x, y);
 
-   *ret = Atspi_Name[ad->role];
+   evas_object_resize(evobj, w, h);
+   if (ret) *ret = EINA_TRUE;
 }
 
 static void
-_localized_role_name_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_comp_layer_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   const char **ret = ARG_GET(list, const char **);
-   Atspi_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(int *, ret, list);
+   Elm_Object_Layer layer;
+   Evas_Object *evobj = NULL;
+   AtspiComponentLayer spi_layer;
+
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+   if (!evobj) return;
+
+   layer = evas_object_layer_get(evobj);
+   switch (layer) {
+    case ELM_OBJECT_LAYER_BACKGROUND:
+       spi_layer = ATSPI_LAYER_BACKGROUND;
+       break;
+    case ELM_OBJECT_LAYER_FOCUS:
+    case ELM_OBJECT_LAYER_TOOLTIP:
+    case ELM_OBJECT_LAYER_CURSOR:
+       spi_layer = ATSPI_LAYER_OVERLAY;
+       break;
+    default:
+       spi_layer = ATSPI_LAYER_WIDGET;
+   }
+   if (ret) *ret = spi_layer;
+}
 
-#ifdef ENABLE_NLS
-   *ret = gettext(Atspi_Name[ad->role]);
-#else
-   *ret = Atspi_Name[ad->role];
-#endif
+static void
+_comp_z_order_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   // FIXME
 }
 
 static void
-_child_at_index_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
+_cb_call(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   int idx = ARG_GET(list, int);
-   Elm_Atspi_Object **ao = ARG_GET(list, Elm_Atspi_Object**);
-   Eina_List *children = NULL;
-   eo_do(obj, elm_atspi_obj_children_get(&children));
+   Elm_Atspi_Global_Callback_Info *info;
+   Eina_List *l;
+   EO_PARAMETER_GET(const Eo_Event_Description *, desc, list);
+   EO_PARAMETER_GET(void *, event_info, list);
+   EO_PARAMETER_GET(Eina_Bool *, ret, list);
 
-   if (children)
-     *ao = eina_list_nth(children, idx);
-   else
-     *ao = NULL;
+   EINA_LIST_FOREACH(_global_callbacks, l, info)
+     {
+        if (info->cb) info->cb(info->user_data, obj, desc, event_info);
+     }
 
-   eina_list_free(children);
+   eo_do_super(obj, ELM_ATSPI_CLASS, eo_event_callback_call(desc, event_info, ret));
 }
 
 static void
-_index_in_parent_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
+_comp_alpha_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   unsigned int *idx = ARG_GET(list, unsigned int*);
-   Elm_Atspi_Object *chld, *parent = NULL;
-   Eina_List *l, *children = NULL;
-   unsigned int tmp = 0;
-   eo_do(obj, elm_atspi_obj_parent_get(&parent));
+   EO_PARAMETER_GET(double *, ret, list);
+   Evas_Object *evobj = NULL;
+   int alpha;
 
-   if (parent)
-     {
-        eo_do(parent, elm_atspi_obj_children_get(&children));
-        EINA_LIST_FOREACH(children, l, chld)
-          {
-             if (chld == obj)
-               {
-                  *idx = tmp;
-                  break;
-               }
-             tmp++;
-          }
-        if (tmp == eina_list_count(children))
-             ERR("Access object not present in parent's children list!");
-        EINA_LIST_FREE(children, chld)
-           eo_unref(chld);
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+   if (!evobj) return;
 
-        eo_unref(parent);
-     }
-   else
-     DBG("Access Object has no parent.");
+   evas_object_color_get(evobj, NULL, NULL, NULL, &alpha);
+   if (ret) *ret = (double)alpha / 255.0;
 }
 
 static void
@@ -294,17 +442,20 @@ _class_constructor(Eo_Class *klass)
    const Eo_Op_Func_Description func_desc[] = {
         EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
         EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
-        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_NAME_GET), _name_get),
-        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_NAME_SET), _name_set),
-        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_GET), _description_get),
-        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_SET), _description_set),
-        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET), _parent_get),
+        EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_CALL), _cb_call),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_OBJECT_GET), _object_get),
         EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_CHILD_AT_INDEX_GET), _child_at_index_get),
         EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_INDEX_IN_PARENT_GET), _index_in_parent_get),
-        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_GET), _role_get),
-        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_SET), _role_set),
         EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_NAME_GET), _role_name_get),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_GET), _description_get),
         EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_LOCALIZED_ROLE_NAME_GET), _localized_role_name_get),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_STATE_GET), _state_get),
+        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_ACCESSIBLE_AT_POINT_GET), _comp_access_at_point_get),
+        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_EXTENTS_GET), _comp_extents_get),
+        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_EXTENTS_SET), _comp_extents_set),
+        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_LAYER_GET), _comp_layer_get),
+        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_Z_ORDER_GET), _comp_z_order_get),
+        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_ALPHA_GET), _comp_alpha_get),
         EO_OP_FUNC_SENTINEL
    };
    eo_class_funcs_set(klass, func_desc);
@@ -312,17 +463,14 @@ _class_constructor(Eo_Class *klass)
 
 static const Eo_Op_Description op_desc[] = {
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_NAME_GET, ""),
-     EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_NAME_SET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_GET, ""),
-     EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_SET, ""),
-     EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_CHILD_AT_INDEX_GET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_CHILDREN_GET, ""),
+     EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET, ""),
+     EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_OBJECT_GET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_INDEX_IN_PARENT_GET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_RELATION_SET_GET, ""),
-     EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_RELATION_SET_SET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_ROLE_GET, ""),
-     EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_ROLE_SET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_ROLE_NAME_GET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_LOCALIZED_ROLE_NAME_GET, ""),
      EO_OP_DESCRIPTION(ELM_ATSPI_OBJ_SUB_ID_STATE_GET, ""),
@@ -330,18 +478,26 @@ static const Eo_Op_Description op_desc[] = {
      EO_OP_DESCRIPTION_SENTINEL
 };
 
+static const Eo_Event_Description *event_desc[] = {
+     EV_ATSPI_OBJ_NAME_CHANGED,
+     EV_ATSPI_OBJ_STATE_CHANGED,
+     EV_ATSPI_OBJ_CHILD_ADD,
+     EV_ATSPI_OBJ_CHILD_DEL,
+     NULL
+};
+
 static const Eo_Class_Description class_desc = {
      EO_VERSION,
-     "Access_Object",
+     "Elm_Atspi_Object",
      EO_CLASS_TYPE_REGULAR,
      EO_CLASS_DESCRIPTION_OPS(&ELM_ATSPI_OBJ_BASE_ID, op_desc, ELM_ATSPI_OBJ_SUB_ID_LAST),
-     NULL,
-     sizeof(Atspi_Object_Data),
+     event_desc,
+     0,
      _class_constructor,
      NULL
 };
 
-EO_DEFINE_CLASS(elm_atspi_obj_class_get, &class_desc, EO_BASE_CLASS, NULL);
+EO_DEFINE_CLASS(elm_atspi_obj_class_get, &class_desc, EO_BASE_CLASS, ELM_ATSPI_COMPONENT_INTERFACE, NULL);
 
 // Component interface
 EAPI Eo_Op ELM_ATSPI_COMPONENT_INTERFACE_BASE_ID = EO_NOOP;
@@ -349,9 +505,9 @@ EAPI Eo_Op ELM_ATSPI_COMPONENT_INTERFACE_BASE_ID = EO_NOOP;
 static void
 _comp_interface_position_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
 {
-   int *x = ARG_GET(list, int*);
-   int *y = ARG_GET(list, int*);
-   AtspiCoordType type = ARG_GET(list, AtspiCoordType);
+   EO_PARAMETER_GET(int *, x, list);
+   EO_PARAMETER_GET(int *, y, list);
+   EO_PARAMETER_GET(AtspiCoordType, type, list);
 
    eo_do(obj, elm_atspi_component_interface_extents_get(x, y, NULL, NULL, type));
 }
@@ -359,10 +515,10 @@ _comp_interface_position_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list
 static void
 _comp_interface_position_set(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
 {
-   int x = ARG_GET(list, int);
-   int y = ARG_GET(list, int);
-   AtspiCoordType type = ARG_GET(list, AtspiCoordType);
-   Eina_Bool *ret = ARG_GET(list, Eina_Bool*);
+   EO_PARAMETER_GET(int, x, list);
+   EO_PARAMETER_GET(int, y, list);
+   EO_PARAMETER_GET(AtspiCoordType, type, list);
+   EO_PARAMETER_GET(Eina_Bool*, ret, list);
    int c_w, c_h;
 
    eo_do(obj, elm_atspi_component_interface_extents_get(NULL, NULL, &c_w, &c_h, type));
@@ -372,9 +528,9 @@ _comp_interface_position_set(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list
 static void
 _comp_interface_size_set(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
 {
-   int w = ARG_GET(list, int);
-   int h = ARG_GET(list, int);
-   Eina_Bool *ret = ARG_GET(list, Eina_Bool*);
+   EO_PARAMETER_GET(int, w, list);
+   EO_PARAMETER_GET(int, h, list);
+   EO_PARAMETER_GET(Eina_Bool*, ret, list);
    int c_x, c_y;
 
    eo_do(obj, elm_atspi_component_interface_extents_get(&c_x, &c_y, NULL, NULL, ATSPI_COORD_TYPE_WINDOW));
@@ -384,8 +540,8 @@ _comp_interface_size_set(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *li
 static void
 _comp_interface_size_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
 {
-   int *w = ARG_GET(list, int*);
-   int *h = ARG_GET(list, int*);
+   EO_PARAMETER_GET(int*, w, list);
+   EO_PARAMETER_GET(int*, h, list);
 
    eo_do(obj, elm_atspi_component_interface_extents_get(NULL,  NULL, w, h, ATSPI_COORD_TYPE_WINDOW));
 }
@@ -393,32 +549,25 @@ _comp_interface_size_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *li
 static void
 _comp_interface_contains(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
 {
-   int x = ARG_GET(list, int);
-   int y = ARG_GET(list, int);
-   AtspiCoordType type = ARG_GET(list, AtspiCoordType);
-   Eina_Bool *ret = ARG_GET(list, Eina_Bool*);
+   EO_PARAMETER_GET(int, x, list);
+   EO_PARAMETER_GET(int, y, list);
+   EO_PARAMETER_GET(AtspiCoordType, type, list);
+   EO_PARAMETER_GET(Eina_Bool*, ret, list);
    int w_x, w_y, w_w, w_h;
 
-   *ret = EINA_FALSE;
+   if (ret) *ret = EINA_FALSE;
 
    if (!eo_do(obj, elm_atspi_component_interface_extents_get(&w_x, &w_y, &w_w, &w_h, type)))
       return;
 
    if ((x >= w_x) && (x <= w_x + w_w) && (y >= w_y) && (y <= w_y + w_h))
-     *ret = EINA_TRUE;
-}
-
-static void
-_component_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
-{
-   eo_do_super(obj, ELM_ATSPI_COMPONENT_INTERFACE, eo_constructor());
+     if (ret) *ret = EINA_TRUE;
 }
 
 static void
 _component_interface_constructor(Eo_Class *klass)
 {
    const Eo_Op_Func_Description func_desc[] = {
-        EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _component_constructor),
         EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_POSITION_GET), _comp_interface_position_get),
         EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_POSITION_SET), _comp_interface_position_set),
         EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_CONTAINS), _comp_interface_contains),
@@ -459,232 +608,174 @@ static const Eo_Class_Description component_interface_desc = {
 
 EO_DEFINE_CLASS(elm_atspi_component_interface_get, &component_interface_desc, NULL, NULL);
 
-/// Elm_Atspi_Widget base class
-#define ELM_ATSPI_WIDGET_CLASS elm_atspi_widget_obj_class_get()
+// Window Interface
 
-const Eo_Class *elm_atspi_widget_obj_class_get(void) EINA_CONST;
-
-typedef struct _Access_Widget_Object_Data Access_Widget_Object_Data;
+static const Eo_Event_Description *window_event_desc[] = {
+     EV_ATSPI_OBJ_WINDOW_ACTIVATED,
+     EV_ATSPI_OBJ_WINDOW_DEACTIVATED,
+     NULL
+};
 
-struct _Access_Widget_Object_Data
-{
-     Evas_Object *obj;
+static const Eo_Class_Description window_interface_desc = {
+     EO_VERSION,
+     "Elm_Atspi_Window_Interface",
+     EO_CLASS_TYPE_INTERFACE,
+     EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
+     window_event_desc,
+     0,
+     NULL,
+     NULL
 };
 
-static void
-_del_ao_obj(void *data, Evas *e EINA_UNUSED, Evas_Object *eo EINA_UNUSED, void *event_info EINA_UNUSED)
-{
-   Elm_Atspi_Object *obj = data;
-   Access_Widget_Object_Data *ad = eo_data_scope_get(obj, ELM_ATSPI_WIDGET_CLASS);
-   ad->obj = NULL;
-   // below will cause Accessibility object destruction while evas object is destroyed and access object has none extra refs
-   eo_unref(obj);
-}
+EO_DEFINE_CLASS(elm_atspi_window_interface_get, &window_interface_desc, NULL, NULL);
 
+/// Elm_Atspi_Widget base class
 static void
-_widget_constructor(Eo *obj, void *_pd, va_list *list)
+_emit_atspi_state_changed_focused_event(void *data, Evas_Object *eo EINA_UNUSED, void *event_info EINA_UNUSED)
 {
-   Evas_Object *widget = ARG_GET(list, Evas_Object*);
-   Access_Widget_Object_Data *ad = _pd;
-   const char *name;
-
-   eo_do_super(obj, ELM_ATSPI_WIDGET_CLASS, eo_constructor());
-   name = evas_object_type_get(widget);
-
-   evas_object_event_callback_add(widget, EVAS_CALLBACK_DEL, _del_ao_obj, obj);
-
-   ad->obj = widget;
-   eo_do(obj, elm_atspi_obj_name_set(name));
-   eo_do(obj, elm_atspi_obj_role_set(ATSPI_ROLE_UNKNOWN));
+   Elm_Atspi_Object *ao = data;
+   int evdata[2] = {ATSPI_STATE_FOCUSED, 1};
+   eo_do(ao, eo_event_callback_call(EV_ATSPI_OBJ_STATE_CHANGED, &evdata[0], NULL));
 }
 
 static void
-_widget_destructor(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+_emit_atspi_state_changed_unfocused_event(void *data, Evas_Object *eo EINA_UNUSED, void *event_info EINA_UNUSED)
 {
-   Access_Widget_Object_Data *ad = _pd;
-   if (ad->obj)
-     evas_object_event_callback_del(ad->obj, EVAS_CALLBACK_DEL, _del_ao_obj);
-
-   eo_do_super(obj, ELM_ATSPI_WIDGET_CLASS, eo_destructor());
+   Elm_Atspi_Object *ao = data;
+   int evdata[2] = {ATSPI_STATE_FOCUSED, 0};
+   eo_do(ao, eo_event_callback_call(EV_ATSPI_OBJ_STATE_CHANGED, &evdata[0], NULL));
 }
 
 static void
-_widget_children_get(Eo *obj, void *_pd, va_list *list)
+_widget_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
 {
-   Eina_List **ret = ARG_GET(list, Eina_List**);
-   Access_Widget_Object_Data *ad = _pd;
-   Eina_List *l, *al = NULL;
-   Evas_Object *sub;
-   Elm_Atspi_Object *ao;
-   Elm_Widget_Smart_Data *sd;
-
-   EINA_SAFETY_ON_NULL_GOTO(ad->obj, fail);
+   Evas_Object *internal_obj = NULL;
+   eo_do_super(obj, ELM_ATSPI_WIDGET_CLASS, eo_constructor());
 
-   sd = eo_data_scope_get(ad->obj, ELM_OBJ_WIDGET_CLASS);
-   EINA_SAFETY_ON_NULL_GOTO(sd, fail);
+   eo_do(obj, eo_parent_get(&internal_obj));
 
-   EINA_LIST_FOREACH(sd->subobjs, l, sub) {
-      if (!sub) continue;
-      ao = _elm_atspi_factory_construct(sub, obj);
-      if (ao)
-         al = eina_list_append(al, ao);
-   }
+   /* Evas_Object can only hold refs to atspi-object */
+   assert(eo_isa(internal_obj, ELM_OBJ_WIDGET_CLASS));
 
-   *ret = al;
-   return;
-
-fail:
-  *ret = NULL;
-  return;
+   evas_object_smart_callback_add(internal_obj, "focused", _emit_atspi_state_changed_focused_event, obj);
+   evas_object_smart_callback_add(internal_obj, "unfocused", _emit_atspi_state_changed_unfocused_event, obj);
 }
 
-
 static void
-_widget_state_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+_widget_name_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   // FIXME
-}
+   EO_PARAMETER_GET(const char **, ret, list);
+   Evas_Object *widget = NULL;
+   const char *name = NULL;
 
-
-static void
-_widget_comp_access_at_point_get(Eo *obj, void *_pd, va_list *list)
-{
-   int x = ARG_GET(list, int);
-   int y = ARG_GET(list, int);
-   AtspiCoordType type = ARG_GET(list, AtspiCoordType);
-   Elm_Atspi_Object **ret = ARG_GET(list, Elm_Atspi_Object**);
-   int ee_x, ee_y;
-   Access_Widget_Object_Data *ad = _pd;
-   Eina_List *l, *objs;
-   Evas_Object *wid;
-
-   if (ad->obj)
-     {
-      if (type == ATSPI_COORD_TYPE_SCREEN)
-        {
-           Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(ad->obj));
-           ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
-           x -= ee_x;
-           y -= ee_y;
-        }
-        objs = evas_objects_at_xy_get(evas_object_evas_get(ad->obj), x, y, EINA_TRUE, EINA_TRUE);
-        EINA_LIST_FOREACH(objs, l, wid)
-          {
-             // return first only
-             if (elm_object_widget_check(wid))
-               {
-                  *ret = _elm_atspi_factory_construct(wid, obj);
-                  break;
-               }
-          }
-        eina_list_free(objs);
-     }
+   eo_do(obj, elm_atspi_obj_object_get(&widget));
+   name = elm_object_text_get(widget);
+   if (ret) *ret = name;
 }
 
 static void
-_widget_comp_extents_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+_widget_role_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   Access_Widget_Object_Data *ad = _pd;
-   int *x, *y, *w, *h;
-   int ee_x, ee_y;
-   x = ARG_GET(list, int*);
-   y = ARG_GET(list, int*);
-   w = ARG_GET(list, int*);
-   h = ARG_GET(list, int*);
-   AtspiCoordType type = ARG_GET(list, AtspiCoordType);
+   EO_PARAMETER_GET(AtspiRole*, ret, list);
+   const char *type;
+   AtspiRole role;
+   Evas_Object *widget = NULL;
+   eo_do(obj, elm_atspi_obj_object_get(&widget));
+   if (!widget) return;
+   type = evas_object_type_get(widget);
+
+   // FIXME make it hash or cast some first bytes to int.
+   if (!strcmp(type, "elm_win"))
+     role = ATSPI_ROLE_WINDOW;
+   else if (!strcmp(type, "elm_button"))
+     role = ATSPI_ROLE_PUSH_BUTTON;
+   else
+     role = ATSPI_ROLE_UNKNOWN;
 
-   if (ad->obj)
-     {
-       evas_object_geometry_get(ad->obj, x, y, w, h);
-       if (type == ATSPI_COORD_TYPE_SCREEN)
-         {
-            Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(ad->obj));
-            ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
-            if (x) *x += ee_x;
-            if (y) *y += ee_y;
-         }
-     }
+   if (ret) *ret = role;
 }
 
 static void
-_widget_comp_extents_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+_widget_parent_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   Access_Widget_Object_Data *ad = _pd;
-   int x, y, w, h;
-   int wx, wy;
-   x = ARG_GET(list, int);
-   y = ARG_GET(list, int);
-   w = ARG_GET(list, int);
-   h = ARG_GET(list, int);
-   AtspiCoordType type = ARG_GET(list, AtspiCoordType);
-   Eina_Bool *ret = ARG_GET(list, Eina_Bool*);
+   EO_PARAMETER_GET(Elm_Atspi_Object **, ret, list);
+   Evas_Object *widget = NULL;
+   Elm_Atspi_Object *parent;
 
-   *ret = EINA_FALSE;
+   eo_do(obj, elm_atspi_obj_object_get(&widget));
+   widget = elm_object_parent_widget_get(widget);
 
-   if ((x < 0) || (y < 0) || (w < 0) || (h < 0)) return;
+   if (widget)
+     parent = _elm_atspi_factory_construct(widget);
+   else // if parent is not found, attach it to atspi root object.
+     parent = _elm_atspi_root_object_get();
 
-   if (ad->obj)
-     {
-        if (type == ATSPI_COORD_TYPE_SCREEN)
-          {
-             Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(ad->obj));
-             evas_object_geometry_get(ad->obj, &wx, &wy, NULL, NULL);
-             ecore_evas_move(ee, x - wx, y - wy);
-          }
-        else
-          evas_object_move(ad->obj, x, y);
-
-        evas_object_resize(ad->obj, w, h);
-        *ret = EINA_TRUE;
-     }
+   if (ret) *ret = parent;
 }
 
-
 static void
-_widget_comp_layer_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+_widget_children_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   int *l = ARG_GET(list, int *);
-   Access_Widget_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(Eina_List **, ret, list);
+   Evas_Object *widget = NULL;
+   Eina_List *l, *accs = NULL;
+   Elm_Widget_Smart_Data *sd;
+   Elm_Atspi_Object *aobj;
 
-   if (ad->obj)
-     *l = evas_object_layer_get(ad->obj);
-}
+   eo_do(obj, elm_atspi_obj_object_get(&widget));
 
-static void
-_widget_comp_z_order_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
-{
-   // FIXME
+   sd = eo_data_scope_get(widget, ELM_OBJ_WIDGET_CLASS);
+   if (!sd) return;
+
+   EINA_LIST_FOREACH(sd->subobjs, l, widget)
+     {
+        if (!elm_object_widget_check(widget)) continue;
+        aobj = _elm_atspi_factory_construct(widget);
+        if (aobj)
+          accs = eina_list_append(accs, aobj);
+     }
+   if (ret)
+     *ret = accs;
+   else
+     eina_list_free(accs);
 }
 
 static void
-_widget_comp_focus_grab(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+_widget_state_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   Eina_Bool *ret = ARG_GET(list, Eina_Bool*);
-   Access_Widget_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(Elm_Atspi_State *, ret, list);
+   Evas_Object *widget;
+   Elm_Atspi_State states;
+   eo_do(obj, elm_atspi_obj_object_get(&widget));
 
-   *ret = EINA_FALSE;
+   eo_do_super(obj, ELM_ATSPI_WIDGET_CLASS, elm_atspi_obj_state_get(&states));
 
-   if (ad->obj && elm_object_focus_allow_get(ad->obj))
-     {
-       Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(ad->obj));
+   if (elm_object_focus_get(widget))
+     BIT_FLAG_SET(states, ATSPI_STATE_FOCUSED);
+   if (elm_object_focus_allow_get(widget))
+     BIT_FLAG_SET(states, ATSPI_STATE_FOCUSABLE);
+   if (!elm_object_disabled_get(widget))
+     BIT_FLAG_SET(states, ATSPI_STATE_ENABLED);
 
-       ecore_evas_activate(ee);
-       elm_object_focus_set(ad->obj, EINA_TRUE);
-       *ret = EINA_TRUE;
-     }
+   if (ret) *ret = states;
 }
 
 static void
-_widget_comp_alpha_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+_widget_comp_focus_grab(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-   double *ret = ARG_GET(list, double*);
-   int alpha;
-   Access_Widget_Object_Data *ad = _pd;
+   EO_PARAMETER_GET(Eina_Bool*, ret, list);
+   Evas_Object *evobj = NULL;
+   if (ret) *ret = EINA_FALSE;
 
-   if (ad->obj)
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+   EINA_SAFETY_ON_NULL_RETURN(evobj);
+   if (elm_object_focus_allow_get(evobj))
      {
-        evas_object_color_get(ad->obj, NULL, NULL, NULL, &alpha);
-        *ret = (double)alpha/255.0;
+       Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(evobj));
+          if (!ee) return;
+       ecore_evas_activate(ee);
+       elm_object_focus_set(evobj, EINA_TRUE);
+       if (ret) *ret = EINA_TRUE;
      }
 }
 
@@ -693,16 +784,12 @@ _widget_class_constructor(Eo_Class *klass)
 {
    const Eo_Op_Func_Description func_desc[] = {
         EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _widget_constructor),
-        EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _widget_destructor),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_NAME_GET), _widget_name_get),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_GET), _widget_role_get),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET), _widget_parent_get),
         EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_CHILDREN_GET), _widget_children_get),
         EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_STATE_GET), _widget_state_get),
-        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_ACCESSIBLE_AT_POINT_GET), _widget_comp_access_at_point_get),
-        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_EXTENTS_GET), _widget_comp_extents_get),
-        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_EXTENTS_SET), _widget_comp_extents_set),
-        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_LAYER_GET), _widget_comp_layer_get),
-        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_Z_ORDER_GET), _widget_comp_z_order_get),
         EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_FOCUS_GRAB), _widget_comp_focus_grab),
-        EO_OP_FUNC(ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_ALPHA_GET), _widget_comp_alpha_get),
         EO_OP_FUNC_SENTINEL
    };
    eo_class_funcs_set(klass, func_desc);
@@ -710,77 +797,65 @@ _widget_class_constructor(Eo_Class *klass)
 
 static const Eo_Class_Description widget_class_desc = {
      EO_VERSION,
-     "Elm_Widget Access_Object",
+     "Elm_Widget_Access_Object",
      EO_CLASS_TYPE_REGULAR,
      EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
      NULL,
-     sizeof(Access_Widget_Object_Data),
+     0,
      _widget_class_constructor,
      NULL
 };
 
-EO_DEFINE_CLASS(elm_atspi_widget_obj_class_get, &widget_class_desc, ELM_ATSPI_CLASS, ELM_ATSPI_COMPONENT_INTERFACE, NULL);
+EO_DEFINE_CLASS(elm_atspi_widget_obj_class_get, &widget_class_desc, ELM_ATSPI_CLASS, NULL);
 
-static Elm_Atspi_Object *
-_elm_atspi_factory_construct(Evas_Object *obj, Elm_Atspi_Object *parent)
-{
-   Elm_Atspi_Object *ret;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
-
-   if (!elm_object_widget_check(obj))
-      return NULL;
-
-   if (!strcmp(evas_object_type_get(obj), "elm_access"))
-     return NULL;
-
-   ret = evas_object_data_get(obj, "_atspi_object");
-   if (!ret)
-     {
-        ret = eo_add(ELM_ATSPI_WIDGET_CLASS, parent, obj);
-        evas_object_data_set(obj, "_atspi_object", ret);
-        eo_unref(ret); // only parent should hold reference to atspi object
-     }
-   else
-     {
-        Elm_Atspi_Object *tmp;
-        eo_do(ret, eo_parent_get(&tmp));
-        if (!tmp)
-          eo_do(ret, eo_parent_set(parent));
-     }
-
-   return ret;
-}
 
 /// Elm_Atspi_App base class
-const Eo_Class *elm_atspi_app_obj_class_get(void) EINA_CONST;
 #define ELM_ATSPI_APP_CLASS elm_atspi_app_obj_class_get()
 
 static void
-_app_children_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
+_app_children_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
 {
-   Eina_List **ret = ARG_GET(list, Eina_List**);
-   Eina_List *l, *objs = NULL;
+   EO_PARAMETER_GET(Eina_List **, ret, list);
+   Eina_List *l, *accs = NULL;
+   Elm_Atspi_Object *aobj;
    Evas_Object *win;
-   Elm_Atspi_Object *o = NULL;
 
    EINA_LIST_FOREACH(_elm_win_list, l, win)
      {
-       if (!win) continue;
-       o = _elm_atspi_factory_construct(win, obj);
-       if (o)
-         objs = eina_list_append(objs, o);
+        if (!win) continue;
+        aobj = _elm_atspi_factory_construct(win);
+        if (aobj)
+          accs = eina_list_append(accs, aobj);
      }
-   *ret = objs;
+
+   if (ret) *ret = accs;
 }
 
 static void
 _app_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
 {
-   eo_do_super(obj, ELM_ATSPI_APP_CLASS, eo_constructor());
+   eo_do_super(obj, ELM_ATSPI_CLASS, eo_constructor());
+}
 
-   eo_do(obj, elm_atspi_obj_name_set(elm_app_name_get()));
-   eo_do(obj, elm_atspi_obj_role_set(ATSPI_ROLE_APPLICATION));
+static void
+_app_name_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   EO_PARAMETER_GET(const char **, name, list);
+   if (name) *name = elm_app_name_get();
+}
+
+static void
+_app_role_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   EO_PARAMETER_GET(AtspiRole *, ret, list);
+   if (ret) *ret = ATSPI_ROLE_APPLICATION;
+}
+
+static void
+_app_parent_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   EO_PARAMETER_GET(Elm_Atspi_Object **, ret, list);
+   if (ret) *ret = NULL;
 }
 
 static void
@@ -788,6 +863,9 @@ _app_class_constructor(Eo_Class *klass)
 {
    const Eo_Op_Func_Description func_desc[] = {
         EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _app_constructor),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_NAME_GET), _app_name_get),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_GET), _app_role_get),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET), _app_parent_get),
         EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_CHILDREN_GET), _app_children_get),
         EO_OP_FUNC_SENTINEL
    };
@@ -800,7 +878,7 @@ static const Eo_Op_Description app_op_desc[] = {
 
 static const Eo_Class_Description app_class_desc = {
      EO_VERSION,
-     "App Access_Object",
+     "Elm_App_Access_Object",
      EO_CLASS_TYPE_REGULAR,
      EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
      NULL,
@@ -811,14 +889,165 @@ static const Eo_Class_Description app_class_desc = {
 
 EO_DEFINE_CLASS(elm_atspi_app_obj_class_get, &app_class_desc, ELM_ATSPI_CLASS, NULL);
 
-Elm_Atspi_Object * elm_atspi_root_object_get(void)
+// elm_win wrapper
+
+const Eo_Class *elm_atspi_win_obj_class_get(void) EINA_CONST;
+#define ELM_ATSPI_WIN_CLASS elm_atspi_win_obj_class_get()
+
+static void
+_win_focused(void *data, Evas_Object *eo EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_Atspi_Object *ao = data;
+   eo_do(ao, eo_event_callback_call(EV_ATSPI_OBJ_WINDOW_ACTIVATED, NULL, NULL));
+}
+
+static void
+_win_unfocused(void *data, Evas_Object *eo EINA_UNUSED, void *event_info EINA_UNUSED)
 {
-   static Elm_Atspi_Object *app;
+   Elm_Atspi_Object *ao = data;
+   eo_do(ao, eo_event_callback_call(EV_ATSPI_OBJ_WINDOW_DEACTIVATED, NULL, NULL));
+}
 
-   if (!app)
-     app = eo_add(ELM_ATSPI_APP_CLASS, NULL);
+static void
+_win_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   eo_do_super(obj, ELM_ATSPI_WIN_CLASS, eo_constructor());
+   Evas_Object *evobj = NULL;
+
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+
+   evas_object_smart_callback_add(evobj, "focused", _win_focused, obj);
+   evas_object_smart_callback_add(evobj, "unfocused", _win_unfocused, obj);
+}
+
+static void
+_win_destructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   Elm_Atspi_Object *root = _elm_atspi_root_object_get();
+   eo_do(root, eo_event_callback_call(EV_ATSPI_OBJ_CHILD_DEL, obj, NULL));
+
+   eo_do_super(obj, ELM_ATSPI_WIN_CLASS, eo_destructor());
+}
+
+static void
+_win_name_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   EO_PARAMETER_GET(const char **, ret, list);
+   Evas_Object *evobj = NULL;
+
+   eo_do(obj, elm_atspi_obj_object_get(&evobj));
+   EINA_SAFETY_ON_NULL_RETURN(evobj);
+
+   if (ret) *ret = elm_win_title_get(evobj);
+}
+
+static void
+_win_parent_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   EO_PARAMETER_GET(Elm_Atspi_Object **, ret, list);
+   if (ret) *ret = _elm_atspi_root_object_get();
+}
+
+static void
+_win_class_constructor(Eo_Class *klass)
+{
+   const Eo_Op_Func_Description func_desc[] = {
+        EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _win_constructor),
+        EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _win_destructor),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_NAME_GET), _win_name_get),
+        EO_OP_FUNC(ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET), _win_parent_get),
+        EO_OP_FUNC_SENTINEL
+   };
+   eo_class_funcs_set(klass, func_desc);
+}
+
+static const Eo_Class_Description win_class_desc = {
+     EO_VERSION,
+     "Elm_Win_Access_Object",
+     EO_CLASS_TYPE_REGULAR,
+     EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
+     NULL,
+     0,
+     _win_class_constructor,
+     NULL
+};
+
+EO_DEFINE_CLASS(elm_atspi_win_obj_class_get, &win_class_desc, ELM_ATSPI_WIDGET_CLASS, ELM_ATSPI_WINDOW_INTERFACE, NULL);
+
+Elm_Atspi_Object*
+_elm_atspi_root_object_get(void)
+{
+   if (!_app)
+     _app = eo_add(ELM_ATSPI_APP_CLASS, NULL);
    else
-     eo_ref(app);
+     eo_ref(_app);
+
+   return _app;
+}
+
+Elm_Atspi_Object *
+_elm_atspi_factory_construct(Evas_Object *obj)
+{
+   Elm_Atspi_Object *ret;
+   const char *type;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+
+   ret = evas_object_data_get(obj, "_atspi_object");
+   if (ret) return ret;
 
-   return app;
+   type = evas_object_type_get(obj);
+
+   //FIXME add possibility to install new handlers
+   if (!strcmp(type, "elm_access"))
+     {
+        DBG("Unable to create ATSPI object for elm_access widget.");
+        return NULL;
+     }
+   else if (!strcmp(type, "elm_win"))
+     ret = eo_add(ELM_ATSPI_WIN_CLASS, obj);
+   else if (!strncmp(type, "elm_", 4)) // defaults to implementation for elm_widget class.
+     ret = eo_add(ELM_ATSPI_WIDGET_CLASS, obj);
+
+   eo_unref(ret); // only evas_object should hold reference to atspi object
+
+   return ret;
+}
+
+void _elm_atspi_object_init(void)
+{
+}
+
+void _elm_atspi_object_shutdown(void)
+{
+   Elm_Atspi_Global_Callback_Info *info;
+   if (_app)
+      eo_del(_app);
+
+   EINA_LIST_FREE(_global_callbacks, info)
+      free(info);
+   _global_callbacks = NULL;
+}
+
+void _elm_atspi_object_global_callback_add(Eo_Event_Cb cb, void *user_data)
+{
+   Elm_Atspi_Global_Callback_Info *info = calloc(1, sizeof(Elm_Atspi_Global_Callback_Info));
+   if (!info) return;
+   info->user_data = user_data;
+   info->cb = cb;
+   _global_callbacks = eina_list_append(_global_callbacks, info);
+}
+
+void _elm_atspi_object_global_callback_del(Eo_Event_Cb cb)
+{
+   Elm_Atspi_Global_Callback_Info *info;
+   Eina_List *l;
+   EINA_LIST_FOREACH(_global_callbacks, l, info)
+     {
+        if ((info->cb == cb))
+          {
+             _global_callbacks = eina_list_remove(_global_callbacks, info);
+             free(info);
+          }
+     }
 }
index fdc533b..767f74b 100644 (file)
@@ -1 +1,24 @@
 typedef Eo Elm_Atspi_Object;
+
+typedef uint64_t Elm_Atspi_State;
+
+typedef enum _Elm_Atspi_Event Elm_Atspi_Event;
+
+#define BIT_FLAG_SET(mask, bit) (mask |= (1 << bit))
+#define BIT_FLAG_UNSET(mask, bit) (mask &= ~(1 << bit))
+#define BIT_FLAG_GET(mask, bit) (mask & (1 << bit))
+
+/*
+ * @brief Gets root (application) type atspi-object.
+ */
+Elm_Atspi_Object * _elm_atspi_root_object_get(void);
+
+/*
+ * @brief Constructs atspi-object for evas_object
+ */
+Elm_Atspi_Object * _elm_atspi_factory_construct(Evas_Object *obj);
+
+void _elm_atspi_object_init(void);
+
+void _elm_atspi_object_shutdown(void);
+
index 67a07c6..d1ff2b7 100644 (file)
@@ -1,32 +1,47 @@
-#define ELM_ATSPI_CLASS elm_atspi_obj_class_get()
+void _elm_atspi_object_global_callback_add(Eo_Event_Cb cv, void *user_data);
+void _elm_atspi_object_global_callback_del(Eo_Event_Cb cv);
 
+#define ELM_ATSPI_CLASS elm_atspi_obj_class_get()
 const Eo_Class *elm_atspi_obj_class_get(void) EINA_CONST;
 
+#define ELM_ATSPI_WIDGET_CLASS elm_atspi_widget_obj_class_get()
+const Eo_Class *elm_atspi_widget_obj_class_get(void) EINA_CONST;
+
 extern EAPI Eo_Op ELM_ATSPI_OBJ_BASE_ID;
 
 enum
 {
-   ELM_ATSPI_OBJ_SUB_ID_NAME_GET,
-   ELM_ATSPI_OBJ_SUB_ID_NAME_SET,
-   ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_GET,
-   ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_SET,
-   ELM_ATSPI_OBJ_SUB_ID_PARENT_GET,
+   ELM_ATSPI_OBJ_SUB_ID_NAME_GET, /* virtual */
+   ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_GET, /* virtual */
    ELM_ATSPI_OBJ_SUB_ID_CHILD_AT_INDEX_GET,
-   ELM_ATSPI_OBJ_SUB_ID_CHILDREN_GET,
+   ELM_ATSPI_OBJ_SUB_ID_CHILDREN_GET, /* virtual */
+   ELM_ATSPI_OBJ_SUB_ID_PARENT_GET, /* virtual */
+   ELM_ATSPI_OBJ_SUB_ID_OBJECT_GET,
    ELM_ATSPI_OBJ_SUB_ID_INDEX_IN_PARENT_GET,
-   ELM_ATSPI_OBJ_SUB_ID_RELATION_SET_GET,
-   ELM_ATSPI_OBJ_SUB_ID_RELATION_SET_SET,
-   ELM_ATSPI_OBJ_SUB_ID_ROLE_GET,
-   ELM_ATSPI_OBJ_SUB_ID_ROLE_SET,
+   ELM_ATSPI_OBJ_SUB_ID_RELATION_SET_GET, /* virtual */
+   ELM_ATSPI_OBJ_SUB_ID_ROLE_GET, /* virtual */
    ELM_ATSPI_OBJ_SUB_ID_ROLE_NAME_GET,
    ELM_ATSPI_OBJ_SUB_ID_LOCALIZED_ROLE_NAME_GET,
-   ELM_ATSPI_OBJ_SUB_ID_STATE_GET,
-   ELM_ATSPI_OBJ_SUB_ID_ATTRIBUTES_GET,
+   ELM_ATSPI_OBJ_SUB_ID_STATE_GET, /* virtual */
+   ELM_ATSPI_OBJ_SUB_ID_ATTRIBUTES_GET, /* virtual */
    ELM_ATSPI_OBJ_SUB_ID_LAST
 };
 
 #define ELM_ATSPI_OBJ_ID(sub_id) (ELM_ATSPI_OBJ_BASE_ID + sub_id)
 
+/* Elm_Atspi_Object events */
+extern const Eo_Event_Description _EV_ATSPI_OBJ_NAME_CHANGED;
+#define EV_ATSPI_OBJ_NAME_CHANGED (&(_EV_ATSPI_OBJ_NAME_CHANGED))
+
+extern const Eo_Event_Description _EV_ATSPI_OBJ_CHILD_ADD;
+#define EV_ATSPI_OBJ_CHILD_ADD (&(_EV_ATSPI_OBJ_CHILD_ADD))
+
+extern const Eo_Event_Description _EV_ATSPI_OBJ_CHILD_DEL;
+#define EV_ATSPI_OBJ_CHILD_DEL (&(_EV_ATSPI_OBJ_CHILD_DEL))
+
+extern const Eo_Event_Description _EV_ATSPI_OBJ_STATE_CHANGED;
+#define EV_ATSPI_OBJ_STATE_CHANGED (&(_EV_ATSPI_OBJ_STATE_CHANGED))
+
 /* Component Interface */
 #define ELM_ATSPI_COMPONENT_INTERFACE elm_atspi_component_interface_get()
 
@@ -54,6 +69,17 @@ enum
 #define ELM_ATSPI_COMPONENT_INTERFACE_ID(sub_id) (ELM_ATSPI_COMPONENT_INTERFACE_BASE_ID + sub_id)
 /* Component Interface - END */
 
+/* Window Interface */
+#define ELM_ATSPI_WINDOW_INTERFACE elm_atspi_window_interface_get()
+const Eo_Class *elm_atspi_window_interface_get(void) EINA_CONST;
+
+extern const Eo_Event_Description _EV_ATSPI_OBJ_WINDOW_ACTIVATED;
+#define EV_ATSPI_OBJ_WINDOW_ACTIVATED (&(_EV_ATSPI_OBJ_WINDOW_ACTIVATED))
+
+extern const Eo_Event_Description _EV_ATSPI_OBJ_WINDOW_DEACTIVATED;
+#define EV_ATSPI_OBJ_WINDOW_DEACTIVATED (&(_EV_ATSPI_OBJ_WINDOW_DEACTIVATED))
+/* Window Interface - END */
+
 /* Action Interface */
 #define ELM_ATSPI_ACTION_INTERFACE elm_accessible_action_interface_get()
 
@@ -108,6 +134,7 @@ enum
 };
 /* Text Interface - END */
 
+
 /* EditableText Interface */
 #define ELM_ATSPI_EDITABLE_TEXT_INTERFACE elm_accessible_editable_text_interface_get()
 
@@ -127,10 +154,9 @@ enum
 };
 /* EditableText Interface - END */
 
+/* Value Interface */
 #define ELM_ATSPI_VALUE_INTERFACE elm_accessible_value_interface_get()
 
-
-/* Value Interface */
 const Eo_Class *elm_accessible_value_interface_get(void) EINA_CONST;
 
 extern EAPI Eo_Op ELM_ATSPI_VALUE_INTERFACE_BASE_ID;
@@ -184,18 +210,10 @@ enum
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_NAME_GET), \
    EO_TYPECHECK(const char **, ret)
 
-#define elm_atspi_obj_name_set(name)\
-   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_NAME_SET),\
-   EO_TYPECHECK(const char *, name)
-
 #define elm_atspi_obj_role_get(role)\
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_GET), \
    EO_TYPECHECK(AtspiRole*, role)
 
-#define elm_atspi_obj_role_set(role)\
-   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_SET),\
-   EO_TYPECHECK(AtspiRole, role)
-
 #define elm_atspi_obj_role_name_get(ret)\
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ROLE_NAME_GET),\
    EO_TYPECHECK(const char **, ret)
@@ -208,14 +226,6 @@ enum
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_GET),\
    EO_TYPECHECK(const char **, ret)
 
-#define elm_atspi_obj_description_set(desc)\
-   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_DESCRIPTION_SET),\
-   EO_TYPECHECK(const char *, desc)
-
-#define elm_atspi_obj_parent_get(ret)\
-   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET),\
-   EO_TYPECHECK(Elm_Atspi_Object**, ret)
-
 #define elm_atspi_obj_child_at_index_get(idx, ret)\
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_CHILD_AT_INDEX_GET), \
    EO_TYPECHECK(int, idx),\
@@ -225,6 +235,14 @@ enum
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_CHILDREN_GET),\
    EO_TYPECHECK(Eina_List**, ret)
 
+#define elm_atspi_obj_parent_get(ret)\
+   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_PARENT_GET),\
+   EO_TYPECHECK(Elm_Atspi_Object**, ret)
+
+#define elm_atspi_obj_object_get(ret)\
+   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_OBJECT_GET),\
+   EO_TYPECHECK(Evas_Object**, ret)
+
 #define elm_atspi_obj_index_in_parent_get(ret)\
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_INDEX_IN_PARENT_GET),\
    EO_TYPECHECK(int*, ret)
@@ -233,11 +251,13 @@ enum
    ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_RELATION_SET_GET),\
    EO_TYPECHECK()
 
-#define elm_atspi_obj_relation_set_set() ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_RELATION_SET_SET), EO_TYPECHECK()
-
-#define elm_atspi_obj_state_get() ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_STATE_GET), EO_TYPECHECK()
+#define elm_atspi_obj_state_get(ret)\
+   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_STATE_GET),\
+   EO_TYPECHECK(Elm_Atspi_State*, ret)
 
-#define elm_atspi_obj_attributes_get() ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ATTRIBUTES_GET), EO_TYPECHECK()
+#define elm_atspi_obj_attributes_get()\
+   ELM_ATSPI_OBJ_ID(ELM_ATSPI_OBJ_SUB_ID_ATTRIBUTES_GET),\
+   EO_TYPECHECK()
 
 #define elm_atspi_component_interface_contains(x, y, type, ret)\
    ELM_ATSPI_COMPONENT_INTERFACE_ID(ELM_ATSPI_COMPONENT_INTERFACE_SUB_ID_CONTAINS),\
index ea5e93b..5ec21a3 100644 (file)
@@ -1 +1,2 @@
-EAPI Elm_Atspi_Object * elm_atspi_root_object_get(void);
+// to be removed to private:
+
index 4cb6010..5671efb 100644 (file)
@@ -6318,6 +6318,19 @@ elm_widget_tree_dot_dump(const Evas_Object *top,
 #endif
 }
 
+static Eina_Bool
+_atspi_obj_create(void *data)
+{
+   Elm_Atspi_Object *parent = NULL;
+   Elm_Atspi_Object *obj = _elm_atspi_factory_construct(data);
+   if (obj)
+     {
+       eo_do(obj, elm_atspi_obj_parent_get(&parent));
+       eo_do(parent, eo_event_callback_call(EV_ATSPI_OBJ_CHILD_ADD, obj, NULL));
+     }
+   return EINA_FALSE;
+}
+
 static void
 _constructor(Eo *obj, void *class_data EINA_UNUSED, va_list *list EINA_UNUSED)
 {
@@ -6331,6 +6344,9 @@ _constructor(Eo *obj, void *class_data EINA_UNUSED, va_list *list EINA_UNUSED)
          eo_parent_get(&parent));
    eo_do(obj, elm_wdg_parent_set(parent));
    sd->on_create = EINA_FALSE;
+
+   if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
+     ecore_idle_enterer_add(_atspi_obj_create, obj);
 }
 
 static void