2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/accessibility/bridge/bridge-accessible.h>
25 //comment out 2 lines below to get more logs
27 #define LOG() _LoggerEmpty()
29 using namespace Dali::Accessibility;
31 #define GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH 10000
36 bool SortVertically(Component* lhs, Component* rhs)
38 auto leftRect = lhs->GetExtents(CoordinateType::WINDOW);
39 auto rightRect = rhs->GetExtents(CoordinateType::WINDOW);
41 return leftRect.y < rightRect.y;
44 bool SortHorizontally(Component* lhs, Component* rhs)
46 auto leftRect = lhs->GetExtents(CoordinateType::WINDOW);
47 auto rightRect = rhs->GetExtents(CoordinateType::WINDOW);
49 return leftRect.x < rightRect.x;
52 std::vector<std::vector<Component*>> SplitLines(const std::vector<Component*>& children)
54 // Find first with non-zero area
55 auto first = std::find_if(children.begin(), children.end(), [](Component* child) -> bool {
56 auto extents = child->GetExtents(CoordinateType::WINDOW);
57 return extents.height != 0.0f && extents.width != 0.0f;
60 if(first == children.end())
65 std::vector<std::vector<Component*>> lines(1);
66 Dali::Rect<> lineRect = (*first)->GetExtents(CoordinateType::WINDOW);
70 for(auto it = first; it != children.end(); ++it)
74 rect = child->GetExtents(CoordinateType::WINDOW);
75 if(rect.height == 0.0f || rect.width == 0.0f)
81 if(lineRect.y + (0.5 * lineRect.height) >= rect.y + (0.5 * rect.height))
84 lines.back().push_back(child);
91 lines.back().push_back(child);
98 static bool AcceptObjectCheckRelations(Component* obj)
100 auto relations = obj->GetRelationSet();
102 for(const auto& it : relations)
104 if(it.relationType == RelationType::CONTROLLED_BY)
112 static Component* GetScrollableParent(Accessible* obj)
116 obj = obj->GetParent();
117 auto comp = dynamic_cast<Component*>(obj);
118 if(comp && comp->IsScrollable())
126 static bool IsObjectItem(Component* obj)
132 auto role = obj->GetRole();
133 return role == Role::LIST_ITEM || role == Role::MENU_ITEM;
136 static bool IsObjectCollapsed(Component* obj)
142 const auto states = obj->GetStates();
143 return states[State::EXPANDABLE] && !states[State::EXPANDED];
146 static bool IsObjectZeroSize(Component* obj)
152 auto extents = obj->GetExtents(CoordinateType::WINDOW);
153 return extents.height == 0 || extents.width == 0;
156 static bool IsObjectAcceptable(Component* obj)
163 const auto states = obj->GetStates();
164 if(!states[State::VISIBLE])
168 if(!AcceptObjectCheckRelations(obj))
172 if(!states[State::HIGHLIGHTABLE])
177 if(GetScrollableParent(obj) != nullptr)
179 auto parent = dynamic_cast<Component*>(obj->GetParent());
183 return !IsObjectItem(obj) || !IsObjectCollapsed(parent);
188 if(IsObjectZeroSize(obj))
192 if(!states[State::SHOWING])
200 static bool IsObjectAcceptable(Accessible* obj)
202 auto component = dynamic_cast<Component*>(obj);
203 return IsObjectAcceptable(component);
206 static int32_t GetItemCountOfList(Accessible* obj)
208 int32_t itemCount = 0;
209 if(obj && obj->GetRole() == Role::LIST)
211 for(auto i = 0u; i < static_cast<size_t>(obj->GetChildCount()); ++i)
213 auto child = obj->GetChildAtIndex(i);
214 if(child && child->GetRole() == Role::LIST_ITEM)
223 static int32_t GetItemCountOfFirstDescendantList(Accessible* obj)
225 int32_t itemCount = 0;
226 itemCount = GetItemCountOfList(obj);
227 if(itemCount > 0 || !obj)
232 for(auto i = 0u; i < static_cast<size_t>(obj->GetChildCount()); ++i)
234 auto child = obj->GetChildAtIndex(i);
235 itemCount = GetItemCountOfFirstDescendantList(child);
244 static std::string GetComponentInfo(Component* obj)
251 std::ostringstream object;
252 auto extent = obj->GetExtents(CoordinateType::SCREEN);
253 object << "name: " << obj->GetName() << " extent: (" << extent.x << ", "
254 << extent.y << "), [" << extent.width << ", " << extent.height << "]";
258 static std::string MakeIndent(unsigned int maxRecursionDepth)
260 return std::string(GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH - maxRecursionDepth, ' ');
263 static bool IsDeputy(Accessible* obj)
269 static Accessible* GetProxyInParent(Accessible* obj)
276 auto children = obj->GetChildren();
277 for(auto& child : children)
287 static bool IsRoleAcceptableWhenNavigatingNextPrev(Accessible* obj)
293 auto role = obj->GetRole();
294 return role != Role::POPUP_MENU && role != Role::DIALOG;
297 static Accessible* FindNonDefunctChild(const std::vector<Component*>& children, unsigned int currentIndex, unsigned char forward)
299 unsigned int childrenCount = children.size();
300 for(; currentIndex < childrenCount; forward ? ++currentIndex : --currentIndex)
302 Accessible* object = children[currentIndex];
303 if(object && !object->GetStates()[State::DEFUNCT])
311 // The auxiliary method for Depth-First Search (DFS) algorithm to find non defunct child directionally
312 static Accessible* FindNonDefunctChildWithDepthFirstSearch(Accessible* node, const std::vector<Component*>& children, unsigned char forward)
319 auto childrenCount = children.size();
320 if(childrenCount > 0)
322 const bool isShowing = GetScrollableParent(node) == nullptr ? node->GetStates()[State::SHOWING] : true;
325 return FindNonDefunctChild(children, forward ? 0 : childrenCount - 1, forward);
331 static bool CheckChainEndWithAttribute(Accessible* obj, unsigned char forward)
338 auto attrs = obj->GetAttributes();
339 for(auto& attr : attrs)
341 if(attr.first == "relation_chain_end")
343 if((attr.second == "prev,end" && forward == 0) || (attr.second == "next,end" && forward == 1) || attr.second == "prev,next,end")
352 static Accessible* GetDeputyOfProxyInParent(Accessible* obj)
357 static std::vector<Component*> GetScrollableParents(Accessible *accessible)
359 std::vector<Component*> scrollableParents;
363 accessible = accessible->GetParent();
364 auto component = dynamic_cast<Component*>(accessible);
365 if(component && component->IsScrollable())
367 scrollableParents.push_back(component);
370 return scrollableParents;
373 static std::vector<Component*> GetNonDuplicatedScrollableParents(Accessible *child, Accessible *start)
375 auto scrollableParentsOfChild = GetScrollableParents(child);
376 auto scrollableParentsOfStart = GetScrollableParents(start);
378 // find the first different scrollable parent by comparing from top to bottom.
379 // since it can not be the same after that, there is no need to compare.
380 while(!scrollableParentsOfChild.empty() && !scrollableParentsOfStart.empty() && scrollableParentsOfChild.back() == scrollableParentsOfStart.back())
382 scrollableParentsOfChild.pop_back();
383 scrollableParentsOfStart.pop_back();
386 return scrollableParentsOfChild;
389 } // anonymous namespace
392 BridgeAccessible::BridgeAccessible()
396 void BridgeAccessible::RegisterInterfaces()
398 DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceAccessible};
399 AddGetPropertyToInterface(desc, "ChildCount", &BridgeAccessible::GetChildCount);
400 AddGetPropertyToInterface(desc, "Name", &BridgeAccessible::GetName);
401 AddGetPropertyToInterface(desc, "Description", &BridgeAccessible::GetDescription);
402 AddGetPropertyToInterface(desc, "Parent", &BridgeAccessible::GetParent);
403 AddFunctionToInterface(desc, "GetRole", &BridgeAccessible::GetRole);
404 AddFunctionToInterface(desc, "GetRoleName", &BridgeAccessible::GetRoleName);
405 AddFunctionToInterface(desc, "GetLocalizedRoleName", &BridgeAccessible::GetLocalizedRoleName);
406 AddFunctionToInterface(desc, "GetState", &BridgeAccessible::GetStates);
407 AddFunctionToInterface(desc, "GetAttributes", &BridgeAccessible::GetAttributes);
408 AddFunctionToInterface(desc, "GetInterfaces", &BridgeAccessible::GetInterfaces);
409 AddFunctionToInterface(desc, "GetChildAtIndex", &BridgeAccessible::GetChildAtIndex);
410 AddFunctionToInterface(desc, "GetChildren", &BridgeAccessible::GetChildren);
411 AddFunctionToInterface(desc, "GetIndexInParent", &BridgeAccessible::GetIndexInParent);
412 AddFunctionToInterface(desc, "GetNavigableAtPoint", &BridgeAccessible::GetNavigableAtPoint);
413 AddFunctionToInterface(desc, "GetNeighbor", &BridgeAccessible::GetNeighbor);
414 AddFunctionToInterface(desc, "GetDefaultLabelInfo", &BridgeAccessible::GetDefaultLabelInfo);
415 AddFunctionToInterface(desc, "DoGesture", &BridgeAccessible::DoGesture);
416 AddFunctionToInterface(desc, "GetReadingMaterial", &BridgeAccessible::GetReadingMaterial);
417 AddFunctionToInterface(desc, "GetRelationSet", &BridgeAccessible::GetRelationSet);
418 mDbusServer.addInterface("/", desc, true);
421 Component* BridgeAccessible::GetObjectInRelation(Accessible* obj, RelationType relationType)
428 for(auto& relation : obj->GetRelationSet())
430 if(relation.relationType == relationType)
432 for(auto& address : relation.targets)
434 auto component = dynamic_cast<Component*>(Find(address));
445 Component* BridgeAccessible::CalculateNavigableAccessibleAtPoint(Accessible* root, Point point, CoordinateType type, unsigned int maxRecursionDepth)
447 if(!root || maxRecursionDepth == 0)
452 auto rootComponent = dynamic_cast<Component*>(root);
453 LOG() << "CalculateNavigableAccessibleAtPoint: checking: " << MakeIndent(maxRecursionDepth) << GetComponentInfo(rootComponent);
455 if(rootComponent && !rootComponent->IsAccessibleContainingPoint(point, type))
460 auto children = root->GetChildren();
461 for(auto childIt = children.rbegin(); childIt != children.rend(); childIt++)
463 //check recursively all children first
464 auto result = CalculateNavigableAccessibleAtPoint(*childIt, point, type, maxRecursionDepth - 1);
473 //Found a candidate, all its children are already checked
474 auto controledBy = GetObjectInRelation(rootComponent, RelationType::CONTROLLED_BY);
477 controledBy = rootComponent;
480 if(controledBy->IsProxy() || IsObjectAcceptable(controledBy))
482 LOG() << "CalculateNavigableAccessibleAtPoint: found: " << MakeIndent(maxRecursionDepth) << GetComponentInfo(rootComponent);
489 BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
491 auto self = FindSelf();
492 auto findObjectByRelationType = [this, &self](RelationType relationType) {
493 auto relations = self->GetRelationSet();
494 auto relation = std::find_if(relations.begin(),
496 [relationType](const Dali::Accessibility::Relation& relation) -> bool {
497 return relation.relationType == relationType;
499 return relations.end() != relation && !relation->targets.empty() ? Find(relation->targets.back()) : nullptr;
502 auto labellingObject = findObjectByRelationType(RelationType::LABELLED_BY);
503 std::string labeledByName = labellingObject ? labellingObject->GetName() : "";
505 auto describedByObject = findObjectByRelationType(RelationType::DESCRIBED_BY);
507 double currentValue = 0.0;
508 double minimumIncrement = 0.0;
509 double maximumValue = 0.0;
510 double minimumValue = 0.0;
511 auto* valueInterface = dynamic_cast<Dali::Accessibility::Value*>(self);
514 currentValue = valueInterface->GetCurrent();
515 minimumIncrement = valueInterface->GetMinimumIncrement();
516 maximumValue = valueInterface->GetMaximum();
517 minimumValue = valueInterface->GetMinimum();
520 int32_t firstSelectedChildIndex = -1;
521 int32_t selectedChildCount = 0;
522 auto* selfSelectionInterface = dynamic_cast<Dali::Accessibility::Selection*>(self);
523 if(selfSelectionInterface)
525 selectedChildCount = selfSelectionInterface->GetSelectedChildrenCount();
526 auto firstSelectedChild = selfSelectionInterface->GetSelectedChild(0);
527 if(firstSelectedChild)
529 firstSelectedChildIndex = firstSelectedChild->GetIndexInParent();
533 auto childCount = static_cast<int32_t>(self->GetChildCount());
534 bool hasCheckBoxChild = false;
535 for(auto i = 0u; i < static_cast<size_t>(childCount); ++i)
537 auto child = self->GetChildAtIndex(i);
538 if(child->GetRole() == Role::CHECK_BOX)
540 hasCheckBoxChild = true;
545 auto role = static_cast<uint32_t>(self->GetRole());
546 int32_t listChildrenCount = 0;
547 if(role == static_cast<uint32_t>(Role::DIALOG))
549 listChildrenCount = GetItemCountOfFirstDescendantList(self);
552 auto* textInterface = dynamic_cast<Dali::Accessibility::Text*>(self);
553 std::string nameFromTextInterface = "";
556 nameFromTextInterface = textInterface->GetText(0, textInterface->GetCharacterCount());
559 auto description = self->GetDescription();
560 auto attributes = self->GetAttributes();
561 auto states = self->GetStates();
562 auto name = self->GetName();
563 auto localizedRoleName = self->GetLocalizedRoleName();
564 auto indexInParent = static_cast<int32_t>(self->GetIndexInParent());
566 auto parent = self->GetParent();
567 auto parentRole = static_cast<uint32_t>(parent ? parent->GetRole() : Role{});
568 auto parentChildCount = parent ? static_cast<int32_t>(parent->GetChildCount()) : 0;
569 auto parentStateSet = parent ? parent->GetStates() : States{};
570 bool isSelectedInParent = false;
571 auto* parentSelectionInterface = dynamic_cast<Dali::Accessibility::Selection*>(parent);
572 if(parentSelectionInterface)
574 isSelectedInParent = parentSelectionInterface->IsChildSelected(indexInParent);
581 nameFromTextInterface,
595 firstSelectedChildIndex,
604 DBus::ValueOrError<bool> 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)
606 // Please be aware of sending GestureInfo point in the different order with parameters
607 return FindSelf()->DoGesture(Dali::Accessibility::GestureInfo{type, startPositionX, endPositionX, startPositionY, endPositionY, state, eventTime});
610 DBus::ValueOrError<Accessible*, uint8_t, Accessible*> BridgeAccessible::GetNavigableAtPoint(int32_t x, int32_t y, uint32_t coordinateType)
612 Accessible* deputy = nullptr;
613 auto accessible = FindSelf();
614 auto cType = static_cast<CoordinateType>(coordinateType);
615 LOG() << "GetNavigableAtPoint: " << x << ", " << y << " type: " << coordinateType;
616 auto component = CalculateNavigableAccessibleAtPoint(accessible, {x, y}, cType, GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH);
617 bool recurse = false;
620 recurse = component->IsProxy();
623 return {component, recurse, deputy};
626 Accessible* BridgeAccessible::GetCurrentlyHighlighted()
628 //TODO: add currently highlighted object
632 std::vector<Component*> BridgeAccessible::GetValidChildren(const std::vector<Accessible*>& children, Accessible* start)
639 std::vector<Component*> vec;
641 Dali::Rect<> scrollableParentExtents;
642 auto nonDuplicatedScrollableParents = GetNonDuplicatedScrollableParents(children.front(), start);
643 if (!nonDuplicatedScrollableParents.empty())
645 scrollableParentExtents = nonDuplicatedScrollableParents.front()->GetExtents(CoordinateType::WINDOW);
648 for(auto child : children)
650 auto* component = dynamic_cast<Component*>(child);
653 if(nonDuplicatedScrollableParents.empty() || scrollableParentExtents.Intersects(component->GetExtents(CoordinateType::WINDOW)))
655 vec.push_back(component);
663 void BridgeAccessible::SortChildrenFromTopLeft(std::vector<Dali::Accessibility::Component*>& children)
670 std::vector<Component*> sortedChildren;
672 std::sort(children.begin(), children.end(), &SortVertically);
674 for(auto& line : SplitLines(children))
676 std::sort(line.begin(), line.end(), &SortHorizontally);
677 sortedChildren.insert(sortedChildren.end(), line.begin(), line.end());
680 children = sortedChildren;
685 struct CycleDetection
687 CycleDetection(const T value)
689 mCurrentSearchSize(1),
694 bool Check(const T value)
703 mCurrentSearchSize <<= 1;
704 if(mCurrentSearchSize == 0)
706 return true; // UNDEFINED BEHAVIOR
708 mCounter = mCurrentSearchSize;
715 unsigned int mCurrentSearchSize;
716 unsigned int mCounter;
719 Accessible* BridgeAccessible::GetNextNonDefunctSibling(Accessible* obj, Accessible* start, unsigned char forward)
726 auto parent = obj->GetParent();
732 auto children = GetValidChildren(parent->GetChildren(), start);
733 SortChildrenFromTopLeft(children);
735 unsigned int childrenCount = children.size();
736 if(childrenCount == 0)
741 unsigned int current = 0;
742 for(; current < childrenCount && children[current] != obj; ++current)
746 if(current >= childrenCount)
751 forward ? ++current : --current;
752 auto ret = FindNonDefunctChild(children, current, forward);
756 Accessible* BridgeAccessible::FindNonDefunctSibling(bool& areAllChildrenVisited, Accessible* node, Accessible* start, Accessible* root, unsigned char forward)
760 Accessible* sibling = GetNextNonDefunctSibling(node, start, forward);
764 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.
768 node = node->GetParent();
769 if(node == nullptr || node == root)
774 // in backward traversing stop the walk up on parent
784 Accessible* BridgeAccessible::CalculateNeighbor(Accessible* root, Accessible* start, unsigned char forward, BridgeAccessible::NeighborSearchMode searchMode)
786 if(start && CheckChainEndWithAttribute(start, forward))
790 if(root && root->GetStates()[State::DEFUNCT])
794 if(start && start->GetStates()[State::DEFUNCT])
800 if(searchMode == BridgeAccessible::NeighborSearchMode::RECURSE_TO_OUTSIDE)
802 // This only works if we navigate backward, and it is not possible to
803 // find in embedded process. In this case the deputy should be used */
804 return GetDeputyOfProxyInParent(start);
807 Accessible* node = start ? start : root;
813 // initialization of all-children-visited flag for start node - we assume
814 // that when we begin at start node and we navigate backward, then all children
815 // are visited, so navigation will ignore start's children and go to
816 // previous sibling available.
817 // Regarding condtion (start != root):
818 // The last object can be found only if areAllChildrenVisited is false.
819 // The start is same with root, when looking for the last object.
820 bool areAllChildrenVisited = (start != root) && (searchMode != BridgeAccessible::NeighborSearchMode::RECURSE_FROM_ROOT && !forward);
822 // true, if starting element should be ignored. this is only used in rare case of
823 // recursive search failing to find an object.
824 // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
825 // element A algorithm has to descend into BUS_B and search element B and its children. this is done
826 // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
827 // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
828 // and will call us again with object A and flag searchMode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
829 // this flag means, that object A was already checked previously and we should skip it and its children.
830 bool forceNext = (searchMode == BridgeAccessible::NeighborSearchMode::CONTINUE_AFTER_FAILED_RECURSION);
832 CycleDetection<Accessible*> cycleDetection(node);
835 if(node->GetStates()[State::DEFUNCT])
840 // always accept proxy object from different world
841 if(!forceNext && node->IsProxy())
846 auto children = GetValidChildren(node->GetChildren(), start);
847 SortChildrenFromTopLeft(children);
851 // 2. parent after all children in backward traversing
852 // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
853 // Objects with those roles shouldnt be reachable, when navigating next / prev.
854 bool areAllChildrenVisitedOrMovingForward= (children.size() == 0 || forward || areAllChildrenVisited);
856 if(!forceNext && node != start && areAllChildrenVisitedOrMovingForward && IsObjectAcceptable(node))
858 if(start == NULL || IsRoleAcceptableWhenNavigatingNextPrev(node))
864 Accessible* nextRelatedInDirection = !forceNext ? GetObjectInRelation(node, forward ? RelationType::FLOWS_TO : RelationType::FLOWS_FROM) : nullptr;
865 // forceNext means that the searchMode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
866 // in this case the node is elm_layout which is parent of proxy object.
867 // There is an access object working for the proxy object, and the access
868 // object could have relation information. This relation information should
869 // be checked first before using the elm_layout as a node.
870 if(forceNext && forward)
872 auto deputy = GetDeputyOfProxyInParent(node);
873 nextRelatedInDirection = GetObjectInRelation(deputy, RelationType::FLOWS_TO);
876 if(nextRelatedInDirection && start && start->GetStates()[State::DEFUNCT])
878 nextRelatedInDirection = NULL;
881 unsigned char wantCycleDetection = 0;
882 if(nextRelatedInDirection)
884 // Check whether nextRelatedInDirection is deputy object or not
888 // If the prev object is deputy, then go to inside of its proxy first
889 if(IsDeputy(nextRelatedInDirection))
891 parent = nextRelatedInDirection->GetParent();
892 nextRelatedInDirection = GetProxyInParent(parent);
897 // If current object is deputy, and it has relation next object,
898 // then do not use the relation next object, and use proxy first
901 parent = node->GetParent();
902 nextRelatedInDirection = GetProxyInParent(parent);
905 node = nextRelatedInDirection;
906 wantCycleDetection = 1;
910 auto child = !forceNext && !areAllChildrenVisited ? FindNonDefunctChildWithDepthFirstSearch(node, children, forward) : nullptr;
913 wantCycleDetection = 1;
917 if(!forceNext && node == root)
921 areAllChildrenVisited = true;
922 child = FindNonDefunctSibling(areAllChildrenVisited, node, start, root, forward);
928 if(wantCycleDetection && cycleDetection.Check(node))
936 DBus::ValueOrError<Accessible*, uint8_t> BridgeAccessible::GetNeighbor(std::string rootPath, int32_t direction, int32_t searchMode)
938 auto start = FindSelf();
939 rootPath = StripPrefix(rootPath);
940 auto root = !rootPath.empty() ? Find(rootPath) : nullptr;
941 auto accessible = CalculateNeighbor(root, start, direction == 1, static_cast<NeighborSearchMode>(searchMode));
942 unsigned char recurse = 0;
945 recurse = accessible->IsProxy();
947 return {accessible, recurse};
950 Accessible* BridgeAccessible::GetParent()
952 // NOTE: currently bridge supports single application root element.
953 // only element set as application root might return nullptr from GetParent
954 // if you want more, then you need to change setApplicationRoot to
955 // add/remove ApplicationRoot and make roots a vector.
956 auto parent = FindSelf()->GetParent();
961 DBus::ValueOrError<std::vector<Accessible*>> BridgeAccessible::GetChildren()
963 return FindSelf()->GetChildren();
966 std::string BridgeAccessible::GetDescription()
968 return FindSelf()->GetDescription();
971 DBus::ValueOrError<uint32_t> BridgeAccessible::GetRole()
973 return static_cast<unsigned int>(FindSelf()->GetRole());
976 DBus::ValueOrError<std::string> BridgeAccessible::GetRoleName()
978 return FindSelf()->GetRoleName();
981 DBus::ValueOrError<std::string> BridgeAccessible::GetLocalizedRoleName()
983 return FindSelf()->GetLocalizedRoleName();
986 DBus::ValueOrError<int32_t> BridgeAccessible::GetIndexInParent()
988 return FindSelf()->GetIndexInParent();
991 DBus::ValueOrError<std::array<uint32_t, 2>> BridgeAccessible::GetStates()
993 return FindSelf()->GetStates().GetRawData();
996 DBus::ValueOrError<std::unordered_map<std::string, std::string>> BridgeAccessible::GetAttributes()
998 std::unordered_map<std::string, std::string> attributes = FindSelf()->GetAttributes();
1000 if(mIsScreenReaderSuppressed)
1002 attributes.insert({"suppress-screen-reader", "true"});
1008 DBus::ValueOrError<std::vector<std::string>> BridgeAccessible::GetInterfaces()
1010 return FindSelf()->GetInterfaces();
1013 int BridgeAccessible::GetChildCount()
1015 return FindSelf()->GetChildCount();
1018 DBus::ValueOrError<Accessible*> BridgeAccessible::GetChildAtIndex(int index)
1022 throw std::domain_error{"negative index (" + std::to_string(index) + ")"};
1024 return FindSelf()->GetChildAtIndex(static_cast<size_t>(index));
1027 std::string BridgeAccessible::GetName()
1029 return FindSelf()->GetName();
1032 DBus::ValueOrError<Accessible*, uint32_t, std::unordered_map<std::string, std::string>> BridgeAccessible::GetDefaultLabelInfo()
1034 auto defaultLabel = FindSelf()->GetDefaultLabel();
1035 // By default, the text is taken from navigation context root's accessibility properties name and description.
1036 return {defaultLabel, static_cast<uint32_t>(defaultLabel->GetRole()), defaultLabel->GetAttributes()};
1039 DBus::ValueOrError<std::vector<BridgeAccessible::Relation>> BridgeAccessible::GetRelationSet()
1041 auto relations = FindSelf()->GetRelationSet();
1042 std::vector<BridgeAccessible::Relation> ret;
1044 for(auto& it : relations)
1046 ret.emplace_back(Relation{static_cast<uint32_t>(it.relationType), it.targets});