elm: Conditional registration of elm_access object as atspi objects
authorPatryk Kaczmarek <patryk.k@samsung.com>
Mon, 27 Nov 2017 06:38:50 +0000 (12:08 +0530)
committerJiyoun Park <jy0703.park@samsung.com>
Thu, 21 Dec 2017 09:24:04 +0000 (18:24 +0900)
@tizen_feature

orignal patch: fec8bd2f2eb6e657aa67771e147723afc8fab2dc

Change-Id: I79d5bea97cd41ef94a204f699daccfb087d67c46

src/lib/elementary/elc_naviframe.c
src/lib/elementary/elm_calendar.c
src/lib/elementary/elm_flipselector.c

index d4dfba4..f61e850 100644 (file)
@@ -52,6 +52,9 @@ static void _on_item_back_btn_clicked(void *data, const Efl_Event *event);
 
 static Eina_Bool _key_action_top_item_get(Evas_Object *obj, const char *params);
 static Eina_Bool _key_action_item_pop(Evas_Object *obj, const char *params);
+//TIZEN ONLY(20151012): expose title as at-spi object
+static char * _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED);
+//
 
 static const Elm_Action key_actions[] = {
    {"top_item_get", _key_action_top_item_get},
@@ -321,6 +324,68 @@ _item_signals_emit(Elm_Naviframe_Item_Data *it)
    _item_content_signals_emit(it);
 }
 
+//TIZEN ONLY(20151012): expose title as at-spi object
+static void
+_naviframe_atspi_bridge_on_connect_cb(void *data, const Efl_Event *event EINA_UNUSED)
+{
+   Elm_Naviframe_Item_Data *it = (Elm_Naviframe_Item_Data*)data;
+   Evas_Object *part;
+   Evas_Object *access;
+
+   part = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(VIEW(it)), TITLE_ACCESS_PART);
+   if (part)
+     {
+        access = elm_access_object_register(part, VIEW(it));
+        _elm_access_callback_set(_elm_access_info_get(access),
+                                 ELM_ACCESS_INFO, _access_info_cb, it);
+        efl_access_role_set(access, EFL_ACCESS_ROLE_HEADING);
+     }
+}
+
+static void
+_naviframe_atspi_bridge_on_disconnect_cb(void *data, const Efl_Event *event EINA_UNUSED)
+{
+   Elm_Naviframe_Item_Data *it = (Elm_Naviframe_Item_Data*)data;
+   Evas_Object *part;
+   part = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(VIEW(it)), TITLE_ACCESS_PART);
+   elm_access_object_unregister( part );
+}
+
+static void
+_unregister_naviframe_atspi_bridge_callbacks(Elm_Naviframe_Item_Data *it EINA_UNUSED)
+{
+   if (!_elm_config->atspi_mode) return;
+
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge) return;
+
+   efl_event_callback_del(bridge, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, _naviframe_atspi_bridge_on_connect_cb, NULL);
+   efl_event_callback_del(bridge, ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, _naviframe_atspi_bridge_on_disconnect_cb, NULL);
+
+}
+
+static void
+_atspi_expose_title(Elm_Naviframe_Item_Data *it)
+{
+   Eina_Bool connected = EINA_FALSE;
+
+   if (!_elm_config->atspi_mode) return;
+
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge) return;
+
+   // If bridge is connected expose it now
+   connected = elm_obj_atspi_bridge_connected_get(bridge);
+   if (connected)
+     _naviframe_atspi_bridge_on_connect_cb(it, NULL);
+
+   // Register for bridge connect/disconnect
+   _unregister_naviframe_atspi_bridge_callbacks(it);
+   efl_event_callback_add(bridge, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, _naviframe_atspi_bridge_on_connect_cb, NULL);
+   efl_event_callback_add(bridge, ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, _naviframe_atspi_bridge_on_disconnect_cb, NULL);
+}
+//
+
 /* FIXME: we need to handle the case when this function is called
  * during a transition */
 static void
@@ -356,6 +421,10 @@ _item_style_set(Elm_Naviframe_Item_Data *it,
 
    if (sd->freeze_events)
      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
+
+   //TIZEN ONLY(20151012): expose title as at-spi object
+   _atspi_expose_title(it);
+   //
 }
 
 static void
