From ce26f5300b84a9ffaf8944a1070d80773195a6c9 Mon Sep 17 00:00:00 2001 From: Patryk Kaczmarek Date: Mon, 27 Nov 2017 12:08:50 +0530 Subject: [PATCH] elm: Conditional registration of elm_access object as atspi objects @tizen_feature orignal patch: fec8bd2f2eb6e657aa67771e147723afc8fab2dc Change-Id: I79d5bea97cd41ef94a204f699daccfb087d67c46 --- src/lib/elementary/elc_naviframe.c | 73 ++++++++++++++++++++++++++ src/lib/elementary/elm_calendar.c | 98 +++++++++++++++++++++++++++++++++++ src/lib/elementary/elm_flipselector.c | 97 +++++++++++++++++++++++++++------- 3 files changed, 249 insertions(+), 19 deletions(-) diff --git a/src/lib/elementary/elc_naviframe.c b/src/lib/elementary/elc_naviframe.c index d4dfba4..f61e850 100644 --- a/src/lib/elementary/elc_naviframe.c +++ b/src/lib/elementary/elc_naviframe.c @@ -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)); } diff --git a/src/lib/elementary/elm_calendar.c b/src/lib/elementary/elm_calendar.c index 2aff582..8b22efc 100644 --- a/src/lib/elementary/elm_calendar.c +++ b/src/lib/elementary/elm_calendar.c @@ -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)); } diff --git a/src/lib/elementary/elm_flipselector.c b/src/lib/elementary/elm_flipselector.c index 32d8ed4..42aceab 100644 --- a/src/lib/elementary/elm_flipselector.c +++ b/src/lib/elementary/elm_flipselector.c @@ -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; -- 2.7.4