/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/internal/accessibility/bridge/bridge-accessible.h>
// EXTERNAL INCLUDES
+#include <dali/public-api/math/math-utils.h>
+
#include <algorithm>
#include <iostream>
+// INTERNAL INCLUDES
+#include <dali/devel-api/atspi-interfaces/accessible.h>
+#include <dali/devel-api/atspi-interfaces/component.h>
+#include <dali/devel-api/atspi-interfaces/selection.h>
+#include <dali/devel-api/atspi-interfaces/text.h>
+#include <dali/devel-api/atspi-interfaces/value.h>
+
//comment out 2 lines below to get more logs
#undef LOG
#define LOG() _LoggerEmpty()
namespace
{
-
bool SortVertically(Component* lhs, Component* rhs)
{
auto leftRect = lhs->GetExtents(CoordinateType::WINDOW);
// Find first with non-zero area
auto first = std::find_if(children.begin(), children.end(), [](Component* child) -> bool {
auto extents = child->GetExtents(CoordinateType::WINDOW);
- return extents.height != 0.0f && extents.width != 0.0f;
+ return !Dali::EqualsZero(extents.height) && !Dali::EqualsZero(extents.width);
});
if(first == children.end())
}
std::vector<std::vector<Component*>> lines(1);
- Dali::Rect<> lineRect = (*first)->GetExtents(CoordinateType::WINDOW);
- Dali::Rect<> rect;
+ Dali::Rect<> lineRect = (*first)->GetExtents(CoordinateType::WINDOW);
+ Dali::Rect<> rect;
// Split into lines
for(auto it = first; it != children.end(); ++it)
auto child = *it;
rect = child->GetExtents(CoordinateType::WINDOW);
- if(rect.height == 0.0f || rect.width == 0.0f)
+ if(Dali::EqualsZero(rect.height) || Dali::EqualsZero(rect.width))
{
// Zero area, ignore
continue;
for(const auto& it : relations)
{
- if(it.relationType == RelationType::CONTROLLED_BY)
+ if(it.mRelationType == RelationType::CONTROLLED_BY)
{
return false;
}
return false;
}
auto extents = obj->GetExtents(CoordinateType::WINDOW);
- return extents.height == 0 || extents.width == 0;
+ return Dali::EqualsZero(extents.height) || Dali::EqualsZero(extents.width);
}
static bool IsObjectAcceptable(Component* obj)
std::ostringstream object;
auto extent = obj->GetExtents(CoordinateType::SCREEN);
object << "name: " << obj->GetName() << " extent: (" << extent.x << ", "
- << extent.y << "), [" << extent.width << ", " << extent.height << "]";
+ << extent.y << "), [" << extent.width << ", " << extent.height << "]";
return object.str();
}
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;
}
-static Accessible* GetDeputyOfProxyInParent(Accessible* obj)
-{
- return nullptr;
-}
-
-static std::vector<Component*> GetScrollableParents(Accessible *accessible)
+static std::vector<Component*> GetScrollableParents(Accessible* accessible)
{
std::vector<Component*> scrollableParents;
while(accessible)
{
- accessible = accessible->GetParent();
+ accessible = accessible->GetParent();
auto component = dynamic_cast<Component*>(accessible);
if(component && component->IsScrollable())
{
return scrollableParents;
}
-static std::vector<Component*> GetNonDuplicatedScrollableParents(Accessible *child, Accessible *start)
+static std::vector<Component*> GetNonDuplicatedScrollableParents(Accessible* child, Accessible* start)
{
auto scrollableParentsOfChild = GetScrollableParents(child);
auto scrollableParentsOfStart = GetScrollableParents(start);
{
scrollableParentsOfChild.pop_back();
scrollableParentsOfStart.pop_back();
- }
+ }
return scrollableParentsOfChild;
}
} // anonymous namespace
-
BridgeAccessible::BridgeAccessible()
{
}
void BridgeAccessible::RegisterInterfaces()
{
- DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceAccessible};
+ DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::ACCESSIBLE)};
AddGetPropertyToInterface(desc, "ChildCount", &BridgeAccessible::GetChildCount);
AddGetPropertyToInterface(desc, "Name", &BridgeAccessible::GetName);
AddGetPropertyToInterface(desc, "Description", &BridgeAccessible::GetDescription);
AddFunctionToInterface(desc, "GetLocalizedRoleName", &BridgeAccessible::GetLocalizedRoleName);
AddFunctionToInterface(desc, "GetState", &BridgeAccessible::GetStates);
AddFunctionToInterface(desc, "GetAttributes", &BridgeAccessible::GetAttributes);
- AddFunctionToInterface(desc, "GetInterfaces", &BridgeAccessible::GetInterfaces);
+ AddFunctionToInterface(desc, "GetInterfaces", &BridgeAccessible::GetInterfacesAsStrings);
AddFunctionToInterface(desc, "GetChildAtIndex", &BridgeAccessible::GetChildAtIndex);
AddFunctionToInterface(desc, "GetChildren", &BridgeAccessible::GetChildren);
AddFunctionToInterface(desc, "GetIndexInParent", &BridgeAccessible::GetIndexInParent);
AddFunctionToInterface(desc, "DoGesture", &BridgeAccessible::DoGesture);
AddFunctionToInterface(desc, "GetReadingMaterial", &BridgeAccessible::GetReadingMaterial);
AddFunctionToInterface(desc, "GetRelationSet", &BridgeAccessible::GetRelationSet);
+ AddFunctionToInterface(desc, "SetListenPostRender", &BridgeAccessible::SetListenPostRender);
mDbusServer.addInterface("/", desc, true);
}
+Accessible* BridgeAccessible::FindSelf() const
+{
+ return FindCurrentObject();
+}
+
Component* BridgeAccessible::GetObjectInRelation(Accessible* obj, RelationType relationType)
{
if(!obj)
for(auto& relation : obj->GetRelationSet())
{
- if(relation.relationType == relationType)
+ if(relation.mRelationType == relationType)
{
- for(auto& address : relation.targets)
+ for(auto& target : relation.mTargets)
{
- auto component = dynamic_cast<Component*>(Find(address));
+ auto component = dynamic_cast<Component*>(target);
if(component)
{
return component;
auto relation = std::find_if(relations.begin(),
relations.end(),
[relationType](const Dali::Accessibility::Relation& relation) -> bool {
- return relation.relationType == relationType;
+ return relation.mRelationType == relationType;
});
- return relations.end() != relation && !relation->targets.empty() ? Find(relation->targets.back()) : nullptr;
+ return relations.end() != relation && !relation->mTargets.empty() ? relation->mTargets.back() : nullptr;
};
auto labellingObject = findObjectByRelationType(RelationType::LABELLED_BY);
auto describedByObject = findObjectByRelationType(RelationType::DESCRIBED_BY);
- double currentValue = 0.0;
- double minimumIncrement = 0.0;
- double maximumValue = 0.0;
- double minimumValue = 0.0;
- auto* valueInterface = dynamic_cast<Dali::Accessibility::Value*>(self);
+ double currentValue = 0.0;
+ std::string currentValueText;
+ double minimumIncrement = 0.0;
+ double maximumValue = 0.0;
+ double minimumValue = 0.0;
+ auto* valueInterface = Value::DownCast(self);
if(valueInterface)
{
currentValue = valueInterface->GetCurrent();
+ currentValueText = valueInterface->GetValueText();
minimumIncrement = valueInterface->GetMinimumIncrement();
maximumValue = valueInterface->GetMaximum();
minimumValue = valueInterface->GetMinimum();
int32_t firstSelectedChildIndex = -1;
int32_t selectedChildCount = 0;
- auto* selfSelectionInterface = dynamic_cast<Dali::Accessibility::Selection*>(self);
+ auto* selfSelectionInterface = Selection::DownCast(self);
if(selfSelectionInterface)
{
selectedChildCount = selfSelectionInterface->GetSelectedChildrenCount();
listChildrenCount = GetItemCountOfFirstDescendantContainer(self, Role::POPUP_MENU, Role::MENU_ITEM, false);
}
- auto* textInterface = dynamic_cast<Dali::Accessibility::Text*>(self);
+ auto* textInterface = Text::DownCast(self);
std::string nameFromTextInterface = "";
if(textInterface)
{
auto parentChildCount = parent ? static_cast<int32_t>(parent->GetChildCount()) : 0;
auto parentStateSet = parent ? parent->GetStates() : States{};
bool isSelectedInParent = false;
- auto* parentSelectionInterface = dynamic_cast<Dali::Accessibility::Selection*>(parent);
+ auto* parentSelectionInterface = Selection::DownCast(parent);
if(parentSelectionInterface)
{
isSelectedInParent = parentSelectionInterface->IsChildSelected(indexInParent);
localizedRoleName,
childCount,
currentValue,
+ currentValueText,
minimumIncrement,
maximumValue,
minimumValue,
describedByObject};
}
-void BridgeAccessible::SuppressScreenReader(bool suppress)
-{
- mIsScreenReaderSuppressed = suppress;
-}
-
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)
{
// Please be aware of sending GestureInfo point in the different order with parameters
Accessible* deputy = nullptr;
auto accessible = FindSelf();
auto cType = static_cast<CoordinateType>(coordinateType);
+
+ x -= mData->mExtentsOffset.first;
+ y -= mData->mExtentsOffset.second;
+
LOG() << "GetNavigableAtPoint: " << x << ", " << y << " type: " << coordinateType;
auto component = CalculateNavigableAccessibleAtPoint(accessible, {x, y}, cType, GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH);
bool recurse = false;
std::vector<Component*> vec;
Dali::Rect<> scrollableParentExtents;
- auto nonDuplicatedScrollableParents = GetNonDuplicatedScrollableParents(children.front(), start);
- if (!nonDuplicatedScrollableParents.empty())
+ auto nonDuplicatedScrollableParents = GetNonDuplicatedScrollableParents(children.front(), start);
+ if(!nonDuplicatedScrollableParents.empty())
{
scrollableParentExtents = nonDuplicatedScrollableParents.front()->GetExtents(CoordinateType::WINDOW);
}
children = sortedChildren;
}
-
template<class T>
struct CycleDetection
{
{
return nullptr;
}
+ else if(parent->IsProxy())
+ {
+ return parent;
+ }
auto children = GetValidChildren(parent->GetChildren(), start);
SortChildrenFromTopLeft(children);
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 GetDeputyOfProxyInParent(start);
+ searchMode = BridgeAccessible::NeighborSearchMode::CONTINUE_AFTER_FAILED_RECURSION;
}
Accessible* node = start ? start : root;
// 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 areAllChildrenVisitedOrMovingForward= (children.size() == 0 || forward || areAllChildrenVisited);
+ bool areAllChildrenVisitedOrMovingForward = (children.size() == 0 || forward || areAllChildrenVisited);
if(!forceNext && node != start && areAllChildrenVisitedOrMovingForward && IsObjectAcceptable(node))
{
}
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(forceNext && forward)
- {
- auto deputy = GetDeputyOfProxyInParent(node);
- nextRelatedInDirection = GetObjectInRelation(deputy, RelationType::FLOWS_TO);
- }
-
if(nextRelatedInDirection && start && start->GetStates()[State::DEFUNCT])
{
nextRelatedInDirection = NULL;
unsigned char wantCycleDetection = 0;
if(nextRelatedInDirection)
{
- // 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(IsDeputy(nextRelatedInDirection))
- {
- 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(IsDeputy(node))
- {
- parent = node->GetParent();
- nextRelatedInDirection = GetProxyInParent(parent);
- }
- }
node = nextRelatedInDirection;
wantCycleDetection = 1;
}
DBus::ValueOrError<Accessible*, uint8_t> 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 start = FindSelf();
+ auto root = !rootPath.empty() ? Find(StripPrefix(rootPath)) : nullptr;
auto accessible = CalculateNeighbor(root, start, direction == 1, static_cast<NeighborSearchMode>(searchMode));
unsigned char recurse = 0;
if(accessible)
return attributes;
}
-DBus::ValueOrError<std::vector<std::string>> BridgeAccessible::GetInterfaces()
+DBus::ValueOrError<std::vector<std::string>> BridgeAccessible::GetInterfacesAsStrings()
{
- return FindSelf()->GetInterfaces();
+ return FindSelf()->GetInterfacesAsStrings();
}
int BridgeAccessible::GetChildCount()
DBus::ValueOrError<Accessible*, uint32_t, std::unordered_map<std::string, std::string>> BridgeAccessible::GetDefaultLabelInfo()
{
- auto defaultLabel = FindSelf()->GetDefaultLabel();
+ auto* defaultLabel = GetDefaultLabel(FindSelf());
+ DALI_ASSERT_DEBUG(defaultLabel);
+
// By default, the text is taken from navigation context root's accessibility properties name and description.
return {defaultLabel, static_cast<uint32_t>(defaultLabel->GetRole()), defaultLabel->GetAttributes()};
}
for(auto& it : relations)
{
- ret.emplace_back(Relation{static_cast<uint32_t>(it.relationType), it.targets});
+ ret.emplace_back(Relation{static_cast<uint32_t>(it.mRelationType), it.mTargets});
}
return ret;
}
+
+DBus::ValueOrError<void> BridgeAccessible::SetListenPostRender(bool enabled)
+{
+ FindSelf()->SetListenPostRender(enabled);
+ return {};
+}