@@ -1452,6 +1521,10 @@ _elm_naviframe_efl_canvas_group_group_del(Eo *obj, Elm_Naviframe_Data *sd)
 
    evas_object_del(sd->dummy_edje);
 
+   // TIZEN_ONLY(20151012): Unregister callbacks for ATSPI bridge enable/disable
+   _unregister_naviframe_atspi_bridge_callbacks(it);
+   //
+
    efl_canvas_group_del(efl_super(obj, MY_CLASS));
 }
 
index 2aff582..8b22efc 100644 (file)
@@ -459,6 +459,96 @@ _flush_calendar_composite_elements(Evas_Object *obj, Elm_Calendar_Data *sd)
    efl_ui_focus_composition_elements_set(obj, items);
 }
 
+//TIZEN_ONLY(20151012): Register smart callbacks for calendar buttons.
+static char *
+_localized_access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
+{
+   if (data) return E_(data);
+   return NULL;
+}
+
+static void
+_calendar_atspi_bridge_on_connect_cb(void *data, const Efl_Event *event EINA_UNUSED)
+{
+   Evas_Object *obj = (Evas_Object*)data;
+   int day;
+   int maxdays;
+   char day_s[3];
+   int ii;
+   char pname[14];
+   Evas_Object *ao, *ac;
+
+   ELM_CALENDAR_DATA_GET(obj, sd);
+   day = 0;
+   maxdays = _maxdays_get(&sd->shown_time, 0);
+   for (ii = 0; ii < 42; ii++)
+     {
+      snprintf(pname, sizeof(pname), "cit_%i.access", ii);
+      ac = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(obj), pname);
+      elm_access_object_unregister(ac);
+      if ((!day) && (ii == sd->first_day_it)) day = 1;
+      if ((day) && (day <= maxdays))
+        {
+           ao = elm_access_object_register(ac, obj);
+           efl_access_role_set(ao, EFL_ACCESS_ROLE_TABLE_CELL);
+
+           snprintf(day_s, sizeof(day_s), "%i", day++);
+           elm_access_info_set(ao, ELM_ACCESS_INFO, (const char*)day_s);
+           elm_access_info_cb_set(ao, ELM_ACCESS_CONTEXT_INFO, _localized_access_info_cb, "calendar item");
+        }
+     }
+}
+
+static void
+_calendar_atspi_bridge_on_disconnect_cb(void *data, const Efl_Event *event EINA_UNUSED)
+{
+   Evas_Object *obj = (Evas_Object*)data;
+   int ii;
+   char pname[14];
+   Evas_Object *ac;
+
+   for (ii = 0; ii < 42; ii++)
+     {
+        snprintf(pname, sizeof(pname), "cit_%i.access", ii);
+        ac = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(obj), pname);
+        elm_access_object_unregister(ac);
+     }
+}
+
+static void
+_unregister_atspi_calendar_bridge_callbacks(Evas_Object *obj)
+{
+   if (!_elm_config->atspi_mode) return;
+
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge) return;
+
+   efl_event_callback_del(bridge, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, _calendar_atspi_bridge_on_connect_cb, NULL);
+   efl_event_callback_del(bridge, ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, _calendar_atspi_bridge_on_connect_cb, NULL);
+}
+
+static void
+_register_smart_callbacks_for_calendar_buttons(Evas_Object *obj)
+{
+   Eina_Bool connected = EINA_FALSE;
+
+   if (!_elm_config->atspi_mode) return;
+
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge) return;
+
+   // If already connected register callendar buttons callbacks
+   connected = elm_obj_atspi_bridge_connected_get(bridge);
+   if (connected)
+     _calendar_atspi_bridge_on_connect_cb(obj, NULL);
+
+   // Register bridge connect/disconnect
+   _unregister_atspi_calendar_bridge_callbacks(obj);
+   efl_event_callback_add(bridge, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, _calendar_atspi_bridge_on_connect_cb, NULL);
+   efl_event_callback_add(bridge, ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, _calendar_atspi_bridge_on_disconnect_cb, NULL);
+}
+//
+
 static void
 _populate(Evas_Object *obj)
 {
@@ -683,6 +773,10 @@ _populate(Evas_Object *obj)
    elm_layout_thaw(obj);
    edje_object_message_signal_process(elm_layout_edje_get(obj));
 
+   //TIZEN_ONLY(20151012): Register smart callbacks for calendar buttons.
+   _register_smart_callbacks_for_calendar_buttons(obj);
+   //
+
    _flush_calendar_composite_elements(obj, sd);
 }
 
