}
return checkIfStillRunning();
}
+
#define continueProcessing(args) continueProcessingImpl(__FILE__, __LINE__, args)
void createNavigationRowsFromElements(
DEBUG("got %d elements", elements.size());
for (size_t i = 0; i < elements.size(); ++i)
DEBUG("got element %2d %s", (unsigned int)i, Atspi::getUniqueId(elements[i]).c_str());
+
struct Elem {
AtspiAccessiblePtr obj, parent;
Rectangle pos;
struct All {
std::vector<AtspiAccessiblePtr> expandableElems, expandableAndExpandedElems;
std::unordered_map<AtspiAccessiblePtr, size_t> ptrToIndex;
- Optional<Rectangle> rootPos, rootPos2;
+ Optional<Rectangle> rootPos, focusableChildrenPos;
UIElement::ApplicationCategory application = UIElement::ApplicationCategory::OTHER;
bool hasError = false;
}
}
};
+
auto clb = [callback, updateIsCollapsed, root, visibleRoot](ExecHelper & result) {
auto nav = std::dynamic_pointer_cast<NavigationImpl>(Singleton<UniversalSwitch>::instance().getNavigationInterface());
- if (nav) {
- DEBUG("finalizing navigation");
- updateIsCollapsed(result);
- for (auto &inf : result.elems) {
- DEBUG("elem %30s pos %s relation %d item %d collapsed %d", Atspi::getUniqueId(inf.obj).c_str(),
- inf.pos.toString().c_str(), inf.hasRelation ? 1 : 0, inf.isItem ? 1 : 0, inf.isCollapsed ? 1 : 0);
- }
- std::vector<AcceptedObjectInfo> objects;
- objects.reserve(result.elems.size());
- for (size_t i = 0; i < result.elems.size(); ++i) {
- if (result.elems[i].obj && result.elems[i].pos.size.width > 0 && result.elems[i].pos.size.height > 0)
- objects.push_back({ result.elems[i].obj, result.elems[i].pos });
- }
- auto &r = result.all.rootPos ? result.all.rootPos : result.all.rootPos2;
- if (!r) callback({});
- else callback(nav->reconstructNavigationRows(objects, *r, root, visibleRoot, result.all.application));
- } else {
+ if (!nav) {
DEBUG("no navigation");
callback({});
+ return;
}
+
+ DEBUG("finalizing navigation");
+ updateIsCollapsed(result);
+ std::vector<AcceptedObjectInfo> objects;
+ objects.reserve(result.elems.size());
+ for (auto &elem : result.elems) {
+ DEBUG("elem %30s pos %s relation %d item %d collapsed %d",
+ Atspi::getUniqueId(elem.obj).c_str(), elem.pos.toString().c_str(), elem.hasRelation, elem.isItem, elem.isCollapsed);
+
+ if (elem.obj && elem.pos.size.isPositive())
+ objects.push_back({ elem.obj, elem.pos });
+ }
+ Optional<Rectangle> rect = result.all.focusableChildrenPos ? result.all.focusableChildrenPos : result.all.rootPos;
+ callback(!rect ? NavigationRows {} : nav->reconstructNavigationRows(objects, *rect, root, visibleRoot, result.all.application));
};
- auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
auto sizes = std::make_shared<ExecHelper>(clb, elements.size());
sizes->all.application = application;
- auto queryChildWithGivenRoleAndChildrenCount = [ = ](const AtspiAccessiblePtr & parent, size_t index, size_t expectedCount,
- AtspiRole expectedRole, std::function<void(AtspiAccessiblePtr elem)> callback) {
+ auto failedCallback = [ = ]() {
+ sizes->all.hasError = true;
+ };
+
+ auto updateTotalSize = [ = ](AtspiAccessiblePtr elem, bool focusableChildren) {
auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- if (atspi) {
- atspi->getChildrenCount(parent, [ = ](DBus::ValueOrError<size_t> count) {
- if (continueProcessing(count)) {
- if (std::get<0>(count) != expectedCount) {
- callback(nullptr);
- } else {
- auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- atspi->getChildAtIndex(parent, index, [ = ](DBus::ValueOrError<AtspiAccessiblePtr> child) {
- if (continueProcessing(child)) {
- auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- atspi->getRole(std::get<0>(child), [ = ](DBus::ValueOrError<AtspiRole> role) {
- if (continueProcessing(role)) {
- if (std::get<0>(role) != expectedRole)
- callback(nullptr);
- else
- callback(std::get<0>(child));
- } else {
- sizes->all.hasError = true;
- }
- });
- } else {
- sizes->all.hasError = true;
- }
- });
- }
+ if (!atspi)
+ return;
+
+ atspi->getComponentInterface(elem, [ = ](DBus::ValueOrError<AtspiComponentPtr> col) {
+ if (!continueProcessing(col)) {
+ failedCallback();
+ return;
+ }
+
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ atspi->getScreenPosition(std::get<0>(col), [ = ](DBus::ValueOrError<Rectangle> pos) {
+ if (!continueProcessing(pos)) {
+ failedCallback();
+ return;
+ }
+ if (focusableChildren) {
+ Optional<Rectangle> &optRect = sizes->all.focusableChildrenPos;
+ optRect = optRect ? Rectangle::sum(*optRect, std::get<0>(pos)) : std::get<0>(pos);
} else {
- sizes->all.hasError = true;
+ sizes->all.rootPos = std::get<0>(pos);
}
});
- }
+
+ });
};
- auto updateTotalSize = [ = ](AtspiAccessiblePtr elem, bool first) {
+
+ auto updateFocusableChildrenSize = [ updateTotalSize ](AtspiAccessiblePtr elem) {
+ updateTotalSize(std::move(elem), true);
+ };
+
+ auto calculateAcceptedArea = [ = ](AtspiAccessiblePtr obj) {
+ if (!obj)
+ return;
+
auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- if (atspi) {
- atspi->getComponentInterface(elem, [ = ](DBus::ValueOrError<AtspiComponentPtr> col) {
- if (continueProcessing(col)) {
- auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- atspi->getScreenPosition(std::get<0>(col), [ = ](DBus::ValueOrError<Rectangle> pos) {
- if (continueProcessing(pos)) {
- if (first)
- sizes->all.rootPos = std::get<0>(pos);
- else
- sizes->all.rootPos2 = std::get<0>(pos);
- } else {
- sizes->all.hasError = true;
- }
- });
- } else {
- sizes->all.hasError = true;
+ atspi->getCollectionInterface(obj, [ = ](DBus::ValueOrError<AtspiCollectionPtr> collection) {
+ if (!continueProcessing(collection)) {
+ failedCallback();
+ return;
+ }
+
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ atspi->getMatchedElements(std::get<0>(collection), ATSPI_Collection_SORT_ORDER_CANONICAL, MaximumAllowedElements,
+ Atspi::Matcher().states({ ATSPI_STATE_VISIBLE, ATSPI_STATE_SHOWING, ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_ENABLED, ATSPI_STATE_FOCUSABLE }, ATSPI_Collection_MATCH_ALL).
+ roles({ATSPI_ROLE_INVALID}, ATSPI_Collection_MATCH_NONE),
+ false, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elements) {
+ if (!continueProcessing(elements)) {
+ failedCallback();
+ return;
}
+
+ for (auto &element : std::get<0>(elements))
+ updateFocusableChildrenSize(element);
});
- } else {
- DEBUG("no atspi");
- }
+ });
};
- atspi->getRole(visibleRoot, [ = ](DBus::ValueOrError<AtspiRole> role) {
- if (continueProcessing(role)) {
- auto callback = [ = ](AtspiAccessiblePtr c1) {
- if (c1) {
- queryChildWithGivenRoleAndChildrenCount(c1, 0, 1, ATSPI_ROLE_NOTIFICATION, [ = ](AtspiAccessiblePtr c2) {
- if (c2) {
- queryChildWithGivenRoleAndChildrenCount(c2, 1, 2, ATSPI_ROLE_FILLER, [ = ](AtspiAccessiblePtr c3) {
- if (c3) {
- updateTotalSize(c3, true);
- }
- });
- }
- });
- }
- };
- if (std::get<0>(role) == ATSPI_ROLE_WINDOW) {
- queryChildWithGivenRoleAndChildrenCount(visibleRoot, 0, 1, ATSPI_ROLE_DIALOG, std::move(callback));
- } else {
- callback(visibleRoot);
- }
- } else {
- sizes->all.hasError = true;
- }
- });
+
updateTotalSize(visibleRoot, false);
+ calculateAcceptedArea(visibleRoot);
for (size_t i = 0; i < elements.size(); ++i) {
auto &e = elements[i];
sizes->all.ptrToIndex[e] = i;
}
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
atspi->getMatchedElements(collection, ATSPI_Collection_SORT_ORDER_CANONICAL, MaximumAllowedElements,
Atspi::Matcher().states({ ATSPI_STATE_VISIBLE, ATSPI_STATE_SHOWING, ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_ENABLED, ATSPI_STATE_EXPANDABLE }, ATSPI_Collection_MATCH_ALL).
roles(ignoredAtspiRoles, ATSPI_Collection_MATCH_NONE),
if (continueProcessing(elems))
sizes->all.expandableElems = std::move(std::get<0>(elems));
else
- sizes->all.hasError = true;
+ failedCallback();
});
atspi->getMatchedElements(collection, ATSPI_Collection_SORT_ORDER_CANONICAL, MaximumAllowedElements,
Atspi::Matcher().states({ ATSPI_STATE_VISIBLE, ATSPI_STATE_SHOWING, ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_ENABLED, ATSPI_STATE_EXPANDABLE, ATSPI_STATE_EXPANDED }, ATSPI_Collection_MATCH_ALL).
if (continueProcessing(elems))
sizes->all.expandableAndExpandedElems = std::move(std::get<0>(elems));
else
- sizes->all.hasError = true;
+ failedCallback();
});
atspi->getMatchedElements(collection, ATSPI_Collection_SORT_ORDER_CANONICAL, MaximumAllowedElements,
Atspi::Matcher().states({ ATSPI_STATE_VISIBLE, ATSPI_STATE_SHOWING, ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_ENABLED }, ATSPI_Collection_MATCH_ALL).
sizes->elems[indexIt->second].isItem = true;
}
} else {
- sizes->all.hasError = true;
+ failedCallback();
}
});
if (continueProcessing(val))
sizes->elems[i].pos = std::get<0>(val);
else
- sizes->all.hasError = true;
+ failedCallback();
});
} else {
- sizes->all.hasError = true;
+ failedCallback();
}
});
atspi->getObjectInRelation(e, ATSPI_RELATION_CONTROLLED_BY, [ = ](DBus::ValueOrError<AtspiAccessiblePtr> obj) {
if (continueProcessing(obj))
sizes->elems[i].hasRelation = std::get<0>(obj) != nullptr;
else
- sizes->all.hasError = true;
+ failedCallback();
});
atspi->getParent(e, [ = ](DBus::ValueOrError<AtspiAccessiblePtr> parent) {
if (continueProcessing(parent))
sizes->elems[i].parent = std::move(std::get<0>(parent));
else
- sizes->all.hasError = true;
+ failedCallback();
});
}
}