From 2515c38ceb5d038b83e1fd4cbfc7502bf5afae3a Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Fri, 17 Feb 2023 08:32:59 +0530 Subject: [PATCH] [M108 Migration][Accessibility] Support atk in select picker This patch is for supporting atk in select picker. Reference: https://review.tizen.org/gerrit/280726 Change-Id: I4b8f83a18b6963a5ff8bc6c938d0b3bf2a3f562e Signed-off-by: Ayush Kumar --- .../browser/select_picker/select_picker_base.cc | 29 +++++- .../browser/select_picker/select_picker_base.h | 7 ++ .../select_picker/select_picker_mobile_base.cc | 106 +++++++++++++++++++++ .../select_picker/select_picker_mobile_base.h | 24 +++++ .../browser/select_picker/select_picker_tv_base.cc | 3 + .../browser/select_picker/select_picker_util.cc | 26 ++++- .../browser/select_picker/select_picker_util.h | 13 ++- .../browser/select_picker/select_picker_mobile.cc | 6 ++ .../browser/select_picker/select_picker_mobile.h | 4 + .../browser/select_picker/select_picker_tv.cc | 6 ++ .../browser/select_picker/select_picker_tv.h | 4 + 11 files changed, 224 insertions(+), 4 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.cc b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.cc index a4668c7..18d11e3 100644 --- a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.cc +++ b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.cc @@ -194,18 +194,41 @@ void SelectPickerBase::InitializeSelectedPickerData( bool need_scroll_to_top = true; for (size_t index = 0; index < items.size(); index++) { bool checked = items[index]->checked; - auto data = new GenlistCallbackData( +#if defined(TIZEN_ATK_SUPPORT) + auto* data = new GenlistCallbackData(index, this, std::move(items[index]), + popup_list_, item_class_, group_class_, + is_multiple_selection_, + ItemSelectedCallback, GetAtkStatus()); + + // Save first item for atk + if (!index) { + first_item_ = data->GetElmItem(); + selected_item_ = data->GetElmItem(); + } +#else + auto* data = new GenlistCallbackData( index, this, std::move(items[index]), popup_list_, item_class_, group_class_, is_multiple_selection_, ItemSelectedCallback); +#endif if (is_multiple_selection_ && checked) { selected_indexes_.push_back(index); if (need_scroll_to_top) { data->ScrollToTop(); need_scroll_to_top = false; +#if defined(TIZEN_ATK_SUPPORT) + // Save selected item for atk with multiple selection + selected_item_ = data->GetElmItem(); +#endif } } select_picker_data_.push_back(data); +#if defined(TIZEN_ATK_SUPPORT) + // Save selected item for atk + if (base::checked_cast(index) == selected_index_ && + !is_multiple_selection_) + selected_item_ = data->GetElmItem(); +#endif } if (is_multiple_selection_) { @@ -220,6 +243,10 @@ void SelectPickerBase::InitializeSelectedPickerData( void SelectPickerBase::Show() { evas_object_show(layout_); +#if defined(TIZEN_ATK_SUPPORT) + if (GetAtkStatus()) + elm_atspi_component_highlight_grab(selected_item_); +#endif } void SelectPickerBase::Hide() { diff --git a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.h b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.h index 95d62a6..0900cbe 100644 --- a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.h +++ b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_base.h @@ -55,6 +55,13 @@ class SelectPickerBase { virtual content::WebContentsViewAura* wcva() const { return nullptr; } +#if defined(TIZEN_ATK_SUPPORT) + virtual bool GetAtkStatus() = 0; + + Elm_Object_Item* first_item_ = nullptr; + Elm_Object_Item* selected_item_ = nullptr; +#endif + Evas_Object* evas_object_; Evas_Object* popup_list_; Evas_Object* layout_; diff --git a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.cc b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.cc index 55ae1ab..1d1d1a0 100644 --- a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.cc +++ b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.cc @@ -17,6 +17,12 @@ namespace { const char* const kChangedCbName = "changed"; +#if defined(TIZEN_ATK_SUPPORT) +const char* const kImagePrevBgObj = "elm.image.prev_bg"; +const char* const kImageNextBgObj = "elm.image.next_bg"; +const char* const kImageDoneBgObj = "elm.image.done_bg"; +#endif + void RadioIconChangedCallback(void* data, Evas_Object* obj, void* event_info) { auto callback_data = static_cast(data); callback_data->SetSelection(true); @@ -35,10 +41,98 @@ SelectPickerMobileBase::SelectPickerMobileBase(Evas_Object* evas_object, } SelectPickerMobileBase::~SelectPickerMobileBase() { +#if defined(TIZEN_ATK_SUPPORT) + RemoveAtkObject(); +#endif Hide(); DestroyRadioList(); } +#if defined(TIZEN_ATK_SUPPORT) +Eina_Bool SelectPickerMobileBase::AccessNavigateToPrevCallback( + void* data, + Evas_Object* obj, + Elm_Access_Action_Info* action_info) { + auto* picker = static_cast(data); + picker->FormNavigate(false); + return EINA_TRUE; +} + +Eina_Bool SelectPickerMobileBase::AccessNavigateToNextCallback( + void* data, + Evas_Object* obj, + Elm_Access_Action_Info* action_info) { + auto* picker = static_cast(data); + picker->FormNavigate(true); + return EINA_TRUE; +} + +Eina_Bool SelectPickerMobileBase::AccessDoneCallback( + void* data, + Evas_Object* obj, + Elm_Access_Action_Info* action_info) { + auto* picker = static_cast(data); + picker->HidePopupMenu(); + return EINA_TRUE; +} + +void SelectPickerMobileBase::AddAtkObject() { + auto* edje_obj = elm_layout_edje_get(layout_); + + prev_button_ = + (Evas_Object*)edje_object_part_object_get(edje_obj, kImagePrevBgObj); + ao_prev_button_ = elm_access_object_register(prev_button_, layout_); + elm_atspi_accessible_name_set( + ao_prev_button_, dgettext("WebKit", "IDS_WEBVIEW_BUTTON_PREV_ABB")); + elm_atspi_accessible_reading_info_type_set( + ao_prev_button_, ELM_ACCESSIBLE_READING_INFO_TYPE_NAME); + + next_button_ = + (Evas_Object*)edje_object_part_object_get(edje_obj, kImageNextBgObj); + ao_next_button_ = elm_access_object_register(next_button_, layout_); + elm_atspi_accessible_name_set( + ao_next_button_, dgettext("WebKit", "IDS_WEBVIEW_BUTTON_NEXT_ABB3")); + elm_atspi_accessible_reading_info_type_set( + ao_next_button_, ELM_ACCESSIBLE_READING_INFO_TYPE_NAME); + + done_button_ = + (Evas_Object*)edje_object_part_object_get(edje_obj, kImageDoneBgObj); + ao_done_button_ = elm_access_object_register(done_button_, layout_); + elm_atspi_accessible_name_set(ao_done_button_, + dgettext("WebKit", "IDS_WEBVIEW_BUTTON_DONE")); + elm_atspi_accessible_reading_info_type_set( + ao_done_button_, ELM_ACCESSIBLE_READING_INFO_TYPE_NAME); + + elm_access_action_cb_set(ao_prev_button_, ELM_ACCESS_ACTION_ACTIVATE, + AccessNavigateToPrevCallback, this); + elm_access_action_cb_set(ao_next_button_, ELM_ACCESS_ACTION_ACTIVATE, + AccessNavigateToNextCallback, this); + elm_access_action_cb_set(ao_done_button_, ELM_ACCESS_ACTION_ACTIVATE, + AccessDoneCallback, this); + + elm_atspi_accessible_relationship_append( + ao_done_button_, ELM_ATSPI_RELATION_FLOWS_TO, first_item_); + elm_atspi_accessible_relationship_append( + first_item_, ELM_ATSPI_RELATION_FLOWS_FROM, ao_done_button_); +} + +void SelectPickerMobileBase::RemoveAtkObject() { + if (ao_done_button_) { + elm_atspi_accessible_relationship_remove( + ao_done_button_, ELM_ATSPI_RELATION_FLOWS_TO, first_item_); + elm_atspi_accessible_relationship_remove( + first_item_, ELM_ATSPI_RELATION_FLOWS_FROM, ao_done_button_); + } + + if (prev_button_) + elm_access_object_unregister(prev_button_); + if (next_button_) + elm_access_object_unregister(next_button_); + if (done_button_) + elm_access_object_unregister(done_button_); +} +#endif + void SelectPickerMobileBase::Init(std::vector items, const gfx::Rect& bounds) { // Request form navigation information as early as possible, @@ -107,6 +201,10 @@ void SelectPickerMobileBase::ItemSelected(GenlistCallbackData* data, selected_index_ = data->GetIndex(); DidSelectPopupMenuItem(); } +#if defined(TIZEN_ATK_SUPPORT) + if (GetAtkStatus()) + HidePopupMenu(); +#endif } void SelectPickerMobileBase::CreateAndPopulatePopupList( @@ -120,8 +218,13 @@ void SelectPickerMobileBase::CreateAndPopulatePopupList( elm_object_focus_allow_set(popup_list_, false); +#if defined(TIZEN_ATK_SUPPORT) + if (GetAtkStatus()) + item_class_->func.content_get = nullptr; +#else item_class_->func.content_get = is_multiple_selection_ ? nullptr : IconGetCallback; +#endif elm_genlist_multi_select_set(popup_list_, is_multiple_selection_); @@ -147,6 +250,9 @@ void SelectPickerMobileBase::CreateAndPopulatePopupList( } elm_object_part_content_set(layout_, "elm.swallow.content", popup_list_); +#if defined(TIZEN_ATK_SUPPORT) + AddAtkObject(); +#endif } gfx::Rect SelectPickerMobileBase::GetGeometryDIP() const { diff --git a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.h b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.h index a60b360..5f67184 100644 --- a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.h +++ b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_mobile_base.h @@ -33,6 +33,30 @@ class SelectPickerMobileBase : public FormNavigablePicker { void DestroyRadioList(); +#if defined(TIZEN_ATK_SUPPORT) + void AddAtkObject(); + void RemoveAtkObject(); + + static Eina_Bool AccessNavigateToPrevCallback( + void* data, + Evas_Object* obj, + Elm_Access_Action_Info* action_info); + static Eina_Bool AccessNavigateToNextCallback( + void* data, + Evas_Object* obj, + Elm_Access_Action_Info* action_info); + static Eina_Bool AccessDoneCallback(void* data, + Evas_Object* obj, + Elm_Access_Action_Info* action_info); + + Evas_Object* prev_button_ = nullptr; + Evas_Object* next_button_ = nullptr; + Evas_Object* done_button_ = nullptr; + Evas_Object* ao_prev_button_ = nullptr; + Evas_Object* ao_next_button_ = nullptr; + Evas_Object* ao_done_button_ = nullptr; +#endif + Evas_Object* radio_main_; }; diff --git a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_tv_base.cc b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_tv_base.cc index 1422a45..219b5aa 100644 --- a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_tv_base.cc +++ b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_tv_base.cc @@ -50,6 +50,9 @@ void SelectPickerTvBase::CreateAndPopulatePopupList( item_class_->func.content_get = nullptr; elm_genlist_multi_select_set(popup_list_, is_multiple_selection_); InitializeSelectedPickerData(std::move(items)); +#if defined(TIZEN_ATK_SUPPORT) + elm_genlist_item_selected_set(selected_item_, EINA_TRUE); +#endif elm_object_part_content_set(layout_, "elm.swallow.content", popup_list_); elm_object_scale_set(popup_list_, kBoxRatio); } diff --git a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.cc b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.cc index 5cc09fa..993d88a 100644 --- a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.cc +++ b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.cc @@ -14,10 +14,20 @@ GenlistCallbackData::GenlistCallbackData( const Elm_Genlist_Item_Class* item_class, const Elm_Genlist_Item_Class* group_class, bool is_multiple_selection, - Evas_Smart_Cb item_selected_cb) + Evas_Smart_Cb item_selected_cb +#if defined(TIZEN_ATK_SUPPORT) + , + bool atk_enabled +#endif + ) : index_(index), select_picker_(select_picker), - menu_item_(std::move(menu_item)) { + menu_item_(std::move(menu_item)) +#if defined(TIZEN_ATK_SUPPORT) + , + atk_enabled_(atk_enabled) +#endif +{ bool is_option_type = (menu_item_->type == blink::mojom::MenuItem::Type::kOption); elm_item_ = elm_genlist_item_append( @@ -33,7 +43,13 @@ GenlistCallbackData::GenlistCallbackData( } GenlistCallbackData::~GenlistCallbackData() { +#if defined(TIZEN_ATK_SUPPORT) + // TODO(bj1987.kim): This code prevents the elm_genlist from crashing + // when ATK is turned on. After fixing genlist crash, need to remove. + if (!atk_enabled_ && elm_item_) +#else if (elm_item_) +#endif elm_object_item_del(elm_item_); } @@ -53,6 +69,12 @@ const std::string& GenlistCallbackData::GetLabel() const { return menu_item_->label.value(); } +#if defined(TIZEN_ATK_SUPPORT) +Elm_Object_Item* GenlistCallbackData::GetElmItem() const { + return elm_item_; +} +#endif + SelectPickerBase* GenlistCallbackData::GetSelectPicker() const { return select_picker_; } diff --git a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.h b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.h index 77ad829..4592c76 100644 --- a/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.h +++ b/tizen_src/chromium_impl/content/browser/select_picker/select_picker_util.h @@ -20,7 +20,12 @@ class GenlistCallbackData { const Elm_Genlist_Item_Class* item_class, const Elm_Genlist_Item_Class* group_class, bool is_multiple_selection, - Evas_Smart_Cb item_selected_cb); + Evas_Smart_Cb item_selected_cb +#if defined(TIZEN_ATK_SUPPORT) + , + bool atk_enabled +#endif + ); ~GenlistCallbackData(); GenlistCallbackData(const GenlistCallbackData&) = delete; @@ -30,6 +35,9 @@ class GenlistCallbackData { void ScrollToTop(); int GetIndex() const; const std::string& GetLabel() const; +#if defined(TIZEN_ATK_SUPPORT) + Elm_Object_Item* GetElmItem() const; +#endif SelectPickerBase* GetSelectPicker() const; bool IsEnabled() const; @@ -38,6 +46,9 @@ class GenlistCallbackData { SelectPickerBase* select_picker_; Elm_Object_Item* elm_item_; blink::mojom::MenuItemPtr menu_item_; +#if defined(TIZEN_ATK_SUPPORT) + bool atk_enabled_; +#endif }; #endif // CONTENT_BROWSER_SELECT_PICKER_SELECT_PICKER_UTIL_H_ diff --git a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.cc b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.cc index 4b507f0..a8ef5c3 100644 --- a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.cc +++ b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.cc @@ -43,3 +43,9 @@ void SelectPickerMobile::RequestFormNavigationInformation() { rfh->Send( new EwkFrameMsg_RequestSelectCollectionInformation(rfh->GetRoutingID())); } + +#if defined(TIZEN_ATK_SUPPORT) +bool SelectPickerMobile::GetAtkStatus() { + return web_view_->GetAtkStatus(); +} +#endif diff --git a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.h b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.h index 96a3c38..29a38f8 100644 --- a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.h +++ b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_mobile.h @@ -28,6 +28,10 @@ class SelectPickerMobile : public SelectPickerMobileBase { // SelectPickerBase content::WebContentsViewAura* wcva() const override; +#if defined(TIZEN_ATK_SUPPORT) + bool GetAtkStatus() override; +#endif + EWebView* web_view_; }; diff --git a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.cc b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.cc index 70fd877..7227569 100644 --- a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.cc +++ b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.cc @@ -47,3 +47,9 @@ void SelectPickerTv::RequestFormNavigationInformation() { void SelectPickerTv::HidePopupMenu() { web_view_->HidePopupMenu(); } + +#if defined(TIZEN_ATK_SUPPORT) +bool SelectPickerTv::GetAtkStatus() { + return web_view_->GetAtkStatus(); +} +#endif diff --git a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.h b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.h index a9f1ad1..0ab05f7 100644 --- a/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.h +++ b/tizen_src/ewk/efl_integration/browser/select_picker/select_picker_tv.h @@ -28,6 +28,10 @@ class SelectPickerTv : public SelectPickerTvBase { // SelectPickerBase content::WebContentsViewAura* wcva() const override; +#if defined(TIZEN_ATK_SUPPORT) + bool GetAtkStatus() override; +#endif + EWebView* web_view_; }; -- 2.7.4