@@ -1526,6 +1620,10 @@ _elm_calendar_efl_canvas_group_group_del(Eo *obj, Elm_Calendar_Data *sd)
    for (i = 0; i < ELM_DAY_LAST; i++)
      eina_stringshare_del(sd->weekdays[i]);
 
+   // TIZEN_ONLY(20151012): Unregister callbacks for ATSPI bridge enable/disable
+   _unregister_atspi_calendar_bridge_callbacks(sd->obj);
+   //
+
    efl_canvas_group_del(efl_super(obj, MY_CLASS));
 }
 
index 32d8ed4..42aceab 100644 (file)
@@ -55,6 +55,9 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
    {NULL, NULL}
 };
 
+// TIZEN_ONLY(20151012): Unregister callbacks for ATSPI bridge enable/disable
+static void _unregister_flipselector_atspi_bridge_callbacks(Elm_Flipselector_Data *sd);
+//
 static Eina_Bool _key_action_flip(Evas_Object *obj, const char *params);
 
 static const Elm_Action key_actions[] = {
@@ -668,6 +671,10 @@ _elm_flipselector_efl_canvas_group_group_del(Eo *obj, Elm_Flipselector_Data *sd)
    ecore_timer_del(sd->spin);
    ecore_job_del(sd->view_update);
 
+   // TIZEN_ONLY(20151012): Unregister callbacks for ATSPI bridge enable/disable
+   _unregister_flipselector_atspi_bridge_callbacks(sd);
+   //
+
    efl_canvas_group_del(efl_super(obj, MY_CLASS));
 }
 
@@ -679,7 +686,7 @@ elm_flipselector_add(Evas_Object *parent)
 }
 
 //TIZEN ONLY(2015090): expose flipselector top/bottom buttons for accessibility tree
