From 3174f045709a1016f13e65106b12a998be69d67e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Artur=20=C5=9Awigo=C5=84?= Date: Thu, 28 Mar 2024 13:02:06 +0100 Subject: [PATCH] [Tizen][AT-SPI] Move AccessibilityAttributes to Accessible This patch allows setting arbitrary attributes on the Accessible level. Previously this was only possible for Control, and thus application-side customization of the attributes was unavailable for some other classes (most notably Layer, which stands in for Window in the AT-SPI tree). Change-Id: Iccdf65eb0b078f1962b31fbf3f6091d7e7d3f07d --- dali/devel-api/adaptor-framework/accessibility.cpp | 91 +++++++++++++++++++--- .../adaptor-framework/actor-accessible.cpp | 18 +++++ .../devel-api/adaptor-framework/actor-accessible.h | 5 ++ .../devel-api/adaptor-framework/proxy-accessible.h | 5 -- dali/devel-api/atspi-interfaces/accessible.h | 84 +++++++++++++++++++- dali/internal/accessibility/bridge/bridge-base.h | 5 -- 6 files changed, 186 insertions(+), 22 deletions(-) diff --git a/dali/devel-api/adaptor-framework/accessibility.cpp b/dali/devel-api/adaptor-framework/accessibility.cpp index 804ed61..5c5d1ce 100644 --- a/dali/devel-api/adaptor-framework/accessibility.cpp +++ b/dali/devel-api/adaptor-framework/accessibility.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include // INTERNAL INCLUDES @@ -197,6 +198,79 @@ std::string Accessible::GetRoleName() const return std::string{it->second}; } +void Accessible::UpdateAttributes(Attributes& attributes) const +{ + using MapType = std::map; + + static const std::string readingInfoTypeKey = "reading_info_type"; + static const char separator = '|'; + static const MapType readingInfoTypeMap{ + {ReadingInfoType::NAME, "name"}, + {ReadingInfoType::ROLE, "role"}, + {ReadingInfoType::DESCRIPTION, "description"}, + {ReadingInfoType::STATE, "state"}, + }; + + bool allEnabled = mReadingInfoTypes[ReadingInfoType::NAME] + && mReadingInfoTypes[ReadingInfoType::ROLE] + && mReadingInfoTypes[ReadingInfoType::DESCRIPTION] + && mReadingInfoTypes[ReadingInfoType::STATE]; + + if(DALI_LIKELY(allEnabled)) + { + attributes.erase(readingInfoTypeKey); + return; + } + + std::stringstream buf; + for(auto& item : readingInfoTypeMap) + { + if(mReadingInfoTypes[item.first]) + { + if(buf.tellp()) // non-empty + { + buf << separator; + } + + buf << item.second; + } + } + + attributes.insert_or_assign(readingInfoTypeKey, buf.str()); +} + +const Attributes& Accessible::GetAttributes() const +{ + UpdateAttributes(mAttributes); + + return mAttributes; +} + +bool Accessible::SetAttribute(const std::string& key, const std::string& value) +{ + return mAttributes.insert_or_assign(key, value).second; +} + +bool Accessible::UnsetAttribute(const std::string& key) +{ + return (mAttributes.erase(key) > 0); +} + +void Accessible::ClearAttributes() +{ + mAttributes.clear(); +} + +ReadingInfoTypes Accessible::GetReadingInfoTypes() const +{ + return mReadingInfoTypes; +} + +void Accessible::SetReadingInfoTypes(ReadingInfoTypes types) +{ + mReadingInfoTypes = types; +} + AtspiInterfaces Accessible::GetInterfaces() const { if(!mInterfaces) @@ -459,22 +533,19 @@ public: return state; } - Attributes GetAttributes() const override + void UpdateAttributes(Attributes& attributes) const override { - Attributes attributes; + static const std::string resIDKey = "resID"; - if(mRoot) + ActorAccessible::UpdateAttributes(attributes); + + if(mRoot && attributes.find(resIDKey) == attributes.end()) { Dali::Window window = Dali::DevelWindow::Get(Self()); Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window); - attributes["resID"] = windowImpl.GetNativeResourceId(); - } - Dali::TypeInfo type; - Self().GetTypeInfo(type); - attributes["class"] = type.GetName(); - - return attributes; + attributes.emplace(resIDKey, windowImpl.GetNativeResourceId()); + } } bool DoGesture(const GestureInfo& gestureInfo) override diff --git a/dali/devel-api/adaptor-framework/actor-accessible.cpp b/dali/devel-api/adaptor-framework/actor-accessible.cpp index 6f940a7..56125f2 100644 --- a/dali/devel-api/adaptor-framework/actor-accessible.cpp +++ b/dali/devel-api/adaptor-framework/actor-accessible.cpp @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include @@ -177,6 +178,23 @@ void ActorAccessible::DoGetChildren(std::vector& children) } } +void ActorAccessible::UpdateAttributes(Attributes& attributes) const +{ + static const std::string classKey = "class"; + + Accessible::UpdateAttributes(attributes); + + if(attributes.find(classKey) == attributes.end()) + { + Dali::TypeInfo typeInfo; + Self().GetTypeInfo(typeInfo); + if(typeInfo) + { + attributes.emplace(classKey, typeInfo.GetName()); + } + } +} + void ActorAccessible::UpdateChildren() { if(!mChildrenDirty) diff --git a/dali/devel-api/adaptor-framework/actor-accessible.h b/dali/devel-api/adaptor-framework/actor-accessible.h index 1cf3812..777ae9c 100644 --- a/dali/devel-api/adaptor-framework/actor-accessible.h +++ b/dali/devel-api/adaptor-framework/actor-accessible.h @@ -146,6 +146,11 @@ protected: */ virtual void DoGetChildren(std::vector& children); + /** + * @copydoc Dali::Accessibility::Accessible::UpdateAttributes() + */ + void UpdateAttributes(Attributes& attributes) const override; + private: // Extra overload for OnChildrenChanged() to connect to signals directly void OnChildrenChanged(Dali::Actor); diff --git a/dali/devel-api/adaptor-framework/proxy-accessible.h b/dali/devel-api/adaptor-framework/proxy-accessible.h index 33e6b1b..7d4ff21 100644 --- a/dali/devel-api/adaptor-framework/proxy-accessible.h +++ b/dali/devel-api/adaptor-framework/proxy-accessible.h @@ -104,11 +104,6 @@ public: return {}; } - Attributes GetAttributes() const override - { - return {}; - } - bool IsProxy() const override { return true; diff --git a/dali/devel-api/atspi-interfaces/accessible.h b/dali/devel-api/atspi-interfaces/accessible.h index 554fb73..2ba4791 100644 --- a/dali/devel-api/atspi-interfaces/accessible.h +++ b/dali/devel-api/atspi-interfaces/accessible.h @@ -250,9 +250,73 @@ public: /** * @brief Gets accessibility attributes. * + * Attributes are key-value string pairs which can be used to transfer arbitrary + * information from the application to a client such as a screen reader or an + * automation framework. + * + * Typically, attributes are used when the data does not fit any other category + * with a dedicated API (name, description, states etc.). + * + * @see Accessible::SetAttribute() + * @see Accessible::UnsetAttribute() + * @see Accessible::ClearAttributes() + * @see Accessible::UpdateAttributes() + * * @return The map of attributes and their values */ - virtual Attributes GetAttributes() const = 0; + const Attributes& GetAttributes() const; + + /** + * @brief Sets an attribute + * + * The key will be created if necessary and the old attribute value (if any) will be replaced. + * + * @param[in] key Attribute key + * @param[in] value Attribute value + * + * @return True if the key was created, false otherwise (only value was updated) + */ + bool SetAttribute(const std::string& key, const std::string& value); + + /** + * @brief Unsets an attribute + * + * The key-value pair is removed from the attribute collection. + * + * @param[in] key Attribute key + * + * @return True if there was such a key, false otherwise + */ + bool UnsetAttribute(const std::string& key); + + /** + * @brief Unsets all attributes + * + * @see Accessible::UnsetAttribute() + */ + void ClearAttributes(); + + /** + * @brief Gets the reading info types + * + * @return Reading info types bitmask + * @see Accessible::SetReadingInfoTypes() + */ + ReadingInfoTypes GetReadingInfoTypes() const; + + /** + * @brief Sets the reading info types + * + * The reading info types are individual pieces of information (name, role etc.) + * that can be read by the screen reader. This method can be used to enable and + * disable reading specific pieces. + * + * @param[in] types Reading info types bitmask + * + * @note The types will appear in GetAttributes() under the "reading_info_type" key. + * @see Accessible::GetAttributes() + */ + void SetReadingInfoTypes(ReadingInfoTypes types); /** * @brief Checks if this is hidden. @@ -398,6 +462,21 @@ protected: */ virtual AtspiInterfaces DoGetInterfaces() const; + /** + * @brief Updates the attribute collection + * + * This method, which is always called by GetAttributes(), can be overriden to + * provide lazily-calculated or dynamically-calculated (i.e. non-constant) + * attributes. When overriding, make sure to call the base class implementation + * first. + * + * @note The attribute collection is non-empty on entry + * @see Accessible::GetAttributes() + * + * @param[inout] attributes The attribute collection to update + */ + virtual void UpdateAttributes(Attributes& attributes) const; + public: /** * @brief Gets the highlight actor. @@ -484,9 +563,10 @@ private: mutable std::weak_ptr mBridgeData; mutable AtspiInterfaces mInterfaces; + mutable Attributes mAttributes; + ReadingInfoTypes mReadingInfoTypes = ~ReadingInfoTypes(); // all set AtspiEvents mSuppressedEvents; bool mIsOnRootLevel = false; - }; // Accessible class namespace Internal diff --git a/dali/internal/accessibility/bridge/bridge-base.h b/dali/internal/accessibility/bridge/bridge-base.h index 8426ce4..5abe6d5 100644 --- a/dali/internal/accessibility/bridge/bridge-base.h +++ b/dali/internal/accessibility/bridge/bridge-base.h @@ -116,11 +116,6 @@ public: return result; } - Dali::Accessibility::Attributes GetAttributes() const override - { - return {}; - } - /** * @brief Gets the Accessible object from the window. * -- 2.7.4