From bc2ea117e0f8c78fe1d7d3b78dde2404e3b4462a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Artur=20=C5=9Awigo=C5=84?= Date: Fri, 25 Nov 2022 11:13:41 +0100 Subject: [PATCH] [Tizen][AT-SPI] Associate default labels with windows Change-Id: I575f9be4d518c7b03d8bfa2419a6d1961585d5d6 (cherry picked from commit 6f1168bbac355dbd3c082d76559d68f522469172) --- dali/internal/accessibility/bridge/bridge-base.cpp | 75 +++++++++++++++++++--- dali/internal/accessibility/bridge/bridge-base.h | 24 ++++++- 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/dali/internal/accessibility/bridge/bridge-base.cpp b/dali/internal/accessibility/bridge/bridge-base.cpp index 4509694..a819f25 100644 --- a/dali/internal/accessibility/bridge/bridge-base.cpp +++ b/dali/internal/accessibility/bridge/bridge-base.cpp @@ -25,6 +25,7 @@ #include // INTERNAL INCLUDES +#include #include using namespace Dali::Accessibility; @@ -227,28 +228,68 @@ void BridgeBase::RemoveTopLevelWindow(Accessible* windowAccessible) } } +void BridgeBase::CompressDefaultLabels() +{ + // Remove entries for objects which no longer exist + mDefaultLabels.remove_if([](const DefaultLabelType& label) { + return !label.first.GetBaseHandle(); // Check window's weak handle + // TODO: Once Accessible becomes a handle type, check its weak handle here as well + }); +} + void BridgeBase::RegisterDefaultLabel(Accessible* object) { - if(std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object) == mDefaultLabels.end()) + CompressDefaultLabels(); + + Dali::WeakHandle window = GetWindow(object); + if(!window.GetBaseHandle()) // true also if `object` is null + { + DALI_LOG_ERROR("Cannot register default label: object does not belong to any window"); + return; + } + + auto it = std::find_if(mDefaultLabels.begin(), mDefaultLabels.end(), [object](const DefaultLabelType& label) { + return object == label.second; + }); + + if(it == mDefaultLabels.end()) + { + mDefaultLabels.push_back({window, object}); + } + else if(it->first != window) + { + // TODO: Tentative implementation. It is yet to be specified what should happen + // when the same object is re-registered as a default label for another window. + *it = {window, object}; + } + else // it->first == window && it->second == object { - mDefaultLabels.push_back(object); + // Nothing to do } } void BridgeBase::UnregisterDefaultLabel(Accessible* object) { - auto it = std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object); - if(it != mDefaultLabels.end()) - { - mDefaultLabels.erase(it); - } + CompressDefaultLabels(); + + mDefaultLabels.remove_if([object](const DefaultLabelType& label) { + return object == label.second; + }); } Accessible* BridgeBase::GetDefaultLabel(Accessible* root) const { - // TODO (multi-window support): Change mDefaultLabels to a collection of vectors - // (one per window) and select the right one based on the window that 'root' belongs to. - return mDefaultLabels.empty() ? root : mDefaultLabels.back(); + Dali::WeakHandle window = GetWindow(root); + if(!window.GetBaseHandle()) + { + return root; + } + + auto it = std::find_if(mDefaultLabels.rbegin(), mDefaultLabels.rend(), [&window](const DefaultLabelType& label) { + return window == label.first; + }); + + return (it == mDefaultLabels.rend()) ? root : it->second; } std::string BridgeBase::StripPrefix(const std::string& path) @@ -360,3 +401,17 @@ auto BridgeBase::CreateCacheElement(Accessible* item) -> CacheElementType item->GetDescription(), item->GetStates().GetRawData()); } + +Dali::WeakHandle BridgeBase::GetWindow(Dali::Accessibility::Accessible* accessible) +{ + Dali::WeakHandle windowHandle; + Dali::Actor actor = accessible ? accessible->GetInternalActor() : Dali::Actor(); + + if(actor) + { + Dali::Window window = Dali::DevelWindow::Get(actor); + windowHandle = {window}; + } + + return windowHandle; +} diff --git a/dali/internal/accessibility/bridge/bridge-base.h b/dali/internal/accessibility/bridge/bridge-base.h index 35e9e66..60fbb44 100644 --- a/dali/internal/accessibility/bridge/bridge-base.h +++ b/dali/internal/accessibility/bridge/bridge-base.h @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include #include #include #include @@ -611,9 +612,13 @@ public: } protected: - mutable ApplicationAccessible mApplication; - std::vector mDefaultLabels; - bool mIsScreenReaderSuppressed = false; + // We use a weak handle in order not to keep a window alive forever if someone forgets to UnregisterDefaultLabel() + using DefaultLabelType = std::pair, Dali::Accessibility::Accessible*>; + using DefaultLabelsType = std::list; + + mutable ApplicationAccessible mApplication; + DefaultLabelsType mDefaultLabels; + bool mIsScreenReaderSuppressed = false; private: /** @@ -663,6 +668,19 @@ private: */ CacheElementType CreateCacheElement(Dali::Accessibility::Accessible* item); + /** + * @brief Removes expired elements from the default label collection. + */ + void CompressDefaultLabels(); + + /** + * @brief Gets the window to which this accessible belongs (or an empty handle). + * + * @param accessible The accessible + * @return The window + */ + static Dali::WeakHandle GetWindow(Dali::Accessibility::Accessible* accessible); + protected: BridgeBase(); virtual ~BridgeBase(); -- 2.7.4