-static Eina_Bool _activate_top_cb (void *data, Evas_Object *obj EINA_UNUSED, Elm_Access_Action_Info *action_info EINA_UNUSED)
+static Eina_Bool _activate_top_cb(void *data, Evas_Object *obj EINA_UNUSED, Elm_Access_Action_Info *action_info EINA_UNUSED)
 {
    Elm_Flipselector_Data *sd = (Elm_Flipselector_Data*)data;
    _flipselector_walk(sd);
@@ -688,7 +695,7 @@ static Eina_Bool _activate_top_cb (void *data, Evas_Object *obj EINA_UNUSED, Elm
    return EINA_TRUE;
 }
 
-static Eina_Bool _activate_bottom_cb (void *data, Evas_Object *obj EINA_UNUSED, Elm_Access_Action_Info *action_info EINA_UNUSED)
+static Eina_Bool _activate_bottom_cb(void *data, Evas_Object *obj EINA_UNUSED, Elm_Access_Action_Info *action_info EINA_UNUSED)
 {
    Elm_Flipselector_Data *sd = (Elm_Flipselector_Data*)data;
    _flipselector_walk(sd);
@@ -698,6 +705,73 @@ static Eina_Bool _activate_bottom_cb (void *data, Evas_Object *obj EINA_UNUSED,
 }
 //
 
+//TIZEN ONLY(20151012): register callbacks for ATSPI bridge enable/disable
+static void
+_flipselector_atspi_bridge_on_connect_cb(void *data, const Efl_Event *event EINA_UNUSED)
+{
+   Elm_Flipselector_Data *sd = (Elm_Flipselector_Data*)data;
+   Evas_Object *btn1;
+   Evas_Object *btn2;
+   btn1 = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(sd->obj), "top_clipper");
+   btn2 = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(sd->obj), "bottom_clipper");
+   if (btn1 && btn2)
+     {
+        sd->access_top_button = elm_access_object_register(btn1, sd->obj);
+        sd->access_bottom_button = elm_access_object_register(btn2, sd->obj);
+
+        efl_access_role_set(sd->access_top_button, EFL_ACCESS_ROLE_PUSH_BUTTON);
+        efl_access_role_set(sd->access_bottom_button, EFL_ACCESS_ROLE_PUSH_BUTTON);
+
+        elm_access_action_cb_set(sd->access_top_button, ELM_ACCESS_ACTION_ACTIVATE, _activate_top_cb, sd);
+        elm_access_action_cb_set(sd->access_bottom_button, ELM_ACCESS_ACTION_ACTIVATE, _activate_bottom_cb, sd);
+     }
+}
+
+static void
+_flipselector_atspi_bridge_on_disconnect_cb(void *data, const Efl_Event *event EINA_UNUSED)
+{
+   Elm_Flipselector_Data *sd = (Elm_Flipselector_Data*)data;
+   elm_access_object_unregister(sd->access_top_button);
+   elm_access_object_unregister(sd->access_bottom_button);
+}
+
+static void
+_unregister_flipselector_atspi_bridge_callbacks(Elm_Flipselector_Data *sd)
+{
+   if (!_elm_config->atspi_mode) return;
+
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge) return;
+
+   efl_event_callback_del(bridge, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, _flipselector_atspi_bridge_on_connect_cb, NULL);
+   efl_event_callback_del(bridge, ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, _flipselector_atspi_bridge_on_connect_cb, NULL);
+}
+
+static void
+_atspi_expose_flipselector_top_bottom(Elm_Flipselector_Data *sd)
+{
+   Eina_Bool connected = EINA_FALSE;
+
+   if (!_elm_config->atspi_mode) return;
+
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge) return;
+
+   sd->access_top_button = NULL;
+   sd->access_bottom_button = NULL;
+
+   // Expose flipselector buttons
+   connected = elm_obj_atspi_bridge_connected_get(bridge);
+   if (connected)
+     _flipselector_atspi_bridge_on_connect_cb(sd, NULL);
+
+   // Register for ATSPI bridge enable/disable
+   _unregister_flipselector_atspi_bridge_callbacks(sd);
+   efl_event_callback_add(bridge, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, _flipselector_atspi_bridge_on_connect_cb, NULL);
+   efl_event_callback_add(bridge, ELM_ATSPI_BRIDGE_EVENT_DISCONNECTED, _flipselector_atspi_bridge_on_disconnect_cb, NULL);
+}
+//
+
 EOLIAN static Eo *
 _elm_flipselector_efl_object_constructor(Eo *obj, Elm_Flipselector_Data *sd)
 {
@@ -707,23 +781,8 @@ _elm_flipselector_efl_object_constructor(Eo *obj, Elm_Flipselector_Data *sd)
    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
    efl_access_role_set(obj, EFL_ACCESS_ROLE_LIST);
 
-   //TIZEN ONLY(2015090): expose flipselector top/bottom buttons for accessibility tree
-    if (_elm_config->atspi_mode)
-      {
-         Evas_Object *btn1 = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(obj), "top_clipper");
-         Evas_Object *btn2 = (Evas_Object*)edje_object_part_object_get(elm_layout_edje_get(obj), "bottom_clipper");
-         if (btn1 && btn2)
-           {
-              sd->access_top_button = elm_access_object_register(btn1, obj);
-              sd->access_bottom_button = elm_access_object_register(btn2, obj);
-
-              efl_access_role_set(sd->access_top_button, EFL_ACCESS_ROLE_PUSH_BUTTON);
-              efl_access_role_set(sd->access_bottom_button, EFL_ACCESS_ROLE_PUSH_BUTTON);
-
-              elm_access_action_cb_set(sd->access_top_button, ELM_ACCESS_ACTION_ACTIVATE, _activate_top_cb, sd);
-              elm_access_action_cb_set(sd->access_bottom_button, ELM_ACCESS_ACTION_ACTIVATE, _activate_bottom_cb, sd);
-           }
-      }
+   //TIZEN ONLY(20151012): expose flipselector top/bottom buttons for accessibility tree
+    _atspi_expose_flipselector_top_bottom(sd);
     //
 
    return obj;