From 8b6d24a691bb4c9b2f757d30b9575da7dbc547a9 Mon Sep 17 00:00:00 2001 From: Seoyeon Kim Date: Fri, 3 Sep 2021 18:40:51 +0900 Subject: [PATCH] [ATSPI] Add some descriptions to Bridge objects - Added some descriptions for BridgeAccessible and BridgeBase. I'm going to modify other header files, like BridgeAction, to another patch. Otherwise, this patch would become too heavy. - Updated some bridge codes according to dali coding style. Change-Id: I2cc9e7d222c4082af1cc423fd80e0c3eafbf083e Signed-off-by: Seoyeon Kim --- .../adaptor-framework/accessibility-impl.h | 8 +- dali/devel-api/adaptor-framework/accessibility.h | 64 +-- .../accessibility/bridge/accessibility-common.h | 120 ++--- .../accessibility/bridge/bridge-accessible.cpp | 527 ++++++++++++--------- .../accessibility/bridge/bridge-accessible.h | 245 ++++++++-- .../accessibility/bridge/bridge-action.cpp | 17 +- .../accessibility/bridge/bridge-application.cpp | 2 +- dali/internal/accessibility/bridge/bridge-base.cpp | 95 ++-- dali/internal/accessibility/bridge/bridge-base.h | 222 +++++++-- .../accessibility/bridge/bridge-collection.cpp | 112 +++-- .../accessibility/bridge/bridge-component.cpp | 44 +- .../accessibility/bridge/bridge-component.h | 2 +- .../accessibility/bridge/bridge-editable-text.cpp | 16 +- dali/internal/accessibility/bridge/bridge-impl.cpp | 207 +++++--- .../accessibility/bridge/bridge-object.cpp | 98 ++-- .../accessibility/bridge/bridge-selection.cpp | 16 +- dali/internal/accessibility/bridge/bridge-text.cpp | 8 +- .../internal/accessibility/bridge/bridge-value.cpp | 25 +- dali/internal/accessibility/bridge/bridge-value.h | 2 +- dali/internal/accessibility/bridge/component.cpp | 4 +- dali/internal/accessibility/bridge/dummy-atspi.cpp | 2 +- 21 files changed, 1215 insertions(+), 621 deletions(-) diff --git a/dali/devel-api/adaptor-framework/accessibility-impl.h b/dali/devel-api/adaptor-framework/accessibility-impl.h index 6876dd6..dfe1f6b 100644 --- a/dali/devel-api/adaptor-framework/accessibility-impl.h +++ b/dali/devel-api/adaptor-framework/accessibility-impl.h @@ -73,6 +73,8 @@ struct DALI_ADAPTOR_API Bridge /** * @brief Gets bus name which bridge is initialized on. + * + * @return The bus name */ virtual const std::string& GetBusName() const = 0; @@ -380,7 +382,7 @@ protected: ENABLED }; - inline static AutoInitState autoInitState = AutoInitState::ENABLED; + inline static AutoInitState mAutoInitState = AutoInitState::ENABLED; /** * @brief Registers accessible object to be known in bridge object. @@ -1002,7 +1004,7 @@ public: virtual Accessible* GetAccessibleAtPoint(Point point, CoordinateType type); /** - * @brief Checks if current object contains given point. + * @brief Checks if the current object contains the given point inside. * * @param[in] point The two-dimensional point * @param[in] type The enumeration with type of coordinate system @@ -1012,7 +1014,7 @@ public: * @remarks This method is `Contains` in DBus method. * @see Dali::Accessibility::Point */ - virtual bool IsAccessibleContainedAtPoint(Point point, CoordinateType type); + virtual bool IsAccessibleContainingPoint(Point point, CoordinateType type); }; /** diff --git a/dali/devel-api/adaptor-framework/accessibility.h b/dali/devel-api/adaptor-framework/accessibility.h index 1f49d2b..1d4b8e6 100644 --- a/dali/devel-api/adaptor-framework/accessibility.h +++ b/dali/devel-api/adaptor-framework/accessibility.h @@ -88,7 +88,7 @@ enum class RelationType : uint32_t /** * @brief Enumeration describing if coordinates are relative to screen or window * @see Accessibility::Component::GetExtents - * @see Accessibility::Component::IsAccessibleContainedAtPoint + * @see Accessibility::Component::IsAccessibleContainingPoint */ enum class CoordinateType { @@ -447,7 +447,7 @@ enum class ReadingInfoType template class BitSets { - std::array data; + std::array mData; void Set() { @@ -480,7 +480,7 @@ class BitSets public: BitSets() { - for(auto& u : data) + for(auto& u : mData) { u = 0; } @@ -491,8 +491,10 @@ public: template()>::type* = nullptr> BitSets(T t, ARGS... args) { - for(auto& u : data) + for(auto& u : mData) + { u = 0; + } Set(t, args...); } @@ -500,7 +502,7 @@ public: { for(auto i = 0u; i < I; ++i) { - data[i] = d[i]; + mData[i] = d[i]; } } @@ -508,25 +510,25 @@ public: { for(auto i = 0u; i < I; ++i) { - data[i] = static_cast(d[i]); + mData[i] = static_cast(d[i]); } } BitSets& operator=(const BitSets&) = default; BitSets& operator=(BitSets&&) = default; - struct reference + struct Reference { std::array& data; size_t pos; - reference& operator=(reference r) + Reference& operator=(Reference r) { (*this) = static_cast(r); return *this; } - reference& operator=(bool v) + Reference& operator=(bool v) { if(v) { @@ -544,22 +546,22 @@ public: auto i = static_cast(pos); return (data[i / 32] & (1 << (i & 31))) != 0; } - }; + }; // Reference struct - reference operator[](S index) + Reference operator[](S index) { - return {data, static_cast(index)}; + return {mData, static_cast(index)}; } bool operator[](S index) const { auto i = static_cast(index); - return (data[i / 32] & (1 << (i & 31))) != 0; + return (mData[i / 32] & (1 << (i & 31))) != 0; } std::array GetRawData() const { - return data; + return mData; } BitSets operator|(BitSets b) const @@ -567,7 +569,7 @@ public: BitSets r; for(auto i = 0u; i < I; ++i) { - r.data[i] = data[i] | b.data[i]; + r.mData[i] = mData[i] | b.mData[i]; } return r; } @@ -577,7 +579,7 @@ public: BitSets r; for(auto i = 0u; i < I; ++i) { - r.data[i] = data[i] ^ b.data[i]; + r.mData[i] = mData[i] ^ b.mData[i]; } return r; } @@ -587,7 +589,7 @@ public: BitSets r; for(auto i = 0u; i < I; ++i) { - r.data[i] = data[i] & b.data[i]; + r.mData[i] = mData[i] & b.mData[i]; } return r; } @@ -596,7 +598,7 @@ public: { for(auto i = 0u; i < I; ++i) { - if(data[i] != b.data[i]) + if(mData[i] != b.mData[i]) { return false; } @@ -611,7 +613,7 @@ public: explicit operator bool() const { - for(auto& u : data) + for(auto& u : mData) { if(u) { @@ -625,7 +627,7 @@ public: { return I; } -}; +}; // BitSets class using ReadingInfoTypes = BitSets<1, ReadingInfoType>; using States = BitSets<2, State>; @@ -780,8 +782,8 @@ struct DALI_ADAPTOR_API Range /** * @brief Structure containing all values needed to invoke Accessible::DoGesture * type : numerated gesture type - * xBeg, yBeg : point where gesture begins - * xEnd, yEnd : point where gesture ends + * startPositionX, startPositionY : point where gesture begins + * endPositionX, endPositionY : point where gesture ends * state : enumerated state of gesture * eventTime : time when event occured * @see Dali::Accessibility::Accessible::DoGesture @@ -789,22 +791,22 @@ struct DALI_ADAPTOR_API Range struct DALI_ADAPTOR_API GestureInfo { GestureInfo() = default; - GestureInfo(Gesture type, int32_t xBeg, int32_t xEnd, int32_t yBeg, int32_t yEnd, GestureState state, uint32_t eventTime) + GestureInfo(Gesture type, int32_t startPositionX, int32_t endPositionX, int32_t startPositionY, int32_t endPositionY, GestureState state, uint32_t eventTime) : type(type), - xBeg(xBeg), - xEnd(xEnd), - yBeg(yBeg), - yEnd(yEnd), + startPointX(startPositionX), + endPointX(endPositionX), + startPointY(startPositionY), + endPointY(endPositionY), state(state), eventTime(eventTime) { } Gesture type{}; - int32_t xBeg{}; - int32_t xEnd{}; - int32_t yBeg{}; - int32_t yEnd{}; + int32_t startPointX{}; + int32_t endPointX{}; + int32_t startPointY{}; + int32_t endPointY{}; GestureState state{}; uint32_t eventTime{}; }; diff --git a/dali/internal/accessibility/bridge/accessibility-common.h b/dali/internal/accessibility/bridge/accessibility-common.h index d9165f6..eabad2f 100644 --- a/dali/internal/accessibility/bridge/accessibility-common.h +++ b/dali/internal/accessibility/bridge/accessibility-common.h @@ -30,6 +30,8 @@ #include #include +/* DBus Interfaces */ + #define A11yDbusName "org.a11y.Bus" #define A11yDbusPath "/org/a11y/bus" #define A11yDbusStatusInterface "org.a11y.Status" @@ -42,6 +44,8 @@ #define AtspiDbusInterfaceAccessible "org.a11y.atspi.Accessible" #define AtspiDbusInterfaceAction "org.a11y.atspi.Action" #define AtspiDbusInterfaceApplication "org.a11y.atspi.Application" +#define AtspiDbusInterfaceCache "org.a11y.atspi.Cache" +#define AtspiDbusPathCache "/org/a11y/atspi/cache" #define AtspiDbusInterfaceCollection "org.a11y.atspi.Collection" #define AtspiDbusInterfaceComponent "org.a11y.atspi.Component" #define AtspiDbusInterfaceDocument "org.a11y.atspi.Document" @@ -102,41 +106,47 @@ enum class SortOrder : uint32_t namespace DBus { + +/** + * @brief The CurrentBridgePtr class is to save the current Accessibility Bridge. + */ class CurrentBridgePtr { - static Dali::Accessibility::Bridge*& get() + static Dali::Accessibility::Bridge*& Get() { - static thread_local Dali::Accessibility::Bridge* b = nullptr; - return b; + static thread_local Dali::Accessibility::Bridge* bridge = nullptr; + return bridge; } - Dali::Accessibility::Bridge* prev; + Dali::Accessibility::Bridge* mPrev; CurrentBridgePtr(const CurrentBridgePtr&) = delete; CurrentBridgePtr(CurrentBridgePtr&&) = delete; CurrentBridgePtr& operator=(const CurrentBridgePtr&) = delete; CurrentBridgePtr& operator=(CurrentBridgePtr&&) = delete; public: - CurrentBridgePtr(Dali::Accessibility::Bridge* b) - : prev(get()) + CurrentBridgePtr(Dali::Accessibility::Bridge* bridge) + : mPrev(Get()) { - get() = b; + Get() = bridge; } ~CurrentBridgePtr() { - get() = prev; + Get() = mPrev; } - static Dali::Accessibility::Bridge* current() + static Dali::Accessibility::Bridge* GetCurrentBridge() { - return get(); + return Get(); } -}; +}; // CurrentBridgePtr + +// Templates for setting and getting Accessible values namespace detail { template -struct signature_accessible_impl : signature_helper> +struct SignatureAccessibleImpl : signature_helper> { using subtype = std::pair; @@ -144,14 +154,14 @@ struct signature_accessible_impl : signature_helper static constexpr auto sig_v = concat("(so)"); /** - * @brief Marshals value v as marshalled type into message + * @brief Marshals value address as marshalled type into message */ - static void set(const DBusWrapper::MessageIterPtr& iter, T* t) + static void set(const DBusWrapper::MessageIterPtr& iter, T* accessible) { - if(t) + if(accessible) { - auto v = t->GetAddress(); - signature::set(iter, {v.GetBus(), ObjectPath{std::string{ATSPI_PREFIX_PATH} + v.GetPath()}}); + auto address = accessible->GetAddress(); + signature::set(iter, {address.GetBus(), ObjectPath{std::string{ATSPI_PREFIX_PATH} + address.GetPath()}}); } else { @@ -160,9 +170,9 @@ struct signature_accessible_impl : signature_helper } /** - * @brief Marshals value from marshalled type into variable v + * @brief Marshals value from marshalled type into variable path */ - static bool get(const DBusWrapper::MessageIterPtr& iter, T*& v) + static bool get(const DBusWrapper::MessageIterPtr& iter, T*& path) { subtype tmp; if(!signature::get(iter, tmp)) @@ -172,7 +182,7 @@ struct signature_accessible_impl : signature_helper if(tmp.second.value == ATSPI_NULL_PATH) { - v = nullptr; + path = nullptr; return true; } @@ -181,19 +191,19 @@ struct signature_accessible_impl : signature_helper return false; } - auto b = CurrentBridgePtr::current(); - if(b->GetBusName() != tmp.first) + auto currentBridge = CurrentBridgePtr::GetCurrentBridge(); + if(currentBridge->GetBusName() != tmp.first) { return false; } - v = b->FindByPath(tmp.second.value.substr(strlen(ATSPI_PREFIX_PATH))); - return v != nullptr; + path = currentBridge->FindByPath(tmp.second.value.substr(strlen(ATSPI_PREFIX_PATH))); + return path != nullptr; } }; template<> -struct signature : public signature_accessible_impl +struct signature : public SignatureAccessibleImpl { }; @@ -206,24 +216,24 @@ struct signature : signature_helper::set(iter, {v.GetBus(), ObjectPath{std::string{ATSPI_PREFIX_PATH} + v.GetPath()}}); + signature::set(iter, {address.GetBus(), ObjectPath{std::string{ATSPI_PREFIX_PATH} + address.GetPath()}}); } else { - signature::set(iter, {v.GetBus(), ObjectPath{ATSPI_NULL_PATH}}); + signature::set(iter, {address.GetBus(), ObjectPath{ATSPI_NULL_PATH}}); } } /** - * @brief Marshals value from marshalled type into variable v + * @brief Marshals value from marshalled type into variable address */ - static bool get(const DBusWrapper::MessageIterPtr& iter, Dali::Accessibility::Address& v) + static bool get(const DBusWrapper::MessageIterPtr& iter, Dali::Accessibility::Address& address) { subtype tmp; if(!signature::get(iter, tmp)) @@ -233,7 +243,7 @@ struct signature : signature_helper : signature_helper : signature_helper::sig_v; /** - * @brief Marshals value v as marshalled type into message + * @brief Marshals value state as marshalled type into message */ - static void set(const DBusWrapper::MessageIterPtr& iter, const Dali::Accessibility::States& v) + static void set(const DBusWrapper::MessageIterPtr& iter, const Dali::Accessibility::States& states) { - signature::set(iter, v.GetRawData()); + signature::set(iter, states.GetRawData()); } /** - * @brief Marshals value from marshalled type into variable v + * @brief Marshals value from marshalled type into variable state */ - static bool get(const DBusWrapper::MessageIterPtr& iter, Dali::Accessibility::States& v) + static bool get(const DBusWrapper::MessageIterPtr& iter, Dali::Accessibility::States& state) { subtype tmp; if(!signature::get(iter, tmp)) { return false; } - v = Dali::Accessibility::States{tmp}; + state = Dali::Accessibility::States{tmp}; return true; } }; @@ -281,25 +291,25 @@ struct signature : signature_helper _Logger& operator<<(T&& t) { - tmp << std::forward(t); + mTmp << std::forward(t); return *this; } }; @@ -315,19 +325,19 @@ struct _LoggerEmpty struct _LoggerScope { - const char* file; - int line; + const char* mFile; + int mLine; - _LoggerScope(const char* f, int l) - : file(f), - line(l) + _LoggerScope(const char* file, int line) + : mFile(file), + mLine(line) { - Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d: +", file, line); + Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d: +", mFile, mLine); } ~_LoggerScope() { - Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d: -", file, line); + Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d: -", mFile, mLine); } }; diff --git a/dali/internal/accessibility/bridge/bridge-accessible.cpp b/dali/internal/accessibility/bridge/bridge-accessible.cpp index b28d5f1..d507e3a 100644 --- a/dali/internal/accessibility/bridge/bridge-accessible.cpp +++ b/dali/internal/accessibility/bridge/bridge-accessible.cpp @@ -30,7 +30,8 @@ using namespace Dali::Accessibility; #define GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH 10000 -namespace { +namespace +{ bool SortVertically(Component* lhs, Component* rhs) { @@ -94,45 +95,17 @@ std::vector> SplitLines(const std::vector& c return lines; } -} // anonymous namespace - -BridgeAccessible::BridgeAccessible() -{ -} - -void BridgeAccessible::RegisterInterfaces() -{ - DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceAccessible}; - AddGetPropertyToInterface(desc, "ChildCount", &BridgeAccessible::GetChildCount); - AddGetPropertyToInterface(desc, "Name", &BridgeAccessible::GetName); - AddGetPropertyToInterface(desc, "Description", &BridgeAccessible::GetDescription); - AddGetPropertyToInterface(desc, "Parent", &BridgeAccessible::GetParent); - AddFunctionToInterface(desc, "GetRole", &BridgeAccessible::GetRole); - AddFunctionToInterface(desc, "GetRoleName", &BridgeAccessible::GetRoleName); - AddFunctionToInterface(desc, "GetLocalizedRoleName", &BridgeAccessible::GetLocalizedRoleName); - AddFunctionToInterface(desc, "GetState", &BridgeAccessible::GetStates); - AddFunctionToInterface(desc, "GetAttributes", &BridgeAccessible::GetAttributes); - AddFunctionToInterface(desc, "GetInterfaces", &BridgeAccessible::GetInterfaces); - AddFunctionToInterface(desc, "GetChildAtIndex", &BridgeAccessible::GetChildAtIndex); - AddFunctionToInterface(desc, "GetChildren", &BridgeAccessible::GetChildren); - AddFunctionToInterface(desc, "GetIndexInParent", &BridgeAccessible::GetIndexInParent); - AddFunctionToInterface(desc, "GetNavigableAtPoint", &BridgeAccessible::GetNavigableAtPoint); - AddFunctionToInterface(desc, "GetNeighbor", &BridgeAccessible::GetNeighbor); - AddFunctionToInterface(desc, "GetDefaultLabelInfo", &BridgeAccessible::GetDefaultLabelInfo); - AddFunctionToInterface(desc, "DoGesture", &BridgeAccessible::DoGesture); - AddFunctionToInterface(desc, "GetReadingMaterial", &BridgeAccessible::GetReadingMaterial); - AddFunctionToInterface(desc, "GetRelationSet", &BridgeAccessible::GetRelationSet); - dbusServer.addInterface("/", desc, true); -} - static bool AcceptObjectCheckRelations(Component* obj) { - auto r = obj->GetRelationSet(); + auto relations = obj->GetRelationSet(); - for(const auto& it : r) + for(const auto& it : relations) + { if(it.relationType == RelationType::CONTROLLED_BY) + { return false; - + } + } return true; } @@ -143,46 +116,63 @@ static Component* GetScrollableParent(Accessible* obj) obj = obj->GetParent(); auto comp = dynamic_cast(obj); if(comp && comp->IsScrollable()) + { return comp; + } } return nullptr; } -static bool ObjectIsItem(Component* obj) +static bool IsObjectItem(Component* obj) { if(!obj) + { return false; + } auto role = obj->GetRole(); return role == Role::LIST_ITEM || role == Role::MENU_ITEM; } -static bool ObjectIsCollapsed(Component* obj) +static bool IsObjectCollapsed(Component* obj) { if(!obj) + { return false; + } const auto states = obj->GetStates(); return states[State::EXPANDABLE] && !states[State::EXPANDED]; } -static bool ObjectIsZeroSize(Component* obj) +static bool IsObjectZeroSize(Component* obj) { if(!obj) + { return false; + } auto extents = obj->GetExtents(CoordinateType::WINDOW); return extents.height == 0 || extents.width == 0; } -static bool AcceptObject(Component* obj) +static bool IsObjectAcceptable(Component* obj) { if(!obj) + { return false; + } + const auto states = obj->GetStates(); if(!states[State::VISIBLE]) + { return false; + } if(!AcceptObjectCheckRelations(obj)) + { return false; + } if(!states[State::HIGHLIGHTABLE]) + { return false; + } if(GetScrollableParent(obj) != nullptr) { @@ -190,12 +180,12 @@ static bool AcceptObject(Component* obj) if(parent) { - return !ObjectIsItem(obj) || !ObjectIsCollapsed(parent); + return !IsObjectItem(obj) || !IsObjectCollapsed(parent); } } else { - if(ObjectIsZeroSize(obj)) + if(IsObjectZeroSize(obj)) { return false; } @@ -207,10 +197,10 @@ static bool AcceptObject(Component* obj) return true; } -static bool AcceptObject(Accessible* obj) +static bool IsObjectAcceptable(Accessible* obj) { - auto c = dynamic_cast(obj); - return AcceptObject(c); + auto component = dynamic_cast(obj); + return IsObjectAcceptable(component); } static int32_t GetItemCountOfList(Accessible* obj) @@ -251,52 +241,187 @@ static int32_t GetItemCountOfFirstDescendantList(Accessible* obj) return itemCount; } -static std::string objDump(Component* obj) +static std::string GetComponentInfo(Component* obj) { if(!obj) + { return "nullptr"; - std::ostringstream o; - auto e = obj->GetExtents(CoordinateType::SCREEN); - o << "name: " << obj->GetName() << " extent: (" << e.x << ", " - << e.y << "), [" << e.width << ", " << e.height << "]"; - return o.str(); + } + + std::ostringstream object; + auto extent = obj->GetExtents(CoordinateType::SCREEN); + object << "name: " << obj->GetName() << " extent: (" << extent.x << ", " + << extent.y << "), [" << extent.width << ", " << extent.height << "]"; + return object.str(); } -Component* BridgeAccessible::GetObjectInRelation(Accessible* obj, RelationType ralationType) +static std::string MakeIndent(unsigned int maxRecursionDepth) +{ + return std::string(GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH - maxRecursionDepth, ' '); +} + +static bool IsDeputy(Accessible* obj) +{ + //TODO: add deputy + return false; +} + +static Accessible* GetProxyInParent(Accessible* obj) { if(!obj) + { return nullptr; + } + + auto children = obj->GetChildren(); + for(auto& child : children) + { + if(child->IsProxy()) + { + return child; + } + } + return nullptr; +} + +static bool IsRoleAcceptableWhenNavigatingNextPrev(Accessible* obj) +{ + if(!obj) + { + return false; + } + auto role = obj->GetRole(); + return role != Role::POPUP_MENU && role != Role::DIALOG; +} + +static Accessible* FindNonDefunctChild(const std::vector& children, unsigned int currentIndex, unsigned char forward) +{ + unsigned int childrenCount = children.size(); + for(; currentIndex < childrenCount; forward ? ++currentIndex : --currentIndex) + { + Accessible* object = children[currentIndex]; + if(object && !object->GetStates()[State::DEFUNCT]) + { + return object; + } + } + return nullptr; +} + +// The auxiliary method for Depth-First Search (DFS) algorithm to find non defunct child directionally +static Accessible* FindNonDefunctChildWithDepthFirstSearch(Accessible* node, const std::vector& children, unsigned char forward) +{ + if(!node) + { + return nullptr; + } + + auto childrenCount = children.size(); + if(childrenCount > 0) + { + const bool isShowing = GetScrollableParent(node) == nullptr ? node->GetStates()[State::SHOWING] : true; + if(isShowing) + { + return FindNonDefunctChild(children, forward ? 0 : childrenCount - 1, forward); + } + } + return nullptr; +} + +static bool CheckChainEndWithAttribute(Accessible* obj, unsigned char forward) +{ + if(!obj) + { + return false; + } + + auto attrs = obj->GetAttributes(); + for(auto& attr : attrs) + { + if(attr.first == "relation_chain_end") + { + if((attr.second == "prev,end" && forward == 0) || (attr.second == "next,end" && forward == 1) || attr.second == "prev,next,end") + { + return true; + } + } + } + return false; +} + +static Accessible* GetDeputyOfProxyInParent(Accessible* obj) +{ + return nullptr; +} + + +} // anonymous namespace + + +BridgeAccessible::BridgeAccessible() +{ +} + +void BridgeAccessible::RegisterInterfaces() +{ + DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceAccessible}; + AddGetPropertyToInterface(desc, "ChildCount", &BridgeAccessible::GetChildCount); + AddGetPropertyToInterface(desc, "Name", &BridgeAccessible::GetName); + AddGetPropertyToInterface(desc, "Description", &BridgeAccessible::GetDescription); + AddGetPropertyToInterface(desc, "Parent", &BridgeAccessible::GetParent); + AddFunctionToInterface(desc, "GetRole", &BridgeAccessible::GetRole); + AddFunctionToInterface(desc, "GetRoleName", &BridgeAccessible::GetRoleName); + AddFunctionToInterface(desc, "GetLocalizedRoleName", &BridgeAccessible::GetLocalizedRoleName); + AddFunctionToInterface(desc, "GetState", &BridgeAccessible::GetStates); + AddFunctionToInterface(desc, "GetAttributes", &BridgeAccessible::GetAttributes); + AddFunctionToInterface(desc, "GetInterfaces", &BridgeAccessible::GetInterfaces); + AddFunctionToInterface(desc, "GetChildAtIndex", &BridgeAccessible::GetChildAtIndex); + AddFunctionToInterface(desc, "GetChildren", &BridgeAccessible::GetChildren); + AddFunctionToInterface(desc, "GetIndexInParent", &BridgeAccessible::GetIndexInParent); + AddFunctionToInterface(desc, "GetNavigableAtPoint", &BridgeAccessible::GetNavigableAtPoint); + AddFunctionToInterface(desc, "GetNeighbor", &BridgeAccessible::GetNeighbor); + AddFunctionToInterface(desc, "GetDefaultLabelInfo", &BridgeAccessible::GetDefaultLabelInfo); + AddFunctionToInterface(desc, "DoGesture", &BridgeAccessible::DoGesture); + AddFunctionToInterface(desc, "GetReadingMaterial", &BridgeAccessible::GetReadingMaterial); + AddFunctionToInterface(desc, "GetRelationSet", &BridgeAccessible::GetRelationSet); + mDbusServer.addInterface("/", desc, true); +} + +Component* BridgeAccessible::GetObjectInRelation(Accessible* obj, RelationType relationType) +{ + if(!obj) + { + return nullptr; + } + for(auto& relation : obj->GetRelationSet()) { - if(relation.relationType == ralationType) + if(relation.relationType == relationType) { for(auto& address : relation.targets) { auto component = dynamic_cast(Find(address)); if(component) + { return component; + } } } } return nullptr; } -static std::string makeIndent(unsigned int maxRecursionDepth) -{ - return std::string(GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH - maxRecursionDepth, ' '); -} - -Component* BridgeAccessible::CalculateNavigableAccessibleAtPoint(Accessible* root, Point p, CoordinateType type, unsigned int maxRecursionDepth) +Component* BridgeAccessible::CalculateNavigableAccessibleAtPoint(Accessible* root, Point point, CoordinateType type, unsigned int maxRecursionDepth) { if(!root || maxRecursionDepth == 0) { return nullptr; } - auto root_component = dynamic_cast(root); - LOG() << "CalculateNavigableAccessibleAtPoint: checking: " << makeIndent(maxRecursionDepth) << objDump(root_component); + auto rootComponent = dynamic_cast(root); + LOG() << "CalculateNavigableAccessibleAtPoint: checking: " << MakeIndent(maxRecursionDepth) << GetComponentInfo(rootComponent); - if(root_component && !root_component->IsAccessibleContainedAtPoint(p, type)) + if(rootComponent && !rootComponent->IsAccessibleContainingPoint(point, type)) { return nullptr; } @@ -305,25 +430,25 @@ Component* BridgeAccessible::CalculateNavigableAccessibleAtPoint(Accessible* roo for(auto childIt = children.rbegin(); childIt != children.rend(); childIt++) { //check recursively all children first - auto result = CalculateNavigableAccessibleAtPoint(*childIt, p, type, maxRecursionDepth - 1); + auto result = CalculateNavigableAccessibleAtPoint(*childIt, point, type, maxRecursionDepth - 1); if(result) { return result; } } - if(root_component) + if(rootComponent) { //Found a candidate, all its children are already checked - auto controledBy = GetObjectInRelation(root_component, RelationType::CONTROLLED_BY); + auto controledBy = GetObjectInRelation(rootComponent, RelationType::CONTROLLED_BY); if(!controledBy) { - controledBy = root_component; + controledBy = rootComponent; } - if(controledBy->IsProxy() || AcceptObject(controledBy)) + if(controledBy->IsProxy() || IsObjectAcceptable(controledBy)) { - LOG() << "CalculateNavigableAccessibleAtPoint: found: " << makeIndent(maxRecursionDepth) << objDump(root_component); + LOG() << "CalculateNavigableAccessibleAtPoint: found: " << MakeIndent(maxRecursionDepth) << GetComponentInfo(rootComponent); return controledBy; } } @@ -447,12 +572,13 @@ BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial() void BridgeAccessible::SuppressScreenReader(bool suppress) { - suppressScreenReader = suppress; + mIsScreenReaderSuppressed = suppress; } -DBus::ValueOrError BridgeAccessible::DoGesture(Dali::Accessibility::Gesture type, int32_t xBeg, int32_t yBeg, int32_t xEnd, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime) +DBus::ValueOrError BridgeAccessible::DoGesture(Dali::Accessibility::Gesture type, int32_t startPositionX, int32_t startPositionY, int32_t endPositionX, int32_t endPositionY, Dali::Accessibility::GestureState state, uint32_t eventTime) { - return FindSelf()->DoGesture(Dali::Accessibility::GestureInfo{type, xBeg, xEnd, yBeg, yEnd, state, eventTime}); + // Please be aware of sending GestureInfo point in the different order with parameters + return FindSelf()->DoGesture(Dali::Accessibility::GestureInfo{type, startPositionX, endPositionX, startPositionY, endPositionY, state, eventTime}); } DBus::ValueOrError BridgeAccessible::GetNavigableAtPoint(int32_t x, int32_t y, uint32_t coordinateType) @@ -471,36 +597,13 @@ DBus::ValueOrError BridgeAccessible::GetNavig return {component, recurse, deputy}; } -static bool CheckChainEndWithAttribute(Accessible* obj, unsigned char forward) -{ - if(!obj) - return false; - auto attrs = obj->GetAttributes(); - for(auto& attr : attrs) - { - if(attr.first == "relation_chain_end") - { - if((attr.second == "prev,end" && forward == 0) || (attr.second == "next,end" && forward == 1) || attr.second == "prev,next,end") - { - return true; - } - } - } - return false; -} - -static Accessible* DeputyOfProxyInParentGet(Accessible* obj) -{ - return nullptr; -} - Accessible* BridgeAccessible::GetCurrentlyHighlighted() { //TODO: add currently highlighted object return nullptr; } -std::vector BridgeAccessible::ValidChildrenGet(const std::vector& children, Accessible* start, Accessible* root) +std::vector BridgeAccessible::GetValidChildren(const std::vector& children, Accessible* start, Accessible* root) { std::vector vec; std::vector ret; @@ -524,268 +627,251 @@ std::vector BridgeAccessible::ValidChildrenGet(const std::vectorGetChildren(); - for(auto& child : children) - { - if(child->IsProxy()) - return child; - } - return nullptr; -} - -static bool ObjectRoleIsAcceptableWhenNavigatingNextPrev(Accessible* obj) -{ - if(!obj) - return false; - auto role = obj->GetRole(); - return role != Role::POPUP_MENU && role != Role::DIALOG; -} template struct CycleDetection { CycleDetection(const T value) - : key(value), - currentSearchSize(1), - counter(1) + : mKey(value), + mCurrentSearchSize(1), + mCounter(1) { } - bool check(const T value) + + bool Check(const T value) { - if(key == value) + if(mKey == value) + { return true; - if(--counter == 0) + } + + if(--mCounter == 0) { - currentSearchSize <<= 1; - if(currentSearchSize == 0) + mCurrentSearchSize <<= 1; + if(mCurrentSearchSize == 0) + { return true; // UNDEFINED BEHAVIOR - counter = currentSearchSize; - key = value; + } + mCounter = mCurrentSearchSize; + mKey = value; } return false; } - T key; - unsigned int currentSearchSize; - unsigned int counter; + + T mKey; + unsigned int mCurrentSearchSize; + unsigned int mCounter; }; -static Accessible* FindNonDefunctChild(const std::vector& children, unsigned int currentIndex, unsigned char forward) +Accessible* BridgeAccessible::GetNextNonDefunctSibling(Accessible* obj, Accessible* start, Accessible* root, unsigned char forward) { - unsigned int childrenCount = children.size(); - for(; currentIndex < childrenCount; forward ? ++currentIndex : --currentIndex) + if(!obj) { - Accessible* n = children[currentIndex]; - if(n && !n->GetStates()[State::DEFUNCT]) - return n; - } - return nullptr; -} - -static Accessible* DirectionalDepthFirstSearchTryNonDefunctChild(Accessible* node, const std::vector& children, unsigned char forward) -{ - if(!node) return nullptr; - auto childrenCount = children.size(); - if(childrenCount > 0) - { - const bool isShowing = GetScrollableParent(node) == nullptr ? node->GetStates()[State::SHOWING] : true; - if(isShowing) - { - return FindNonDefunctChild(children, forward ? 0 : childrenCount - 1, forward); - } } - return nullptr; -} -Accessible* BridgeAccessible::GetNextNonDefunctSibling(Accessible* obj, Accessible* start, Accessible* root, unsigned char forward) -{ - if(!obj) - return nullptr; auto parent = obj->GetParent(); if(!parent) + { return nullptr; + } - auto children = ValidChildrenGet(parent->GetChildren(), start, root); + auto children = GetValidChildren(parent->GetChildren(), start, root); - unsigned int children_count = children.size(); - if(children_count == 0) + unsigned int childrenCount = children.size(); + if(childrenCount == 0) { return nullptr; } + unsigned int current = 0; - for(; current < children_count && children[current] != obj; ++current) - ; - if(current >= children_count) + for(; current < childrenCount && children[current] != obj; ++current) + { + } + + if(current >= childrenCount) { return nullptr; } + forward ? ++current : --current; auto ret = FindNonDefunctChild(children, current, forward); return ret; } -Accessible* BridgeAccessible::DirectionalDepthFirstSearchTryNonDefunctSibling(bool& all_children_visited, Accessible* node, Accessible* start, Accessible* root, unsigned char forward) +Accessible* BridgeAccessible::FindNonDefunctSibling(bool& areAllChildrenVisited, Accessible* node, Accessible* start, Accessible* root, unsigned char forward) { while(true) { Accessible* sibling = GetNextNonDefunctSibling(node, start, root, forward); if(sibling) { - node = sibling; - all_children_visited = false; + node = sibling; + areAllChildrenVisited = false; // Note that this is passed by non-const reference, so it is the caller that can determine whether this search exhausted all children. break; } // walk up... node = node->GetParent(); if(node == nullptr || node == root) + { return nullptr; + } // in backward traversing stop the walk up on parent if(!forward) + { break; + } } + return node; } -Accessible* BridgeAccessible::CalculateNeighbor(Accessible* root, Accessible* start, unsigned char forward, BridgeAccessible::GetNeighborSearchMode search_mode) +Accessible* BridgeAccessible::CalculateNeighbor(Accessible* root, Accessible* start, unsigned char forward, BridgeAccessible::NeighborSearchMode searchMode) { if(start && CheckChainEndWithAttribute(start, forward)) + { return start; + } if(root && root->GetStates()[State::DEFUNCT]) + { return NULL; + } if(start && start->GetStates()[State::DEFUNCT]) { start = NULL; forward = 1; } - if(search_mode == BridgeAccessible::GetNeighborSearchMode::recurseToOutside) + if(searchMode == BridgeAccessible::NeighborSearchMode::RECURSE_TO_OUTSIDE) { // This only works if we navigate backward, and it is not possible to // find in embedded process. In this case the deputy should be used */ - return DeputyOfProxyInParentGet(start); + return GetDeputyOfProxyInParent(start); } Accessible* node = start ? start : root; if(!node) + { return nullptr; + } // initialization of all-children-visited flag for start node - we assume // that when we begin at start node and we navigate backward, then all children // are visited, so navigation will ignore start's children and go to // previous sibling available. // Regarding condtion (start != root): - // The last object can be found only if all_children_visited is false. + // The last object can be found only if areAllChildrenVisited is false. // The start is same with root, when looking for the last object. - bool all_children_visited = (start != root) && (search_mode != BridgeAccessible::GetNeighborSearchMode::recurseFromRoot && !forward); + bool areAllChildrenVisited = (start != root) && (searchMode != BridgeAccessible::NeighborSearchMode::RECURSE_FROM_ROOT && !forward); + // true, if starting element should be ignored. this is only used in rare case of // recursive search failing to find an object. // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from // element A algorithm has to descend into BUS_B and search element B and its children. this is done // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B). // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out - // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING. + // and will call us again with object A and flag searchMode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING. // this flag means, that object A was already checked previously and we should skip it and its children. - bool force_next = (search_mode == BridgeAccessible::GetNeighborSearchMode::continueAfterFailedRecursion); + bool forceNext = (searchMode == BridgeAccessible::NeighborSearchMode::CONTINUE_AFTER_FAILED_RECURSION); CycleDetection cycleDetection(node); while(node) { if(node->GetStates()[State::DEFUNCT]) + { return nullptr; + } // always accept proxy object from different world - if(!force_next && node->IsProxy()) + if(!forceNext && node->IsProxy()) + { return node; + } auto children = node->GetChildren(); - children = ValidChildrenGet(children, start, root); + children = GetValidChildren(children, start, root); // do accept: // 1. not start node // 2. parent after all children in backward traversing // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element. // Objects with those roles shouldnt be reachable, when navigating next / prev. - bool all_children_visited_or_moving_forward = (children.size() == 0 || forward || all_children_visited); - if(!force_next && node != start && all_children_visited_or_moving_forward && AcceptObject(node)) + bool areAllChildrenVisitedOrMovingForward= (children.size() == 0 || forward || areAllChildrenVisited); + + if(!forceNext && node != start && areAllChildrenVisitedOrMovingForward && IsObjectAcceptable(node)) { - if(start == NULL || ObjectRoleIsAcceptableWhenNavigatingNextPrev(node)) + if(start == NULL || IsRoleAcceptableWhenNavigatingNextPrev(node)) + { return node; + } } - Accessible* next_related_in_direction = !force_next ? GetObjectInRelation(node, forward ? RelationType::FLOWS_TO : RelationType::FLOWS_FROM) : nullptr; - // force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING + Accessible* nextRelatedInDirection = !forceNext ? GetObjectInRelation(node, forward ? RelationType::FLOWS_TO : RelationType::FLOWS_FROM) : nullptr; + // forceNext means that the searchMode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING // in this case the node is elm_layout which is parent of proxy object. // There is an access object working for the proxy object, and the access // object could have relation information. This relation information should // be checked first before using the elm_layout as a node. - if(force_next && forward) + if(forceNext && forward) { - auto deputy = DeputyOfProxyInParentGet(node); - next_related_in_direction = - GetObjectInRelation(deputy, RelationType::FLOWS_TO); + auto deputy = GetDeputyOfProxyInParent(node); + nextRelatedInDirection = GetObjectInRelation(deputy, RelationType::FLOWS_TO); } - if(next_related_in_direction && start && start->GetStates()[State::DEFUNCT]) + if(nextRelatedInDirection && start && start->GetStates()[State::DEFUNCT]) { - next_related_in_direction = NULL; + nextRelatedInDirection = NULL; } - unsigned char want_cycle_detection = 0; - if(next_related_in_direction) + unsigned char wantCycleDetection = 0; + if(nextRelatedInDirection) { - // Check next_related_in_direction is deputy object + // Check whether nextRelatedInDirection is deputy object or not Accessible* parent; if(!forward) { // If the prev object is deputy, then go to inside of its proxy first - if(DeputyIs(next_related_in_direction)) + if(IsDeputy(nextRelatedInDirection)) { - parent = next_related_in_direction->GetParent(); - next_related_in_direction = ProxyInParentGet(parent); + parent = nextRelatedInDirection->GetParent(); + nextRelatedInDirection = GetProxyInParent(parent); } } else { // If current object is deputy, and it has relation next object, // then do not use the relation next object, and use proxy first - if(DeputyIs(node)) + if(IsDeputy(node)) { - parent = node->GetParent(); - next_related_in_direction = ProxyInParentGet(parent); + parent = node->GetParent(); + nextRelatedInDirection = GetProxyInParent(parent); } } - node = next_related_in_direction; - want_cycle_detection = 1; + node = nextRelatedInDirection; + wantCycleDetection = 1; } else { - auto child = !force_next && !all_children_visited ? DirectionalDepthFirstSearchTryNonDefunctChild(node, children, forward) : nullptr; + auto child = !forceNext && !areAllChildrenVisited ? FindNonDefunctChildWithDepthFirstSearch(node, children, forward) : nullptr; if(child) { - want_cycle_detection = 1; + wantCycleDetection = 1; } else { - if(!force_next && node == root) + if(!forceNext && node == root) + { return NULL; - all_children_visited = true; - child = DirectionalDepthFirstSearchTryNonDefunctSibling(all_children_visited, node, start, root, forward); + } + areAllChildrenVisited = true; + child = FindNonDefunctSibling(areAllChildrenVisited, node, start, root, forward); } node = child; } - force_next = 0; - if(want_cycle_detection && cycleDetection.check(node)) + + forceNext = 0; + if(wantCycleDetection && cycleDetection.Check(node)) { return NULL; } @@ -793,12 +879,12 @@ Accessible* BridgeAccessible::CalculateNeighbor(Accessible* root, Accessible* st return NULL; } -DBus::ValueOrError BridgeAccessible::GetNeighbor(std::string rootPath, int32_t direction, int32_t search_mode) +DBus::ValueOrError BridgeAccessible::GetNeighbor(std::string rootPath, int32_t direction, int32_t searchMode) { auto start = FindSelf(); rootPath = StripPrefix(rootPath); auto root = !rootPath.empty() ? Find(rootPath) : nullptr; - auto accessible = CalculateNeighbor(root, start, direction == 1, static_cast(search_mode)); + auto accessible = CalculateNeighbor(root, start, direction == 1, static_cast(searchMode)); unsigned char recurse = 0; if(accessible) { @@ -813,60 +899,74 @@ Accessible* BridgeAccessible::GetParent() // only element set as application root might return nullptr from GetParent // if you want more, then you need to change setApplicationRoot to // add/remove ApplicationRoot and make roots a vector. - auto p = FindSelf()->GetParent(); + auto parent = FindSelf()->GetParent(); - return p; + return parent; } + DBus::ValueOrError> BridgeAccessible::GetChildren() { return FindSelf()->GetChildren(); } + std::string BridgeAccessible::GetDescription() { return FindSelf()->GetDescription(); } + DBus::ValueOrError BridgeAccessible::GetRole() { return static_cast(FindSelf()->GetRole()); } + DBus::ValueOrError BridgeAccessible::GetRoleName() { return FindSelf()->GetRoleName(); } + DBus::ValueOrError BridgeAccessible::GetLocalizedRoleName() { return FindSelf()->GetLocalizedRoleName(); } + DBus::ValueOrError BridgeAccessible::GetIndexInParent() { return FindSelf()->GetIndexInParent(); } + DBus::ValueOrError> BridgeAccessible::GetStates() { return FindSelf()->GetStates().GetRawData(); } + DBus::ValueOrError> BridgeAccessible::GetAttributes() { std::unordered_map attributes = FindSelf()->GetAttributes(); - if(suppressScreenReader) + + if(mIsScreenReaderSuppressed) { attributes.insert({"suppress-screen-reader", "true"}); } return attributes; } + DBus::ValueOrError> BridgeAccessible::GetInterfaces() { return FindSelf()->GetInterfaces(); } + int BridgeAccessible::GetChildCount() { return FindSelf()->GetChildCount(); } + DBus::ValueOrError BridgeAccessible::GetChildAtIndex(int index) { if(index < 0) + { throw std::domain_error{"negative index (" + std::to_string(index) + ")"}; + } return FindSelf()->GetChildAtIndex(static_cast(index)); } @@ -878,6 +978,7 @@ std::string BridgeAccessible::GetName() DBus::ValueOrError> BridgeAccessible::GetDefaultLabelInfo() { auto defaultLabel = FindSelf()->GetDefaultLabel(); + // By default, the text is taken from navigation context root's accessibility properties name and description. return {defaultLabel, static_cast(defaultLabel->GetRole()), defaultLabel->GetAttributes()}; } @@ -887,7 +988,9 @@ DBus::ValueOrError> BridgeAccessible::Ge std::vector ret; for(auto& it : relations) + { ret.emplace_back(Relation{static_cast(it.relationType), it.targets}); + } return ret; } diff --git a/dali/internal/accessibility/bridge/bridge-accessible.h b/dali/internal/accessibility/bridge/bridge-accessible.h index 255dc44..da2c601 100644 --- a/dali/internal/accessibility/bridge/bridge-accessible.h +++ b/dali/internal/accessibility/bridge/bridge-accessible.h @@ -27,38 +27,35 @@ // INTERNAL INCLUDES #include "bridge-base.h" +/** + * @brief The BridgeAccessible class is to correspond with Dali::Accessibility::Accessible. + */ class BridgeAccessible : public virtual BridgeBase { protected: + + /** + * @brief Constructor. + */ BridgeAccessible(); + /** + * @brief Registers Accessible functions to dbus interfaces. + */ void RegisterInterfaces(); - bool suppressScreenReader = false; public: - enum class GetNeighborSearchMode + /** + * @brief Enumeration for NeighborSearchMode. + */ + enum class NeighborSearchMode { - normal = 0, - recurseFromRoot = 1, - continueAfterFailedRecursion = 2, - recurseToOutside = 3, + NORMAL = 0, ///< Normal + RECURSE_FROM_ROOT = 1, ///< Recurse from root + CONTINUE_AFTER_FAILED_RECURSION = 2, ///< Continue after failed recursion + RECURSE_TO_OUTSIDE = 3, ///< Recurse to outside }; - int GetChildCount(); - DBus::ValueOrError GetChildAtIndex(int index); - Dali::Accessibility::Accessible* GetParent(); - DBus::ValueOrError> GetChildren(); - std::string GetName(); - std::string GetDescription(); - DBus::ValueOrError GetRole(); - DBus::ValueOrError GetRoleName(); - DBus::ValueOrError GetLocalizedRoleName(); - DBus::ValueOrError GetIndexInParent(); - DBus::ValueOrError> GetStates(); - DBus::ValueOrError> GetAttributes(); - DBus::ValueOrError> GetInterfaces(); - DBus::ValueOrError GetNavigableAtPoint(int32_t x, int32_t y, uint32_t coordinateType); - DBus::ValueOrError GetNeighbor(std::string root_path, int32_t direction, int32_t search_mode); - DBus::ValueOrError> GetDefaultLabelInfo(); + using ReadingMaterialType = DBus::ValueOrError< std::unordered_map, // attributes std::string, // name @@ -86,22 +83,206 @@ public: Dali::Accessibility::Accessible* // describedByObject >; + using Relation = std::tuple>; + + /** + * @copydoc Dali::Accessibility::Accessible::GetChildCount() + */ + int GetChildCount(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetChildAtIndex() + */ + DBus::ValueOrError GetChildAtIndex(int index); + + /** + * @copydoc Dali::Accessibility::Accessible::GetParent() + */ + Dali::Accessibility::Accessible* GetParent(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetChildren() + */ + DBus::ValueOrError> GetChildren(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetName() + */ + std::string GetName(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetDescription() + */ + std::string GetDescription(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetRole() + */ + DBus::ValueOrError GetRole(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetRoleName() + */ + DBus::ValueOrError GetRoleName(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetLocalizedRoleName() + */ + DBus::ValueOrError GetLocalizedRoleName(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetIndexInParent() + */ + DBus::ValueOrError GetIndexInParent(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetStates() + */ + DBus::ValueOrError> GetStates(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetAttributes() + */ + DBus::ValueOrError> GetAttributes(); + + /** + * @copydoc Dali::Accessibility::Accessible::GetInterfaces() + */ + DBus::ValueOrError> GetInterfaces(); + + /** + * @brief Gets Accessible object on which surface lies the point with given coordinates. + * + * @param[in] x X coordinate of a point + * @param[in] y Y coordinate of a point + * @param[in] coordinateType The coordinate type + * @return The array containing the Accessible object, recursive status, and deputy Accessible + */ + DBus::ValueOrError GetNavigableAtPoint(int32_t x, int32_t y, uint32_t coordinateType); + + /** + * @brief Gets Accessible object that, dependently to the given direction parameter, + * stands in navigation order immediately before/after the Accessible object being a target of this dbus call. + * + * The 'direction' parameter denotes if the neighbor object search is done forward or backward in UI elements navigation order. + * @param[in] rootPath The path of root Accessible object + * @param[in] direction 1 is forward, 0 is backward + * @param[in] searchMode BridgeAccessible::NeighborSearchMode enum + * @return The array containing the neighbor Accessible object and recursive status + */ + DBus::ValueOrError GetNeighbor(std::string rootPath, int32_t direction, int32_t searchMode); + + /** + * @brief Gets the default label information. + * + * The "Default label" is a text that could be read by screen-reader immediately + * after the navigation context has changed (window activates, popup shows up, tab changes) and before first UI element is highlighted. + * @return The array containing the default label, its role, and its attributes + * @note This is a Tizen only feature not present in upstream ATSPI. + * Feature can be enabled/disabled for particular context root object by setting value of its accessibility attribute "default_label". + */ + DBus::ValueOrError> GetDefaultLabelInfo(); + + /** + * @brief Gets Reading material information of the self object. + * @return Reading material information + */ ReadingMaterialType GetReadingMaterial(); - void SuppressScreenReader(bool) override; - DBus::ValueOrError DoGesture(Dali::Accessibility::Gesture type, int32_t xBeg, int32_t yBeg, int32_t xEnd, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime); + /** + * @copydoc Dali::Accessibility::Bridge::SuppressScreenReader() + */ + void SuppressScreenReader(bool) override; - using Relation = std::tuple>; + /** + * @copydoc Dali::Accessibility::Accessible::DoGesture() + */ + DBus::ValueOrError DoGesture(Dali::Accessibility::Gesture type, int32_t startPositionX, int32_t startPositionY, int32_t endPositionX, int32_t endPositionY, Dali::Accessibility::GestureState state, uint32_t eventTime); + + /** + * @copydoc Dali::Accessibility::Accessible::GetRelationSet() + */ DBus::ValueOrError> GetRelationSet(); private: - Dali::Accessibility::Accessible* CalculateNeighbor(Dali::Accessibility::Accessible* root, Dali::Accessibility::Accessible* start, unsigned char forward, GetNeighborSearchMode search_mode); - std::vector ValidChildrenGet(const std::vector& children, Dali::Accessibility::Accessible* start, Dali::Accessibility::Accessible* root); - Dali::Accessibility::Accessible* GetCurrentlyHighlighted(); - Dali::Accessibility::Accessible* DirectionalDepthFirstSearchTryNonDefunctSibling(bool& all_children_visited, Dali::Accessibility::Accessible* node, Dali::Accessibility::Accessible* start, Dali::Accessibility::Accessible* root, unsigned char forward); - Dali::Accessibility::Accessible* GetNextNonDefunctSibling(Dali::Accessibility::Accessible* obj, Dali::Accessibility::Accessible* start, Dali::Accessibility::Accessible* root, unsigned char forward); - Dali::Accessibility::Component* CalculateNavigableAccessibleAtPoint(Dali::Accessibility::Accessible* root, Dali::Accessibility::Point p, Dali::Accessibility::CoordinateType type, unsigned int maxRecursionDepth); - Dali::Accessibility::Component* GetObjectInRelation(Dali::Accessibility::Accessible* obj, Dali::Accessibility::RelationType ralationType); + /** + * @brief Calculates Neighbor candidate object in root node. + * + * The DFS algorithm in the method is implemented in iterative way. + * @param root The accessible root object + * @param start The start node + * @param forward If forward is 1, then it navigates forward, otherwise backward. + * @param searchMode BridgeAccessible::NeighborSearchMode enum + * @return The neighbor Accessible object + */ + Dali::Accessibility::Accessible* CalculateNeighbor(Dali::Accessibility::Accessible* root, Dali::Accessibility::Accessible* start, unsigned char forward, NeighborSearchMode searchMode); + + /** + * @brief Gets valid children accessible. + * + * @param[in] children Children accessible objects + * @param start The start node // NEED TO UPDATE! It seems not to be used anywhere in this function. + * @param root The root node // NEED To UPDATE! + * @return The valid children + */ + std::vector GetValidChildren(const std::vector& children, Dali::Accessibility::Accessible* start, Dali::Accessibility::Accessible* root); + + /** + * @brief Gets the currently highlighted accessible. + * + * @return The highlighted accessible + * @remarks This is an experimental feature and might not be supported now. + */ + Dali::Accessibility::Accessible* GetCurrentlyHighlighted(); + + /** + * @brief Finds the non defunct sibling of the node. + * + * @param[out] areAllChildrenVisited True if all children are visited + * @param[in] node The accessible object to find its non defunct sibling + * @param[in] start The start node + * @param[in] root The root node + * @param[in] forward If forward is 1, then it navigates forward, otherwise backward. + * @return The non defunct sibling accessible + * + * @note This function performs a Depth-First Search (DFS) on all children within the node. + */ + Dali::Accessibility::Accessible* FindNonDefunctSibling(bool& areAllChildrenVisited, Dali::Accessibility::Accessible* node, Dali::Accessibility::Accessible* start, Dali::Accessibility::Accessible* root, unsigned char forward); + + /** + * @brief Gets the next non defunct sibling. + * + * @param obj The accessible object to find its non defunct sibling + * @param start The start node + * @param root The root node + * @param forward If forward is 1, then it navigates forward, otherwise backward. + * @return The non defunct sibling accessible + */ + Dali::Accessibility::Accessible* GetNextNonDefunctSibling(Dali::Accessibility::Accessible* obj, Dali::Accessibility::Accessible* start, Dali::Accessibility::Accessible* root, unsigned char forward); + + /** + * @brief Gets Component object in relation. + * @param obj The accessible object to find component in its address + * @param relationType Accessibility::RelationType enum + * @return The Component object + */ + Dali::Accessibility::Component* GetObjectInRelation(Dali::Accessibility::Accessible* obj, Dali::Accessibility::RelationType relationType); + + /** + * @brief Calculates and gets Component object that can be navigable at given coordinates. + * + * This method calculates which Component should be addressed if user hits certain point in a screen. + * @param root The root node + * @param point The coordinate of a point + * @param type This type says if the coordinates of a point refer to the device screen or current window. + * @param maxRecursionDepth The maximum recursion depth count + * @return The Component object + */ + Dali::Accessibility::Component* CalculateNavigableAccessibleAtPoint(Dali::Accessibility::Accessible* root, Dali::Accessibility::Point point, Dali::Accessibility::CoordinateType type, unsigned int maxRecursionDepth); + + +protected: + bool mIsScreenReaderSuppressed = false; }; #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_ACCESSIBLE_H diff --git a/dali/internal/accessibility/bridge/bridge-action.cpp b/dali/internal/accessibility/bridge/bridge-action.cpp index 5f6189d..9db679f 100644 --- a/dali/internal/accessibility/bridge/bridge-action.cpp +++ b/dali/internal/accessibility/bridge/bridge-action.cpp @@ -35,17 +35,19 @@ void BridgeAction::RegisterInterfaces() AddFunctionToInterface(desc, "GetKeyBinding", &BridgeAction::GetActionKeyBinding); AddFunctionToInterface(desc, "DoAction", &BridgeAction::DoAction); AddFunctionToInterface(desc, "DoActionName", &BridgeAction::DoActionName); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } Action* BridgeAction::FindSelf() const { - auto s = BridgeBase::FindSelf(); - assert(s); - auto s2 = dynamic_cast(s); - if(!s2) - throw std::domain_error{"object " + s->GetAddress().ToString() + " doesn't have Action interface"}; - return s2; + auto self = BridgeBase::FindSelf(); + assert(self); + auto actionInterface = dynamic_cast(self); + if(!actionInterface) + { + throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Action interface"}; + } + return actionInterface; } DBus::ValueOrError BridgeAction::GetActionName(int32_t index) @@ -71,7 +73,6 @@ DBus::ValueOrError BridgeAction::GetActionKeyBinding(int32_t index) DBus::ValueOrError BridgeAction::GetActionCount() { return FindSelf()->GetActionCount(); - ; } DBus::ValueOrError BridgeAction::DoAction(int32_t index) diff --git a/dali/internal/accessibility/bridge/bridge-application.cpp b/dali/internal/accessibility/bridge/bridge-application.cpp index b892601..00e5c19 100644 --- a/dali/internal/accessibility/bridge/bridge-application.cpp +++ b/dali/internal/accessibility/bridge/bridge-application.cpp @@ -28,7 +28,7 @@ void BridgeApplication::RegisterInterfaces() DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceApplication}; AddGetPropertyToInterface(desc, "ToolkitName", &BridgeApplication::GetToolkitName); AddGetPropertyToInterface(desc, "Version", &BridgeApplication::GetVersion); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } Application* BridgeApplication::FindSelf() const diff --git a/dali/internal/accessibility/bridge/bridge-base.cpp b/dali/internal/accessibility/bridge/bridge-base.cpp index 1e47300..ee1987f 100644 --- a/dali/internal/accessibility/bridge/bridge-base.cpp +++ b/dali/internal/accessibility/bridge/bridge-base.cpp @@ -38,14 +38,14 @@ BridgeBase::BridgeBase() { } -void BridgeBase::addFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function functor) +void BridgeBase::AddFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function functor) { if(delay < 0) { delay = 0; } - auto it = filteredEvents.insert({{kind, obj}, {static_cast(delay * 10), {}}}); + auto it = mFilteredEvents.insert({{kind, obj}, {static_cast(delay * 10), {}}}); if(it.second) { functor(); @@ -58,13 +58,13 @@ void BridgeBase::addFilteredEvent(FilteredEvents kind, Dali::Accessibility::Acce if(!tickTimer) { tickTimer = Dali::Timer::New(100); - tickTimer.TickSignal().Connect(this, &BridgeBase::tickFilteredEvents); + tickTimer.TickSignal().Connect(this, &BridgeBase::TickFilteredEvents); } } -bool BridgeBase::tickFilteredEvents() +bool BridgeBase::TickFilteredEvents() { - for(auto it = filteredEvents.begin(); it != filteredEvents.end();) + for(auto it = mFilteredEvents.begin(); it != mFilteredEvents.end();) { if(it->second.first) { @@ -79,33 +79,33 @@ bool BridgeBase::tickFilteredEvents() } else { - it = filteredEvents.erase(it); + it = mFilteredEvents.erase(it); continue; } } ++it; } - return !filteredEvents.empty(); + return !mFilteredEvents.empty(); } -void BridgeBase::RegisteredEventsUpdate() +void BridgeBase::UpdateRegisteredEvents() { using ReturnType = std::vector>; - registry.method()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError msg) { + mRegistry.method()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError msg) { if(!msg) { LOG() << "Get registered events failed"; return; } - allowObjectBoundsChangedEvent = false; + IsBoundsChangedEventAllowed = false; ReturnType values = std::get(msg.getValues()); for(long unsigned int i = 0; i < values.size(); i++) { if(!std::get<1>(values[i]).compare("Object:BoundsChanged")) { - allowObjectBoundsChangedEvent = true; + IsBoundsChangedEventAllowed = true; } } }); @@ -125,31 +125,31 @@ BridgeBase::ForceUpResult BridgeBase::ForceUp() throw std::domain_error{std::string("failed at call '") + dbusLocators::atspi::GET_ADDRESS + "': " + addr.getError().message}; } - con = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr)); - mData->mBusName = DBus::getConnectionName(con); - dbusServer = {con}; + mConnectionPtr = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr)); + mData->mBusName = DBus::getConnectionName(mConnectionPtr); + mDbusServer = {mConnectionPtr}; { - DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Cache"}; + DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCache}; AddFunctionToInterface(desc, "GetItems", &BridgeBase::GetItems); - dbusServer.addInterface("/org/a11y/atspi/cache", desc); + mDbusServer.addInterface(AtspiDbusPathCache, desc); } { - DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Application"}; - AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::IdGet, &BridgeBase::IdSet); - dbusServer.addInterface(AtspiPath, desc); + DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceApplication}; + AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::GetId, &BridgeBase::SetId); + mDbusServer.addInterface(AtspiPath, desc); } - registry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, con}; + mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, mConnectionPtr}; - RegisteredEventsUpdate(); + UpdateRegisteredEvents(); - registry.addSignal("EventListenerRegistered", [this](void) { - RegisteredEventsUpdate(); + mRegistry.addSignal("EventListenerRegistered", [this](void) { + UpdateRegisteredEvents(); }); - registry.addSignal("EventListenerDeregistered", [this](void) { - RegisteredEventsUpdate(); + mRegistry.addSignal("EventListenerDeregistered", [this](void) { + UpdateRegisteredEvents(); }); return ForceUpResult::JUST_STARTED; @@ -158,9 +158,9 @@ BridgeBase::ForceUpResult BridgeBase::ForceUp() void BridgeBase::ForceDown() { Bridge::ForceDown(); - registry = {}; - dbusServer = {}; - con = {}; + mRegistry = {}; + mDbusServer = {}; + mConnectionPtr = {}; } const std::string& BridgeBase::GetBusName() const @@ -183,11 +183,11 @@ Accessible* BridgeBase::FindByPath(const std::string& name) const void BridgeBase::AddPopup(Accessible* object) { - if(std::find(popups.begin(), popups.end(), object) != popups.end()) + if(std::find(mPopups.begin(), mPopups.end(), object) != mPopups.end()) { return; } - popups.push_back(object); + mPopups.push_back(object); if(IsUp()) { object->Emit(WindowEvent::ACTIVATE, 0); @@ -196,39 +196,40 @@ void BridgeBase::AddPopup(Accessible* object) void BridgeBase::RemovePopup(Accessible* object) { - auto it = std::find(popups.begin(), popups.end(), object); - if(it == popups.end()) + auto it = std::find(mPopups.begin(), mPopups.end(), object); + if(it == mPopups.end()) { return; } - popups.erase(it); + mPopups.erase(it); + if(IsUp()) { object->Emit(WindowEvent::DEACTIVATE, 0); - if(popups.empty()) + if(mPopups.empty()) { - application.children.back()->Emit(WindowEvent::ACTIVATE, 0); + mApplication.mChildren.back()->Emit(WindowEvent::ACTIVATE, 0); } else { - popups.back()->Emit(WindowEvent::ACTIVATE, 0); + mPopups.back()->Emit(WindowEvent::ACTIVATE, 0); } } } void BridgeBase::AddTopLevelWindow(Accessible* root) { - application.children.push_back(root); + mApplication.mChildren.push_back(root); SetIsOnRootLevel(root); } void BridgeBase::RemoveTopLevelWindow(Accessible* root) { - for(auto i = 0u; i < application.children.size(); ++i) + for(auto i = 0u; i < mApplication.mChildren.size(); ++i) { - if(application.children[i] == root) + if(mApplication.mChildren[i] == root) { - application.children.erase(application.children.begin() + i); + mApplication.mChildren.erase(mApplication.mChildren.begin() + i); break; } } @@ -244,7 +245,7 @@ Accessible* BridgeBase::Find(const std::string& path) const { if(path == "root") { - return &application; + return &mApplication; } void* accessible; @@ -288,19 +289,19 @@ Accessible* BridgeBase::FindSelf() const return Find(StripPrefix(path)); } -void BridgeBase::IdSet(int id) +void BridgeBase::SetId(int id) { - this->id = id; + this->mId = id; } -int BridgeBase::IdGet() +int BridgeBase::GetId() { - return this->id; + return this->mId; } auto BridgeBase::GetItems() -> DBus::ValueOrError> { - auto root = &application; + auto root = &mApplication; std::vector res; @@ -323,7 +324,7 @@ auto BridgeBase::CreateCacheElement(Accessible* item) -> CacheElementType return {}; } - auto root = &application; + auto root = &mApplication; auto parent = item->GetParent(); std::vector
children; diff --git a/dali/internal/accessibility/bridge/bridge-base.h b/dali/internal/accessibility/bridge/bridge-base.h index 0396539..2c06249 100644 --- a/dali/internal/accessibility/bridge/bridge-base.h +++ b/dali/internal/accessibility/bridge/bridge-base.h @@ -26,16 +26,19 @@ // INTERNAL INCLUDES #include +/** + * @brief The AppAccessible class is to define Accessibility Application. + */ class AppAccessible : public virtual Dali::Accessibility::Accessible, public virtual Dali::Accessibility::Collection, public virtual Dali::Accessibility::Application { public: - Dali::Accessibility::EmptyAccessibleWithAddress parent; - std::vector children; - std::string name; + Dali::Accessibility::EmptyAccessibleWithAddress mParent; + std::vector mChildren; + std::string mName; std::string GetName() override { - return name; + return mName; } std::string GetDescription() override @@ -45,20 +48,22 @@ public: Dali::Accessibility::Accessible* GetParent() override { - return &parent; + return &mParent; } size_t GetChildCount() override { - return children.size(); + return mChildren.size(); } Dali::Accessibility::Accessible* GetChildAtIndex(size_t index) override { - auto s = children.size(); - if(index >= s) - throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(s) + " children"}; - return children[index]; + auto size = mChildren.size(); + if(index >= size) + { + throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(size) + " children"}; + } + return mChildren[index]; } size_t GetIndexInParent() override @@ -81,9 +86,15 @@ public: return {}; } - Dali::Accessibility::Accessible* getActiveWindow() + /** + * @brief Gets the active window. + * + * @return Null if mChildren is empty, otherwise the active window + * @note Currently, the default window would be returned when mChildren is not empty. + */ + Dali::Accessibility::Accessible* GetActiveWindow() { - return children.empty() ? nullptr : children[0]; + return mChildren.empty() ? nullptr : mChildren[0]; } bool DoGesture(const Dali::Accessibility::GestureInfo& gestureInfo) override @@ -112,43 +123,88 @@ public: } }; +/** + * @brief Enumeration for FilteredEvents. + */ enum class FilteredEvents { - boundsChanged + BOUNDS_CHANGED ///< Bounds changed }; +// Custom specialization of std::hash namespace std { template<> struct hash> { - size_t operator()(std::pair v) const + size_t operator()(std::pair value) const { - return (static_cast(v.first) * 131) ^ reinterpret_cast(v.second); + return (static_cast(value.first) * 131) ^ reinterpret_cast(value.second); } }; } // namespace std +/** + * @brief The BridgeBase class is basic class for Bridge functions. + */ class BridgeBase : public Dali::Accessibility::Bridge, public Dali::ConnectionTracker { - std::unordered_map, std::pair>> filteredEvents; + std::unordered_map, std::pair>> mFilteredEvents; - bool tickFilteredEvents(); + /** + * @brief Removes all FilteredEvents using Tick signal. + * + * @return False if mFilteredEvents is empty, otherwise true. + */ + bool TickFilteredEvents(); public: - void addFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function functor); - + /** + * @brief Adds FilteredEvents, Accessible, and delay time to mFilteredEvents. + * + * @param[in] kind FilteredEvents enum value + * @param[in] obj Accessible object + * @param[in] delay The delay time + * @param[in] functor The function to be called // NEED TO UPDATE! + */ + void AddFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function functor); + + /** + * @copydoc Dali::Accessibility::Bridge::GetBusName() + */ const std::string& GetBusName() const override; - void AddTopLevelWindow(Dali::Accessibility::Accessible* window) override; - void RemoveTopLevelWindow(Dali::Accessibility::Accessible* window) override; - void AddPopup(Dali::Accessibility::Accessible* object) override; - void RemovePopup(Dali::Accessibility::Accessible* object) override; + /** + * @copydoc Dali::Accessibility::Bridge::AddTopLevelWindow() + */ + void AddTopLevelWindow(Dali::Accessibility::Accessible* window) override; + + /** + * @copydoc Dali::Accessibility::Bridge::RemoveTopLevelWindow() + */ + void RemoveTopLevelWindow(Dali::Accessibility::Accessible* window) override; + + /** + * @copydoc Dali::Accessibility::Bridge::AddPopup() + */ + void AddPopup(Dali::Accessibility::Accessible* object) override; + + /** + * @copydoc Dali::Accessibility::Bridge::RemovePopup() + */ + void RemovePopup(Dali::Accessibility::Accessible* object) override; + + /** + * @copydoc Dali::Accessibility::Bridge::GetApplication() + */ Dali::Accessibility::Accessible* GetApplication() const override { - return &application; + return &mApplication; } + /** + * @brief Adds function to dbus interface. + */ template void AddFunctionToInterface( DBus::DBusInterfaceDescription& desc, const std::string& funcName, DBus::ValueOrError (SELF::*funcPtr)(ARGS...)) @@ -168,6 +224,9 @@ public: }); } + /** + * @brief Adds 'Get' property to dbus interface. + */ template void AddGetPropertyToInterface(DBus::DBusInterfaceDescription& desc, const std::string& funcName, @@ -188,6 +247,9 @@ public: {}); } + /** + * @brief Adds 'Set' property to dbus interface. + */ template void AddSetPropertyToInterface(DBus::DBusInterfaceDescription& desc, const std::string& funcName, @@ -207,6 +269,9 @@ public: }); } + /** + * @brief Adds 'Set' and 'Get' properties to dbus interface. + */ template void AddGetSetPropertyToInterface(DBus::DBusInterfaceDescription& desc, const std::string& funcName, @@ -238,6 +303,10 @@ public: } }); } + + /** + * @brief Adds 'Get' and 'Set' properties to dbus interface. + */ template void AddGetSetPropertyToInterface(DBus::DBusInterfaceDescription& desc, const std::string& funcName, @@ -269,25 +338,78 @@ public: } }); } + + /** + * @brief Gets the string of the path excluding the specified prefix. + * + * @param path The path to get + * @return The string stripped of the specific prefix + */ static std::string StripPrefix(const std::string& path); + /** + * @brief Finds the Accessible object according to the path. + * + * @param[in] path The path for Accessible object + * @return The Accessible object corresponding to the path + */ Dali::Accessibility::Accessible* Find(const std::string& path) const; + + /** + * @brief Finds the Accessible object with the given address. + * + * @param[in] ptr The unique Address of the object + * @return The Accessible object corresponding to the path + */ Dali::Accessibility::Accessible* Find(const Dali::Accessibility::Address& ptr) const; + + /** + * @brief Returns the target object of the currently executed DBus method call. + * + * And any subclasses redefine `FindSelf` with a different return type as a convenient wrapper around dynamic_cast. + * @return The Accessible object + * @note When a DBus method is called on some object, this target object (`currentObject`) is temporarily saved by the bridge, + * because DBus handles the invocation target separately from the method arguments. + * We then use the saved object inside the 'glue' method (e.g. BridgeValue::GetMinimum) + * to call the equivalent method on the respective C++ object (this could be ScrollBar::AccessibleImpl::GetMinimum in the example given). + */ Dali::Accessibility::Accessible* FindSelf() const; + + /** + * @copydoc Dali::Accessibility::Bridge::FindByPath() + */ Dali::Accessibility::Accessible* FindByPath(const std::string& name) const override; - void SetApplicationName(std::string name) override + + /** + * @copydoc Dali::Accessibility::Bridge::SetApplicationName() + */ + void SetApplicationName(std::string name) override { - application.name = std::move(name); + mApplication.mName = std::move(name); } protected: - mutable AppAccessible application; - std::vector popups; + mutable AppAccessible mApplication; + std::vector mPopups; private: - void IdSet(int id); - int IdGet(); - void RegisteredEventsUpdate(); + + /** + * @brief Sets an ID. + * @param[in] id An ID (integer value) + */ + void SetId(int id); + + /** + * @brief Gets the ID. + * @return The ID to be set + */ + int GetId(); + + /** + * @brief Update registered events. + */ + void UpdateRegisteredEvents(); using CacheElementType = std::tuple< Dali::Accessibility::Address, @@ -299,21 +421,45 @@ private: Dali::Accessibility::Role, std::string, std::array>; + + /** + * @brief Gets Items // NEED TO UPDATE! + * + * @return + */ DBus::ValueOrError> GetItems(); - CacheElementType CreateCacheElement(Dali::Accessibility::Accessible* item); + + /** + * @brief Creates CacheElement. + * + * CreateCacheElement method works for GetItems which is a part of ATSPI protocol. + * ATSPI client library (libatspi from at-spi2-core) depending on cacheing policy configuration uses GetItems + * to pre-load entire accessible tree from application to its own cache in single dbus call. + * Otherwise the particular nodes in a tree are cached lazily when client library tries to access them. + * @param item Accessible to get information + * @return The elements to be cached + */ + CacheElementType CreateCacheElement(Dali::Accessibility::Accessible* item); protected: BridgeBase(); virtual ~BridgeBase(); + /** + * @copydoc Dali::Accessibility::Bridge::ForceUp() + */ ForceUpResult ForceUp() override; - void ForceDown() override; - DBus::DBusServer dbusServer; - DBusWrapper::ConnectionPtr con; - int id = 0; - DBus::DBusClient registry; - bool allowObjectBoundsChangedEvent{false}; + /** + * @copydoc Dali::Accessibility::Bridge::ForceDown() + */ + void ForceDown() override; + + DBus::DBusServer mDbusServer; + DBusWrapper::ConnectionPtr mConnectionPtr; + int mId = 0; + DBus::DBusClient mRegistry; + bool IsBoundsChangedEventAllowed{false}; }; #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H diff --git a/dali/internal/accessibility/bridge/bridge-collection.cpp b/dali/internal/accessibility/bridge/bridge-collection.cpp index b2e0f06..8252465 100644 --- a/dali/internal/accessibility/bridge/bridge-collection.cpp +++ b/dali/internal/accessibility/bridge/bridge-collection.cpp @@ -30,17 +30,19 @@ void BridgeCollection::RegisterInterfaces() { DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCollection}; AddFunctionToInterface(desc, "GetMatches", &BridgeCollection::GetMatches); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } Collection* BridgeCollection::FindSelf() const { - auto s = BridgeBase::FindSelf(); - assert(s); - auto s2 = dynamic_cast(s); - if(!s2) - throw std::domain_error{"object " + s->GetAddress().ToString() + " doesn't have Collection interface"}; - return s2; + auto self = BridgeBase::FindSelf(); + assert(self); + auto collectionInterface = dynamic_cast(self); + if(!collectionInterface) + { + throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Collection interface"}; + } + return collectionInterface; } enum @@ -102,20 +104,26 @@ struct BridgeCollection::Comparer { requested = {std::get(*rule).begin(), std::get(*rule).end()}; } + void Update(Accessible* obj) { object.clear(); - for(auto& q : obj->GetInterfaces()) - object.insert(std::move(q)); + for(auto& interface : obj->GetInterfaces()) + { + object.insert(std::move(interface)); + } } + bool RequestEmpty() const { return requested.empty(); } + bool ObjectEmpty() const { return object.empty(); } + bool Compare(CompareFuncExit exit) { bool foundAny = false; @@ -123,13 +131,19 @@ struct BridgeCollection::Comparer { bool found = (object.find(iname) != object.end()); if(found) + { foundAny = true; + } + if(found == (exit == CompareFuncExit::FIRST_FOUND)) + { return found; + } } return foundAny; } - }; + }; // ComparerInterfaces struct + struct ComparerAttributes { std::unordered_map requested, object; @@ -140,18 +154,22 @@ struct BridgeCollection::Comparer { requested = std::get(*rule); } + void Update(Accessible* obj) { object = obj->GetAttributes(); } + bool RequestEmpty() const { return requested.empty(); } + bool ObjectEmpty() const { return object.empty(); } + bool Compare(CompareFuncExit exit) { bool foundAny = false; @@ -160,7 +178,10 @@ struct BridgeCollection::Comparer auto it = object.find(iname.first); bool found = it != object.end() && iname.second == it->second; if(found) + { foundAny = true; + } + if(found == (exit == CompareFuncExit::FIRST_FOUND)) { return found; @@ -168,7 +189,8 @@ struct BridgeCollection::Comparer } return foundAny; } - }; + }; // ComparerAttributes struct + struct ComparerRoles { using Roles = BitSets<4, Role>; @@ -180,20 +202,24 @@ struct BridgeCollection::Comparer { requested = Roles{std::get(*rule)}; } + void Update(Accessible* obj) { object = {}; object[obj->GetRole()] = true; assert(object); } + bool RequestEmpty() const { return !requested; } + bool ObjectEmpty() const { return !object; } + bool Compare(CompareFuncExit exit) { switch(mode) @@ -218,7 +244,8 @@ struct BridgeCollection::Comparer } return false; } - }; + }; // ComparerRoles struct + struct ComparerStates { States requested, object; @@ -229,18 +256,22 @@ struct BridgeCollection::Comparer { requested = States{std::get(*rule)}; } + void Update(Accessible* obj) { object = obj->GetStates(); } + bool RequestEmpty() const { return !requested; } + bool ObjectEmpty() const { return !object; } + bool Compare(CompareFuncExit exit) { switch(mode) @@ -265,42 +296,57 @@ struct BridgeCollection::Comparer } return false; } - }; + }; // ComparerStates struct template - bool compareFunc(T& cmp, Accessible* obj) + bool CompareFunc(T& cmp, Accessible* obj) { if(cmp.mode == Mode::INVALID) + { return true; + } + cmp.Update(obj); switch(cmp.mode) { case Mode::ANY: { if(cmp.RequestEmpty() || cmp.ObjectEmpty()) + { return false; + } break; } case Mode::ALL: { if(cmp.RequestEmpty()) + { return true; + } if(cmp.ObjectEmpty()) + { return false; + } break; } case Mode::NONE: { if(cmp.RequestEmpty() || cmp.ObjectEmpty()) + { return true; + } break; } case Mode::EMPTY: { if(cmp.RequestEmpty() && cmp.ObjectEmpty()) + { return true; + } if(cmp.RequestEmpty() || cmp.ObjectEmpty()) + { return false; + } break; } case Mode::INVALID: @@ -315,19 +361,25 @@ struct BridgeCollection::Comparer case Mode::ALL: { if(!cmp.Compare(CompareFuncExit::FIRST_NOT_FOUND)) + { return false; + } break; } case Mode::ANY: { if(cmp.Compare(CompareFuncExit::FIRST_FOUND)) + { return true; + } break; } case Mode::NONE: { if(cmp.Compare(CompareFuncExit::FIRST_FOUND)) + { return false; + } break; } case Mode::INVALID: @@ -355,38 +407,44 @@ struct BridgeCollection::Comparer return false; } - ComparerInterfaces ci; - ComparerAttributes ca; - ComparerRoles cr; - ComparerStates cs; + ComparerInterfaces interface; + ComparerAttributes attribute; + ComparerRoles role; + ComparerStates state; Comparer(MatchRule* mr) - : ci(mr), - ca(mr), - cr(mr), - cs(mr) + : interface(mr), + attribute(mr), + role(mr), + state(mr) { } bool operator()(Accessible* obj) { - return compareFunc(ci, obj) && - compareFunc(ca, obj) && - compareFunc(cr, obj) && - compareFunc(cs, obj); + return CompareFunc(interface, obj) && + CompareFunc(attribute, obj) && + CompareFunc(role, obj) && + CompareFunc(state, obj); } -}; +}; // BridgeCollection::Comparer struct void BridgeCollection::VisitNodes(Accessible* obj, std::vector& result, Comparer& cmp, size_t maxCount) { if(maxCount > 0 && result.size() >= maxCount) + { return; + } if(cmp(obj)) + { result.emplace_back(obj); + } for(auto i = 0u; i < obj->GetChildCount(); ++i) + { VisitNodes(obj->GetChildAtIndex(i), result, cmp, maxCount); + } } DBus::ValueOrError > BridgeCollection::GetMatches(MatchRule rule, uint32_t sortBy, int32_t count, bool traverse) diff --git a/dali/internal/accessibility/bridge/bridge-component.cpp b/dali/internal/accessibility/bridge/bridge-component.cpp index d373bcf..64694ca 100644 --- a/dali/internal/accessibility/bridge/bridge-component.cpp +++ b/dali/internal/accessibility/bridge/bridge-component.cpp @@ -36,7 +36,7 @@ void BridgeComponent::RegisterInterfaces() // https://gitlab.gnome.org/GNOME/at-spi2-core/-/blob/master/xml/Component.xml DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceComponent}; - AddFunctionToInterface(desc, "Contains", &BridgeComponent::IsAccessibleContainedAtPoint); + AddFunctionToInterface(desc, "Contains", &BridgeComponent::IsAccessibleContainingPoint); AddFunctionToInterface(desc, "GetAccessibleAtPoint", &BridgeComponent::GetAccessibleAtPoint); AddFunctionToInterface(desc, "GetExtents", &BridgeComponent::GetExtents); AddFunctionToInterface(desc, "GetPosition", &BridgeComponent::GetPosition); @@ -47,62 +47,74 @@ void BridgeComponent::RegisterInterfaces() AddFunctionToInterface(desc, "GrabHighlight", &BridgeComponent::GrabHighlight); AddFunctionToInterface(desc, "GrabFocus", &BridgeComponent::GrabFocus); AddFunctionToInterface(desc, "ClearHighlight", &BridgeComponent::ClearHighlight); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } Component* BridgeComponent::FindSelf() const { - auto s = BridgeBase::FindSelf(); - assert(s); - auto s2 = dynamic_cast(s); - if(!s2) - throw std::domain_error{"object " + s->GetAddress().ToString() + " doesn't have Component interface"}; - return s2; + auto self = BridgeBase::FindSelf(); + assert(self); + auto componentInterface = dynamic_cast(self); + if(!componentInterface) + { + throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Component interface"}; + } + return componentInterface; } -DBus::ValueOrError BridgeComponent::IsAccessibleContainedAtPoint(int32_t x, int32_t y, uint32_t coordType) +DBus::ValueOrError BridgeComponent::IsAccessibleContainingPoint(int32_t x, int32_t y, uint32_t coordType) { - return FindSelf()->IsAccessibleContainedAtPoint({x, y}, static_cast(coordType)); + return FindSelf()->IsAccessibleContainingPoint({x, y}, static_cast(coordType)); } + DBus::ValueOrError BridgeComponent::GetAccessibleAtPoint(int32_t x, int32_t y, uint32_t coordType) { return FindSelf()->GetAccessibleAtPoint({x, y}, static_cast(coordType)); } + DBus::ValueOrError > BridgeComponent::GetExtents(uint32_t coordType) { - auto p = FindSelf()->GetExtents(static_cast(coordType)); - return std::tuple{p.x, p.y, p.width, p.height}; + auto rect = FindSelf()->GetExtents(static_cast(coordType)); + return std::tuple{rect.x, rect.y, rect.width, rect.height}; } + DBus::ValueOrError BridgeComponent::GetPosition(uint32_t coordType) { - auto p = FindSelf()->GetExtents(static_cast(coordType)); - return {static_cast(p.x), static_cast(p.y)}; + auto rect = FindSelf()->GetExtents(static_cast(coordType)); + return {static_cast(rect.x), static_cast(rect.y)}; } + DBus::ValueOrError BridgeComponent::GetSize(uint32_t coordType) { - auto p = FindSelf()->GetExtents(static_cast(coordType)); - return {static_cast(p.width), static_cast(p.height)}; + auto rect = FindSelf()->GetExtents(static_cast(coordType)); + return {static_cast(rect.width), static_cast(rect.height)}; } + DBus::ValueOrError BridgeComponent::GetLayer() { return FindSelf()->GetLayer(); } + DBus::ValueOrError BridgeComponent::GetAlpha() { return FindSelf()->GetAlpha(); } + DBus::ValueOrError BridgeComponent::GrabFocus() { return FindSelf()->GrabFocus(); } + DBus::ValueOrError BridgeComponent::GrabHighlight() { return FindSelf()->GrabHighlight(); } + DBus::ValueOrError BridgeComponent::ClearHighlight() { return FindSelf()->ClearHighlight(); } + DBus::ValueOrError BridgeComponent::GetMdiZOrder() { return FindSelf()->GetMdiZOrder(); diff --git a/dali/internal/accessibility/bridge/bridge-component.h b/dali/internal/accessibility/bridge/bridge-component.h index 4231843..8fa2708 100644 --- a/dali/internal/accessibility/bridge/bridge-component.h +++ b/dali/internal/accessibility/bridge/bridge-component.h @@ -38,7 +38,7 @@ protected: Dali::Accessibility::Component* FindSelf() const; public: - DBus::ValueOrError IsAccessibleContainedAtPoint(int32_t x, int32_t y, uint32_t coordType); + DBus::ValueOrError IsAccessibleContainingPoint(int32_t x, int32_t y, uint32_t coordType); DBus::ValueOrError GetAccessibleAtPoint(int32_t x, int32_t y, uint32_t coordType); DBus::ValueOrError > GetExtents(uint32_t coordType); DBus::ValueOrError GetPosition(uint32_t coordType); diff --git a/dali/internal/accessibility/bridge/bridge-editable-text.cpp b/dali/internal/accessibility/bridge/bridge-editable-text.cpp index bda4a28..33ff63d 100644 --- a/dali/internal/accessibility/bridge/bridge-editable-text.cpp +++ b/dali/internal/accessibility/bridge/bridge-editable-text.cpp @@ -32,17 +32,19 @@ void BridgeEditableText::RegisterInterfaces() AddFunctionToInterface(desc, "InsertText", &BridgeEditableText::InsertText); AddFunctionToInterface(desc, "PasteText", &BridgeEditableText::PasteText); AddFunctionToInterface(desc, "SetTextContents", &BridgeEditableText::SetTextContents); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } EditableText* BridgeEditableText::FindSelf() const { - auto s = BridgeBase::FindSelf(); - assert(s); - auto s2 = dynamic_cast(s); - if(!s2) - throw std::domain_error{"object " + s->GetAddress().ToString() + " doesn't have Text interface"}; - return s2; + auto self = BridgeBase::FindSelf(); + assert(self); + auto editableTextInterface = dynamic_cast(self); + if(!editableTextInterface) + { + throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Text interface"}; + } + return editableTextInterface; } DBus::ValueOrError BridgeEditableText::CopyText(int32_t startPos, int32_t endPos) diff --git a/dali/internal/accessibility/bridge/bridge-impl.cpp b/dali/internal/accessibility/bridge/bridge-impl.cpp index 9724368..a4144ab 100644 --- a/dali/internal/accessibility/bridge/bridge-impl.cpp +++ b/dali/internal/accessibility/bridge/bridge-impl.cpp @@ -43,6 +43,9 @@ using namespace Dali::Accessibility; +/** + * @brief The BridgeImpl class is to implement some Bridge functions. + */ class BridgeImpl : public virtual BridgeBase, public BridgeAccessible, public BridgeObject, @@ -55,21 +58,25 @@ class BridgeImpl : public virtual BridgeBase, public BridgeSelection, public BridgeApplication { - DBus::DBusClient accessibilityStatusClient; - DBus::DBusClient registryClient, directReadingClient; - bool screenReaderEnabled = false; - bool isEnabled = false; - bool isShown = false; - std::unordered_map> directReadingCallbacks; - Dali::Actor highlightedActor; - std::function highlightClearAction; - Dali::CallbackBase* mIdleCallback = NULL; + DBus::DBusClient mAccessibilityStatusClient; + DBus::DBusClient mRegistryClient; + DBus::DBusClient mDirectReadingClient; + bool mIsScreenReaderEnabled = false; + bool mIsEnabled = false; + bool mIsShown = false; + std::unordered_map> mDirectReadingCallbacks; + Dali::Actor mHighlightedActor; + std::function mHighlightClearAction; + Dali::CallbackBase* mIdleCallback = NULL; public: BridgeImpl() { } + /** + * @copydoc Dali::Accessibility::Bridge::Emit() + */ Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override { if(!IsUp()) @@ -96,8 +103,9 @@ public: return Consumed::NO; } } - auto m = registryClient.method)>("NotifyListenersSync"); - auto result = m.call(std::tuple{keyType, 0, static_cast(keyCode), 0, static_cast(timeStamp), keyName, isText ? 1 : 0}); + + auto methodObject = mRegistryClient.method)>("NotifyListenersSync"); + auto result = methodObject.call(std::tuple{keyType, 0, static_cast(keyCode), 0, static_cast(timeStamp), keyName, isText ? 1 : 0}); if(!result) { LOG() << result.getError().message; @@ -106,6 +114,9 @@ public: return std::get<0>(result) ? Consumed::YES : Consumed::NO; } + /** + * @copydoc Dali::Accessibility::Bridge::Pause() + */ void Pause() override { if(!IsUp()) @@ -113,7 +124,7 @@ public: return; } - directReadingClient.method(bool)>("PauseResume").asyncCall([](DBus::ValueOrError msg) { + mDirectReadingClient.method(bool)>("PauseResume").asyncCall([](DBus::ValueOrError msg) { if(!msg) { LOG() << "Direct reading command failed (" << msg.getError().message << ")"; @@ -122,6 +133,9 @@ public: true); } + /** + * @copydoc Dali::Accessibility::Bridge::Resume() + */ void Resume() override { if(!IsUp()) @@ -129,7 +143,7 @@ public: return; } - directReadingClient.method(bool)>("PauseResume").asyncCall([](DBus::ValueOrError msg) { + mDirectReadingClient.method(bool)>("PauseResume").asyncCall([](DBus::ValueOrError msg) { if(!msg) { LOG() << "Direct reading command failed (" << msg.getError().message << ")"; @@ -138,6 +152,9 @@ public: false); } + /** + * @copydoc Dali::Accessibility::Bridge::StopReading() + */ void StopReading(bool alsoNonDiscardable) override { if(!IsUp()) @@ -145,7 +162,7 @@ public: return; } - directReadingClient.method(bool)>("StopReading").asyncCall([](DBus::ValueOrError msg) { + mDirectReadingClient.method(bool)>("StopReading").asyncCall([](DBus::ValueOrError msg) { if(!msg) { LOG() << "Direct reading command failed (" << msg.getError().message << ")"; @@ -154,6 +171,9 @@ public: alsoNonDiscardable); } + /** + * @copydoc Dali::Accessibility::Bridge::Say() + */ void Say(const std::string& text, bool discardable, std::function callback) override { if(!IsUp()) @@ -161,20 +181,23 @@ public: return; } - directReadingClient.method(std::string, bool)>("ReadCommand").asyncCall([=](DBus::ValueOrError msg) { + mDirectReadingClient.method(std::string, bool)>("ReadCommand").asyncCall([=](DBus::ValueOrError msg) { if(!msg) { LOG() << "Direct reading command failed (" << msg.getError().message << ")"; } else if(callback) { - directReadingCallbacks.emplace(std::get<2>(msg), callback); + mDirectReadingCallbacks.emplace(std::get<2>(msg), callback); } }, text, discardable); } + /** + * @copydoc Dali::Accessibility::Bridge::ForceDown() + */ void ForceDown() override { if(mData) @@ -186,14 +209,17 @@ public: mData->mCurrentlyHighlightedActor = {}; mData->mHighlightActor = {}; } - highlightedActor = {}; - highlightClearAction = {}; + mHighlightedActor = {}; + mHighlightClearAction = {}; BridgeAccessible::ForceDown(); - registryClient = {}; - directReadingClient = {}; - directReadingCallbacks.clear(); + mRegistryClient = {}; + mDirectReadingClient = {}; + mDirectReadingCallbacks.clear(); } + /** + * @copydoc Dali::Accessibility::Bridge::Terminate() + */ void Terminate() override { if(mData) @@ -206,11 +232,14 @@ public: { Dali::Adaptor::Get().RemoveIdle(mIdleCallback); } - accessibilityStatusClient = {}; - dbusServer = {}; - con = {}; + mAccessibilityStatusClient = {}; + mDbusServer = {}; + mConnectionPtr = {}; } + /** + * @copydoc Dali::Accessibility::Bridge::ForceUp() + */ ForceUpResult ForceUp() override { if(BridgeAccessible::ForceUp() == ForceUpResult::ALREADY_UP) @@ -229,21 +258,24 @@ public: BridgeSelection::RegisterInterfaces(); BridgeApplication::RegisterInterfaces(); - RegisterOnBridge(&application); + RegisterOnBridge(&mApplication); + + mRegistryClient = {AtspiDbusNameRegistry, AtspiDbusPathDec, AtspiDbusInterfaceDec, mConnectionPtr}; + mDirectReadingClient = DBus::DBusClient{DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, mConnectionPtr}; - registryClient = {AtspiDbusNameRegistry, AtspiDbusPathDec, AtspiDbusInterfaceDec, con}; - directReadingClient = DBus::DBusClient{DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, con}; - directReadingClient.addSignal("ReadingStateChanged", [=](int32_t id, std::string readingState) { - auto it = directReadingCallbacks.find(id); - if(it != directReadingCallbacks.end()) + mDirectReadingClient.addSignal("ReadingStateChanged", [=](int32_t id, std::string readingState) { + auto it = mDirectReadingCallbacks.find(id); + if(it != mDirectReadingCallbacks.end()) { it->second(readingState); if(readingState != "ReadingPaused" && readingState != "ReadingResumed" && readingState != "ReadingStarted") - directReadingCallbacks.erase(it); + { + mDirectReadingCallbacks.erase(it); + } } }); - auto proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, AtspiDbusInterfaceSocket, con}; + auto proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, AtspiDbusInterfaceSocket, mConnectionPtr}; Address root{"", "root"}; auto res = proxy.method("Embed").call(root); if(!res) @@ -251,72 +283,93 @@ public: LOG() << "Call to Embed failed: " << res.getError().message; } assert(res); - application.parent.SetAddress(std::move(std::get<0>(res))); - if(isShown) + + mApplication.mParent.SetAddress(std::move(std::get<0>(res))); + if(mIsShown) { EmitActivate(); } return ForceUpResult::JUST_STARTED; } + /** + * @brief Sends a signal to dbus that the default window is activated. + * + * TODO : This is subject to change if/when we implement multi-window support. + * @see BridgeObject::Emit() + */ void EmitActivate() { - auto win = application.getActiveWindow(); + auto win = mApplication.GetActiveWindow(); if(win) { win->Emit(WindowEvent::ACTIVATE, 0); } } + /** + * @brief Sends a signal to dbus that the default window is deactivated. + * + * TODO : This is subject to change if/when we implement multi-window support. + * @see BridgeObject::Emit() + */ void EmitDeactivate() { - auto win = application.getActiveWindow(); + auto win = mApplication.GetActiveWindow(); if(win) { win->Emit(WindowEvent::DEACTIVATE, 0); } } + /** + * @copydoc Dali::Accessibility::Bridge::WindowHidden() + */ void WindowHidden() override { - if(isShown && IsUp()) + if(mIsShown && IsUp()) { EmitDeactivate(); } - isShown = false; + mIsShown = false; } + /** + * @copydoc Dali::Accessibility::Bridge::WindowShown() + */ void WindowShown() override { - if(!isShown && IsUp()) + if(!mIsShown && IsUp()) { EmitActivate(); } - isShown = true; + mIsShown = true; } void ReadAndListenProperty() { // read property - auto enabled = accessibilityStatusClient.property("ScreenReaderEnabled").get(); + auto enabled = mAccessibilityStatusClient.property("ScreenReaderEnabled").get(); if(enabled) { - screenReaderEnabled = std::get<0>(enabled); + mIsScreenReaderEnabled = std::get<0>(enabled); } - enabled = accessibilityStatusClient.property("IsEnabled").get(); + + enabled = mAccessibilityStatusClient.property("IsEnabled").get(); if(enabled) { - isEnabled = std::get<0>(enabled); + mIsEnabled = std::get<0>(enabled); } - if(screenReaderEnabled || isEnabled) + + if(mIsScreenReaderEnabled || mIsEnabled) { ForceUp(); } // listen property change - accessibilityStatusClient.addPropertyChangedEvent("ScreenReaderEnabled", [this](bool res) { - screenReaderEnabled = res; - if(screenReaderEnabled || isEnabled) + mAccessibilityStatusClient.addPropertyChangedEvent("ScreenReaderEnabled", [this](bool res) { + mIsScreenReaderEnabled = res; + if(mIsScreenReaderEnabled || mIsEnabled) { ForceUp(); } @@ -326,9 +379,9 @@ public: } }); - accessibilityStatusClient.addPropertyChangedEvent("IsEnabled", [this](bool res) { - isEnabled = res; - if(screenReaderEnabled || isEnabled) + mAccessibilityStatusClient.addPropertyChangedEvent("IsEnabled", [this](bool res) { + mIsEnabled = res; + if(mIsScreenReaderEnabled || mIsEnabled) { ForceUp(); } @@ -341,9 +394,9 @@ public: bool InitializeAccessibilityStatusClient() { - accessibilityStatusClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION}; + mAccessibilityStatusClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION}; - if (!accessibilityStatusClient) + if (!mAccessibilityStatusClient) { DALI_LOG_ERROR("Accessibility Status DbusClient is not ready\n"); return false; @@ -364,6 +417,9 @@ public: return true; } + /** + * @copydoc Dali::Accessibility::Bridge::Initialize() + */ void Initialize() override { if ( InitializeAccessibilityStatusClient() ) @@ -384,22 +440,37 @@ public: } } - bool GetScreenReaderEnabled() + /** + * @copydoc Dali::Accessibility::Bridge::GetScreenReaderEnabled() + */ + bool GetScreenReaderEnabled() override { - return screenReaderEnabled; + return mIsScreenReaderEnabled; } - bool IsEnabled() + /** + * @copydoc Dali::Accessibility::Bridge::IsEnabled() + */ + bool IsEnabled() override { - return isEnabled; + return mIsEnabled; } -}; +}; // BridgeImpl -static bool bridgeInitialized; +namespace // unnamed namespace +{ + +bool INITIALIZED_BRIDGE = false; -static Bridge* CreateBridge() +/** + * @brief Creates BridgeImpl instance. + * + * @return The BridgeImpl instance + * @note This method is to check environment variable first. If ATSPI is disable using env, it returns dummy bridge instance. + */ +Bridge* CreateBridge() { - bridgeInitialized = true; + INITIALIZED_BRIDGE = true; try { @@ -419,6 +490,10 @@ static Bridge* CreateBridge() } } +} // unnamed namespace + +// Dali::Accessibility::Bridge class implementation + Bridge* Bridge::GetCurrentBridge() { static Bridge* bridge; @@ -427,7 +502,7 @@ Bridge* Bridge::GetCurrentBridge() { return bridge; } - else if(autoInitState == AutoInitState::ENABLED) + else if(mAutoInitState == AutoInitState::ENABLED) { bridge = CreateBridge(); @@ -446,19 +521,19 @@ Bridge* Bridge::GetCurrentBridge() void Bridge::DisableAutoInit() { - if(bridgeInitialized) + if(INITIALIZED_BRIDGE) { DALI_LOG_ERROR("Bridge::DisableAutoInit() called after bridge auto-initialization"); } - autoInitState = AutoInitState::DISABLED; + mAutoInitState = AutoInitState::DISABLED; } void Bridge::EnableAutoInit() { - autoInitState = AutoInitState::ENABLED; + mAutoInitState = AutoInitState::ENABLED; - if(bridgeInitialized) + if(INITIALIZED_BRIDGE) { return; } diff --git a/dali/internal/accessibility/bridge/bridge-object.cpp b/dali/internal/accessibility/bridge/bridge-object.cpp index 8ac1569..02812c8 100644 --- a/dali/internal/accessibility/bridge/bridge-object.cpp +++ b/dali/internal/accessibility/bridge/bridge-object.cpp @@ -32,7 +32,7 @@ void BridgeObject::RegisterInterfaces() { // DBus::DBusInterfaceDescription desc{ AtspiDbusInterfaceEventObject }; // stateChanged = addSignal, Accessible*>(desc, "StateChanged"); - // dbusServer.addInterface("/", desc, true); + // mDbusServer.addInterface("/", desc, true); } void BridgeObject::EmitActiveDescendantChanged(Accessible* obj, Accessible* child) @@ -40,16 +40,11 @@ void BridgeObject::EmitActiveDescendantChanged(Accessible* obj, Accessible* chil if(!IsUp()) return; auto index = child->GetIndexInParent(); - auto addr = obj->GetAddress(); - const auto prefixPath = "/org/a11y/atspi/accessible/"; - const auto nullPath = "/org/a11y/atspi/null"; - std::string p; - if(addr) - p = prefixPath + addr.GetPath(); - else - p = nullPath; - dbusServer.emit2, Address>( - p, + auto addr = obj->GetAddress(); + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; + + mDbusServer.emit2, Address>( + path, AtspiDbusInterfaceEventObject, "ActiveDescendantChanged", "", @@ -63,6 +58,7 @@ void BridgeObject::Emit(Accessible* obj, Dali::Accessibility::ObjectPropertyChan { if(!IsUp()) return; const char* name = nullptr; + switch(ev) { case ObjectPropertyChangeEvent::NAME: @@ -91,16 +87,14 @@ void BridgeObject::Emit(Accessible* obj, Dali::Accessibility::ObjectPropertyChan break; } } + if(name) { auto addr = obj->GetAddress(); - std::string p; - if(addr) - p = ATSPI_PREFIX_PATH + addr.GetPath(); - else - p = ATSPI_NULL_PATH; - dbusServer.emit2, Address>( - p, + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; + + mDbusServer.emit2, Address>( + path, AtspiDbusInterfaceEventObject, "PropertyChange", name, @@ -115,6 +109,7 @@ void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail) { if(!IsUp()) return; const char* name = nullptr; + switch(event) { case WindowEvent::PROPERTY_CHANGE: @@ -213,16 +208,14 @@ void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail) break; } } + if(name) { auto addr = obj->GetAddress(); - std::string p; - if(addr) - p = ATSPI_PREFIX_PATH + addr.GetPath(); - else - p = ATSPI_NULL_PATH; - dbusServer.emit2, Address>( - p, + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; + + mDbusServer.emit2, Address>( + path, AtspiDbusInterfaceEventWindow, name, "", @@ -237,6 +230,7 @@ void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, { if(!IsUp()) return; const char* stateName = nullptr; + switch(state) { case State::INVALID: @@ -474,16 +468,14 @@ void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, break; } } + if(stateName) { auto addr = obj->GetAddress(); - std::string p; - if(addr) - p = ATSPI_PREFIX_PATH + addr.GetPath(); - else - p = ATSPI_NULL_PATH; - dbusServer.emit2, Address>( - p, + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; + + mDbusServer.emit2, Address>( + path, AtspiDbusInterfaceEventObject, "StateChanged", stateName, @@ -496,21 +488,17 @@ void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect) { - if(!allowObjectBoundsChangedEvent) return; + if(!IsBoundsChangedEventAllowed) return; + + auto addr = obj->GetAddress(); + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; - auto addr = obj->GetAddress(); - const auto prefixPath = "/org/a11y/atspi/accessible/"; - const auto nullPath = "/org/a11y/atspi/null"; - std::string p; - if(addr) - p = prefixPath + addr.GetPath(); - else - p = nullPath; DBus::EldbusVariant > tmp{ std::tuple{rect.x, rect.y, rect.width, rect.height}}; - addFilteredEvent(FilteredEvents::boundsChanged, obj, 1.0f, [=]() { - dbusServer.emit2 >, Address>( - p, + + AddFilteredEvent(FilteredEvents::BOUNDS_CHANGED, obj, 1.0f, [=]() { + mDbusServer.emit2 >, Address>( + path, AtspiDbusInterfaceEventObject, "BoundsChanged", "", @@ -524,9 +512,10 @@ void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect) void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition) { auto addr = obj->GetAddress(); - std::string p = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; - dbusServer.emit2, Address>( - p, + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; + + mDbusServer.emit2, Address>( + path, AtspiDbusInterfaceEventObject, "TextCaretMoved", "", @@ -556,12 +545,14 @@ void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsi break; } } + if(stateName) { auto addr = obj->GetAddress(); - std::string p = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; - dbusServer.emit2, Address>( - p, + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; + + mDbusServer.emit2, Address>( + path, AtspiDbusInterfaceEventObject, "TextChanged", stateName, @@ -575,9 +566,10 @@ void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsi void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type) { auto addr = obj->GetAddress(); - std::string p = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; - dbusServer.emit2, Address>( - p, + std::string path = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH; + + mDbusServer.emit2, Address>( + path, AtspiDbusInterfaceEventObject, "MoveOuted", "", diff --git a/dali/internal/accessibility/bridge/bridge-selection.cpp b/dali/internal/accessibility/bridge/bridge-selection.cpp index 949bc55..942bd97 100644 --- a/dali/internal/accessibility/bridge/bridge-selection.cpp +++ b/dali/internal/accessibility/bridge/bridge-selection.cpp @@ -31,17 +31,19 @@ void BridgeSelection::RegisterInterfaces() AddFunctionToInterface(desc, "SelectAll", &BridgeSelection::SelectAll); AddFunctionToInterface(desc, "ClearSelection", &BridgeSelection::ClearSelection); AddFunctionToInterface(desc, "DeselectChild", &BridgeSelection::DeselectChild); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } Selection* BridgeSelection::FindSelf() const { - auto s = BridgeBase::FindSelf(); - assert(s); - auto s2 = dynamic_cast(s); - if(!s2) - throw std::domain_error{"object " + s->GetAddress().ToString() + " doesn't have Selection interface"}; - return s2; + auto self = BridgeBase::FindSelf(); + assert(self); + auto selectionInterface = dynamic_cast(self); + if(!selectionInterface) + { + throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Selection interface"}; + } + return selectionInterface; } DBus::ValueOrError BridgeSelection::GetSelectedChildrenCount() diff --git a/dali/internal/accessibility/bridge/bridge-text.cpp b/dali/internal/accessibility/bridge/bridge-text.cpp index d71a723..54c87f5 100644 --- a/dali/internal/accessibility/bridge/bridge-text.cpp +++ b/dali/internal/accessibility/bridge/bridge-text.cpp @@ -38,19 +38,19 @@ void BridgeText::RegisterInterfaces() AddFunctionToInterface(desc, "GetSelection", &BridgeText::GetRangeOfSelection); AddFunctionToInterface(desc, "SetSelection", &BridgeText::SetRangeOfSelection); AddFunctionToInterface(desc, "RemoveSelection", &BridgeText::RemoveSelection); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } Text* BridgeText::FindSelf() const { auto self = BridgeBase::FindSelf(); assert(self); - auto textObject = dynamic_cast(self); - if(!textObject) + auto textInterface = dynamic_cast(self); + if(!textInterface) { throw std::domain_error{"Object " + self->GetAddress().ToString() + " doesn't have Text interface"}; } - return textObject; + return textInterface; } DBus::ValueOrError BridgeText::GetText(int startOffset, int endOffset) diff --git a/dali/internal/accessibility/bridge/bridge-value.cpp b/dali/internal/accessibility/bridge/bridge-value.cpp index ee2fc50..7f81a32 100644 --- a/dali/internal/accessibility/bridge/bridge-value.cpp +++ b/dali/internal/accessibility/bridge/bridge-value.cpp @@ -34,34 +34,41 @@ void BridgeValue::RegisterInterfaces() AddGetPropertyToInterface(desc, "MaximumValue", &BridgeValue::GetMaximumValue); AddGetPropertyToInterface(desc, "MinimumIncrement", &BridgeValue::GetMinimumIncrement); AddGetPropertyToInterface(desc, "MinimumValue", &BridgeValue::GetMinimumValue); - dbusServer.addInterface("/", desc, true); + mDbusServer.addInterface("/", desc, true); } Value* BridgeValue::FindSelf() const { - auto s = BridgeBase::FindSelf(); - assert(s); - auto s2 = dynamic_cast(s); - if(!s2) - throw std::domain_error{"object " + s->GetAddress().ToString() + " doesn't have Value interface"}; - return s2; + auto self = BridgeBase::FindSelf(); + assert(self); + auto valueInterface = dynamic_cast(self); + if(!valueInterface) + { + throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Value interface"}; + } + return valueInterface; } + double BridgeValue::GetCurrentValue() { return FindSelf()->GetCurrent(); } -void BridgeValue::SetCurrentValue(double new_value) + +void BridgeValue::SetCurrentValue(double newValue) { - FindSelf()->SetCurrent(new_value); + FindSelf()->SetCurrent(newValue); } + double BridgeValue::GetMaximumValue() { return FindSelf()->GetMaximum(); } + double BridgeValue::GetMinimumIncrement() { return FindSelf()->GetMinimumIncrement(); } + double BridgeValue::GetMinimumValue() { return FindSelf()->GetMinimum(); diff --git a/dali/internal/accessibility/bridge/bridge-value.h b/dali/internal/accessibility/bridge/bridge-value.h index 470a6f7..1919660 100644 --- a/dali/internal/accessibility/bridge/bridge-value.h +++ b/dali/internal/accessibility/bridge/bridge-value.h @@ -39,7 +39,7 @@ protected: public: double GetCurrentValue(); - void SetCurrentValue(double new_value); + void SetCurrentValue(double newValue); double GetMaximumValue(); double GetMinimumIncrement(); double GetMinimumValue(); diff --git a/dali/internal/accessibility/bridge/component.cpp b/dali/internal/accessibility/bridge/component.cpp index a94df86..d93789a 100644 --- a/dali/internal/accessibility/bridge/component.cpp +++ b/dali/internal/accessibility/bridge/component.cpp @@ -25,7 +25,7 @@ using namespace Dali::Accessibility; -bool Component::IsAccessibleContainedAtPoint(Point point, Dali::Accessibility::CoordinateType type) +bool Component::IsAccessibleContainingPoint(Point point, Dali::Accessibility::CoordinateType type) { auto extents = GetExtents(type); return point.x >= extents.x && point.y >= extents.y && point.x <= extents.x + extents.width && point.y <= extents.y + extents.height; @@ -37,7 +37,7 @@ Accessible* Component::GetAccessibleAtPoint(Point point, Dali::Accessibility::Co for(auto childIt = children.rbegin(); childIt != children.rend(); childIt++) { auto component = dynamic_cast(*childIt); - if(component && component->IsAccessibleContainedAtPoint(point, type)) + if(component && component->IsAccessibleContainingPoint(point, type)) { return component; } diff --git a/dali/internal/accessibility/bridge/dummy-atspi.cpp b/dali/internal/accessibility/bridge/dummy-atspi.cpp index faa861d..518330f 100644 --- a/dali/internal/accessibility/bridge/dummy-atspi.cpp +++ b/dali/internal/accessibility/bridge/dummy-atspi.cpp @@ -59,7 +59,7 @@ bool Accessibility::Component::IsScrollable() return false; } -bool Accessibility::Component::IsAccessibleContainedAtPoint(Point point, CoordinateType type) +bool Accessibility::Component::IsAccessibleContainingPoint(Point point, CoordinateType type) { return false; } -- 2.7.4