diff options
author | Igor Olshevskyi <i.olshevskyi@samsung.com> | 2017-08-09 12:01:34 +0300 |
---|---|---|
committer | Igor Olshevskyi <i.olshevskyi@samsung.com> | 2017-08-11 17:14:01 +0300 |
commit | 1085f5ad876240377c36a5fa78ec1d840673380f (patch) | |
tree | 59550b81e64ba0fca9ccf58efc5686680dd7799a | |
parent | 7df53dad9dd42453662f08fa381e2ee953f7e662 (diff) | |
download | call-ui-1085f5ad876240377c36a5fa78ec1d840673380f.tar.gz call-ui-1085f5ad876240377c36a5fa78ec1d840673380f.tar.bz2 call-ui-1085f5ad876240377c36a5fa78ec1d840673380f.zip |
TizenRefApp-9083 [Call UI] Implement Screen Reader highlight logic for KeypadPage
Change-Id: Ib8143cab96a0111dfd6f9b96bf282b22df9fb1e0
-rw-r--r-- | inc/presenters/KeypadPage.h | 16 | ||||
-rw-r--r-- | project_def.prop | 2 | ||||
-rw-r--r-- | src/presenters/AccessoryPresenter.cpp | 6 | ||||
-rw-r--r-- | src/presenters/KeypadPage.cpp | 217 | ||||
-rw-r--r-- | src/view/common.h | 1 |
5 files changed, 205 insertions, 37 deletions
diff --git a/inc/presenters/KeypadPage.h b/inc/presenters/KeypadPage.h index 027ce64..2ca6a1b 100644 --- a/inc/presenters/KeypadPage.h +++ b/inc/presenters/KeypadPage.h @@ -79,6 +79,19 @@ namespace callui { void registerCallbacks(); void unregisterCallbacks(); + // Screen Reader + ucl::Result createAtspiHighlightHelper(); + Elm_Interface_Atspi_Accessible *onAtspiHighlight( + Elm_Interface_Atspi_Accessible *ao, + Elm_Atspi_Relation_Type flowRelation); + ucl::ElmWidget *getFirstButton(); + ucl::ElmWidget *getLastButton(); + void registerVolumeControlAo(); + void onVolumeControlScreenReaderReadStart( + ucl::Widget &widget, + void *eventInfo); + + // Page virtual void onBackKey() override final; @@ -94,6 +107,9 @@ namespace callui { Ecore_Timer *m_vcTimer; AudioStateType m_audioState; + + // Screen Reader + AtspiHighlightHelperSRef m_atspiHelper; }; } diff --git a/project_def.prop b/project_def.prop index 1fe3c17..7bc0ea9 100644 --- a/project_def.prop +++ b/project_def.prop @@ -9,7 +9,7 @@ type = app profile = wearable-4.0 # C/CPP Sources -USER_SRCS = ucl/src/gui/WidgetItem.cpp src/presenters/InstanceManager.cpp ucl/src/appfw/UIApp.cpp src/model/VoiceControlStateProvider.cpp src/presenters/AcceptDialog.cpp ucl/src/gui/NaviItem.cpp ucl/src/gui/Layout.cpp src/model/IncomingCall.cpp src/presenters/Page.cpp src/resources.cpp src/presenters/DeviceStatePresenter.cpp src/model/ContactInfoProvider.cpp ucl/src/gui/Genlist.cpp ucl/src/gui/Window.cpp src/types.cpp src/presenters/RejectMsgPresenter.cpp src/model/ConnectionStateSource.cpp src/presenters/AccessoryPresenter.cpp src/model/ContactInfo.cpp src/model/EndCall.cpp src/presenters/MainPage.cpp src/view/helpers.cpp ucl/src/mvp/ListItemPresenter.cpp ucl/src/util/types/Result.cpp ucl/src/mvp/ListPresenter.cpp ucl/src/misc/Variant.cpp src/model/CallUI.cpp ucl/src/mvp/GuiPresenter.cpp src/view/VolumeControl.cpp src/view/Slider.cpp src/model/CallInfo.cpp ucl/src/gui/ElmWidget.cpp src/model/SimSlotStateSource.cpp src/presenters/AcceptRejectPresenter.cpp ucl/src/gui/EdjeWidget.cpp ucl/src/gui/Naviframe.cpp src/model/CallManager.cpp ucl/src/misc/Timeout.cpp src/presenters/Instance.cpp ucl/src/gui/Widget.cpp src/model/ActiveCall.cpp src/model/RejectMsgProvider.cpp src/presenters/MoreOptionsPresenter.cpp ucl/src/appfw/SysEventProvider.cpp src/presenters/CallInfoPresenter.cpp src/model/BatteryStateSource.cpp src/model/CallClient.cpp src/model/VoiceControlStateSource.cpp src/model/RssiStateSource.cpp src/model/HdVoiceStateSource.cpp ucl/src/util/logging.cpp src/model/IndicatorStateProvider.cpp src/presenters/KeypadPage.cpp src/presenters/helpers.cpp src/presenters/MotionSensorPresenter.cpp src/main.cpp src/model/MsgClient.cpp src/presenters/IndicatorPresenter.cpp ucl/src/appfw/helpers.cpp src/model/CallUIBuilder.cpp src/presenters/CallStatusPresenter.cpp src/model/ConferenceCallInfo.cpp src/model/HeldCall.cpp src/model/SoundManager.cpp src/model/BluetoothManager.cpp src/model/RejectMsg.cpp src/view/AcceptRejectWidget.cpp ucl/src/appfw/InstanceManagerBase.cpp +USER_SRCS = ucl/src/gui/WidgetItem.cpp src/presenters/InstanceManager.cpp ucl/src/appfw/UIApp.cpp src/model/VoiceControlStateProvider.cpp src/presenters/AcceptDialog.cpp ucl/src/gui/NaviItem.cpp ucl/src/gui/Layout.cpp src/model/IncomingCall.cpp src/presenters/Page.cpp src/resources.cpp src/presenters/DeviceStatePresenter.cpp src/model/ContactInfoProvider.cpp ucl/src/gui/Genlist.cpp ucl/src/gui/Window.cpp src/types.cpp src/presenters/RejectMsgPresenter.cpp src/model/ConnectionStateSource.cpp src/presenters/AccessoryPresenter.cpp src/model/ContactInfo.cpp src/model/EndCall.cpp src/presenters/MainPage.cpp src/view/helpers.cpp ucl/src/mvp/ListItemPresenter.cpp ucl/src/util/types/Result.cpp ucl/src/mvp/ListPresenter.cpp ucl/src/misc/Variant.cpp src/model/CallUI.cpp ucl/src/mvp/GuiPresenter.cpp src/view/VolumeControl.cpp src/view/Slider.cpp src/model/CallInfo.cpp ucl/src/gui/ElmWidget.cpp src/model/SimSlotStateSource.cpp src/presenters/AcceptRejectPresenter.cpp ucl/src/gui/EdjeWidget.cpp ucl/src/gui/Naviframe.cpp src/model/CallManager.cpp ucl/src/misc/Timeout.cpp src/presenters/Instance.cpp ucl/src/gui/Widget.cpp src/model/ActiveCall.cpp src/model/RejectMsgProvider.cpp src/presenters/MoreOptionsPresenter.cpp ucl/src/appfw/SysEventProvider.cpp src/presenters/CallInfoPresenter.cpp src/model/BatteryStateSource.cpp src/model/CallClient.cpp src/model/VoiceControlStateSource.cpp src/model/RssiStateSource.cpp src/model/HdVoiceStateSource.cpp ucl/src/util/logging.cpp src/model/IndicatorStateProvider.cpp src/presenters/KeypadPage.cpp src/presenters/helpers.cpp src/presenters/MotionSensorPresenter.cpp src/main.cpp src/model/MsgClient.cpp src/presenters/IndicatorPresenter.cpp ucl/src/appfw/helpers.cpp src/model/CallUIBuilder.cpp src/presenters/AtspiHighlightHelper.cpp src/presenters/CallStatusPresenter.cpp src/model/ConferenceCallInfo.cpp src/model/HeldCall.cpp src/model/SoundManager.cpp src/model/BluetoothManager.cpp src/model/RejectMsg.cpp src/view/AcceptRejectWidget.cpp ucl/src/appfw/InstanceManagerBase.cpp # EDC Sources USER_EDCS = diff --git a/src/presenters/AccessoryPresenter.cpp b/src/presenters/AccessoryPresenter.cpp index 1774f0f..7e15a90 100644 --- a/src/presenters/AccessoryPresenter.cpp +++ b/src/presenters/AccessoryPresenter.cpp @@ -51,8 +51,6 @@ namespace callui { namespace { namespace impl { constexpr EdjeSignal SIGNAL_TURN_ON {"turn.on"}; constexpr EdjeSignal SIGNAL_TURN_OFF {"turn.off"}; - - constexpr SmartEvent EVENT_ACCESS_READ_START {"access,read,start"}; }}} namespace callui { @@ -806,7 +804,7 @@ namespace callui { { auto decrBtn = m_vc->getDecreaseBtn(); if (decrBtn) { - decrBtn->addEventHandler(impl::EVENT_ACCESS_READ_START, + decrBtn->addEventHandler(ATSPI_HIGHLIGHTED, WEAK_DELEGATE(AccessoryPresenter:: onVolumeControlScreenReaderReadStart, asWeak(*this))); @@ -814,7 +812,7 @@ namespace callui { auto incrBtn = m_vc->getIncreaseBtn(); if (incrBtn) { - incrBtn->addEventHandler(impl::EVENT_ACCESS_READ_START, + incrBtn->addEventHandler(ATSPI_HIGHLIGHTED, WEAK_DELEGATE(AccessoryPresenter:: onVolumeControlScreenReaderReadStart, asWeak(*this))); diff --git a/src/presenters/KeypadPage.cpp b/src/presenters/KeypadPage.cpp index d2f512f..04f0ebe 100644 --- a/src/presenters/KeypadPage.cpp +++ b/src/presenters/KeypadPage.cpp @@ -17,6 +17,8 @@ #include "presenters/KeypadPage.h" #include "view/VolumeControl.h" +#include "presenters/AtspiHighlightHelper.h" + #include "resources.h" #include "common.h" @@ -156,59 +158,64 @@ namespace callui { unregisterCallbacks(); } + Result KeypadPage::doPrepare(NaviItem &item) + { + FAIL_RETURN(createWidget(), "createWidget() failed!"); + + FAIL_RETURN(createEntry(), "createEntry() failed!"); + + FAIL_RETURN(createButtons(), "createButtons() failed!"); + + FAIL_RETURN(createVolumeControl(), "createVolumeControl() failed!"); + + registerCallbacks(); + + updateVolume(m_sm->getVolume()); + + FAIL_RETURN(createAtspiHighlightHelper(), + "createAtspiHighlightHelper() failed!"); + + item = getNaviframe().push(*m_widget); + if (!item) { + LOG_RETURN(RES_FAIL, "Naviframe::push() failed!"); + } + + return RES_OK; + } + void KeypadPage::onBtnPressed(Widget &widget, void *eventInfo) { - impl::ButtonInfo *btn = + impl::ButtonInfo *info = static_cast<impl::ButtonInfo*>(widget.getData(impl::BTN_DATA_KEY)); - ILOG("button pressed: %c", *(btn->str)); + DLOG("Button pressed [%c]", *(info->str)); - if (btn->type == impl::OperationType::DTMF) { - elm_entry_entry_append(*m_entry, btn->str); + if (info->type == impl::OperationType::DTMF) { + elm_entry_entry_append(*m_entry, info->str); elm_entry_cursor_end_set(*m_entry); - startDtmf(*(btn->str)); + startDtmf(*(info->str)); } } void KeypadPage::onBtnUnpressed(Widget &widget, void *eventInfo) { - impl::ButtonInfo *btn = + impl::ButtonInfo *info = static_cast<impl::ButtonInfo*>(widget.getData(impl::BTN_DATA_KEY)); - ILOG("button unpressed: %c", *(btn->str)); + DLOG("Button unpressed [%c]", *(info->str)); stopDtmf(); } void KeypadPage::onBtnClicked(Widget &widget, void *eventInfo) { - impl::ButtonInfo *btn = + impl::ButtonInfo *info = static_cast<impl::ButtonInfo*>(widget.getData(impl::BTN_DATA_KEY)); - if(btn->type == impl::OperationType::VOLUME) { - ILOG("button clicked: volume"); + if(info->type == impl::OperationType::VOLUME) { + DLOG("Button clicked [volume]"); show(*m_vc); startVCTimer(); - } - } - - Result KeypadPage::doPrepare(NaviItem &item) - { - FAIL_RETURN(createWidget(), "createWidget() failed!"); - - FAIL_RETURN(createEntry(), "createEntry() failed!"); - - FAIL_RETURN(createButtons(), "createButtons() failed!"); - - FAIL_RETURN(createVolumeControl(), "createVolumeControl() failed!"); - registerCallbacks(); - - updateVolume(m_sm->getVolume()); - - item = getNaviframe().push(*m_widget); - if (!item) { - LOG_RETURN(RES_FAIL, "Naviframe::push() failed!"); + elm_atspi_component_highlight_grab(*m_vc); } - - return RES_OK; } Result KeypadPage::createWidget() @@ -222,6 +229,8 @@ namespace callui { LOG_RETURN(RES_FAIL, "Layout::build() failed!"); } + setDeactivatorSink(m_widget); + return RES_OK; } @@ -263,6 +272,7 @@ namespace callui { } buttonSRef = makeShared<StyledWidget>(button); + buttonSRef->bindToEo(); buttonSRef->setData(impl::BTN_DATA_KEY, &(impl::buttonsInfo[i])); buttonSRef->setStyle(impl::buttonsInfo[i].style); @@ -280,6 +290,22 @@ namespace callui { asWeak(*this))); } + // Screen Reader + elm_atspi_accessible_name_cb_set(*buttonSRef, + [](void *data, Evas_Object *obj) -> char * + { + impl::ButtonInfo *info = + static_cast<impl::ButtonInfo*>(asWidget(obj)-> + getData(impl::BTN_DATA_KEY)); + if (info->type == impl::OperationType::DTMF) { + return strdup(info->str); + } else { + return strdup(AO_STR_VOLUME.translate()); + } + return nullptr; + }, + this); + m_widget->setContent(button, impl::buttonsInfo[i].swlPart); show(*buttonSRef); } @@ -326,6 +352,8 @@ namespace callui { m_vc->resize(w, h); hide(*m_vc); + registerVolumeControlAo(); + return RES_OK; } @@ -381,6 +409,12 @@ namespace callui { m_vc->setIncreaseBtnEnable(true); m_vc->setDecreaseBtnEnable(true); } + + // Screen Reader + if (m_vc->isVisible()) { + elm_atspi_bridge_utils_say(std::to_string(cur).c_str(), + EINA_FALSE, nullptr, nullptr); + } } void KeypadPage::onAudioStateChanged(AudioStateType state) @@ -417,7 +451,12 @@ namespace callui { { stopVCTimer(); - m_vcTimer = ecore_timer_add(CALL_VC_TIMER_INTERVAL, + auto timerInterval = CALL_VC_TIMER_INTERVAL; + if (elm_atspi_bridge_utils_is_screen_reader_enabled()) { + timerInterval = CALL_VC_SCREEN_READER_TIMER_INTERVAL; + } + + m_vcTimer = ecore_timer_add(timerInterval, CALLBACK_B(KeypadPage::onVCTimerCb), this); } @@ -503,4 +542,118 @@ namespace callui { m_sm->delVolumeStateHandler(DELEGATE( KeypadPage::onVolumeLevelChanged, this)); } + + // Screen Reader + Result KeypadPage::createAtspiHighlightHelper() + { + m_atspiHelper = AtspiHighlightHelper::newInstance(*this, getWindow()); + if (!m_atspiHelper) { + LOG_RETURN(RES_FAIL, + "AtspiHighlightHelper::newInstance() failed!"); + } + + m_atspiHelper->setRelationEventHandler(WEAK_DELEGATE( + KeypadPage::onAtspiHighlight, asWeak(*this))); + + m_atspiHelper->registerWidget(*getFirstButton()); + m_atspiHelper->registerWidget(*getLastButton()); + m_atspiHelper->registerWidget(*m_vc.get()); + m_atspiHelper->registerWidget(*m_vc->getDecreaseBtn()); + m_atspiHelper->registerWidget(*m_vc->getIncreaseBtn()); + m_atspiHelper->registerWidget(*m_vc->getValueTxtAo()); + + return RES_OK; + } + + Elm_Interface_Atspi_Accessible *KeypadPage::onAtspiHighlight( + Elm_Interface_Atspi_Accessible *ao, + Elm_Atspi_Relation_Type flowRelation) + { + DLOG("FlowRelation [%s]", + flowRelation == ELM_ATSPI_RELATION_FLOWS_FROM ? + "FROM" : "TO"); + + auto firstBtn = getFirstButton(); + auto lastBtn = getLastButton(); + auto vcLayout = m_vc.get(); + auto vcDecrVolumeBtn = m_vc->getDecreaseBtn(); + auto vcIncrVolumeBtn = m_vc->getIncreaseBtn(); + auto vcVolumeValueAo = m_vc->getValueTxtAo(); + + if (ao == *firstBtn) { + if (flowRelation == ELM_ATSPI_RELATION_FLOWS_TO) { + return nullptr; + } + } else if (ao == *lastBtn) { + if (flowRelation == ELM_ATSPI_RELATION_FLOWS_FROM) { + return nullptr; + } + } else if (ao == *vcLayout) { + if (flowRelation == ELM_ATSPI_RELATION_FLOWS_TO) { + return *vcDecrVolumeBtn; + } + } else if (ao == *vcDecrVolumeBtn) { + if (flowRelation == ELM_ATSPI_RELATION_FLOWS_TO) { + return *vcVolumeValueAo; + } else { + return *vcLayout; + } + } else if (ao == *vcVolumeValueAo) { + if (flowRelation == ELM_ATSPI_RELATION_FLOWS_TO) { + return *vcIncrVolumeBtn; + } else { + return *vcDecrVolumeBtn; + } + } else if (ao == *vcIncrVolumeBtn) { + if (flowRelation == ELM_ATSPI_RELATION_FLOWS_FROM) { + return *vcVolumeValueAo; + } + } else if (ao == getWindow()) { + return *firstBtn; + } else { + LOG_RETURN_VALUE(RES_FAIL, nullptr, "Unknown object!"); + } + + return ao; + } + + ElmWidget *KeypadPage::getFirstButton() + { + return dynamicWidgetCast<ElmWidget>( + m_widget->getContent(impl::buttonsInfo[0].swlPart)); + } + + ElmWidget *KeypadPage::getLastButton() + { + return dynamicWidgetCast<ElmWidget>( + m_widget->getContent(impl::buttonsInfo[( + impl::KEYPAD_BTN_MAX_COUNT - 1)].swlPart)); + } + + void KeypadPage::registerVolumeControlAo() + { + auto decrBtn = m_vc->getDecreaseBtn(); + + if (decrBtn) { + decrBtn->addEventHandler(ATSPI_HIGHLIGHTED, + WEAK_DELEGATE(KeypadPage:: + onVolumeControlScreenReaderReadStart, + asWeak(*this))); + } + + auto incrBtn = m_vc->getIncreaseBtn(); + if (incrBtn) { + incrBtn->addEventHandler(ATSPI_HIGHLIGHTED, + WEAK_DELEGATE(KeypadPage:: + onVolumeControlScreenReaderReadStart, + asWeak(*this))); + } + } + + void KeypadPage::onVolumeControlScreenReaderReadStart( + Widget &widget, + void *eventInfo) + { + restartVCTimer(); + } } diff --git a/src/view/common.h b/src/view/common.h index 6e6cd0b..7c795fe 100644 --- a/src/view/common.h +++ b/src/view/common.h @@ -36,6 +36,7 @@ namespace callui { constexpr ucl::SmartEvent BTN_CLICKED {"clicked"}; + constexpr ucl::SmartEvent ATSPI_HIGHLIGHTED {"atspi,highlighted"}; } #endif // __CALLUI_VIEW_COMMON_H__ |