Fix incorrect deduction of back frame size. 87/169587/7
authorPawel Kurowski <p.kurowski2@samsung.com>
Wed, 7 Feb 2018 19:42:47 +0000 (20:42 +0100)
committerPawel Kurowski <p.kurowski2@samsung.com>
Thu, 8 Feb 2018 17:51:12 +0000 (18:51 +0100)
Previously, to find frame size, tree was searched for fixed signature of roles.
New function calculates smallest rectangle containing all accepted elements.

Change-Id: I0fe08c87ff3e659fb047953fbc91830ef32275c0

src/NavigationInterface.cpp

index 34381c8..0d40b84 100644 (file)
@@ -430,6 +430,7 @@ private:
                }
                return checkIfStillRunning();
        }
+
 #define continueProcessing(args) continueProcessingImpl(__FILE__, __LINE__, args)
 
        void createNavigationRowsFromElements(
@@ -445,6 +446,7 @@ private:
                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;
@@ -453,7 +455,7 @@ private:
                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;
@@ -482,116 +484,97 @@ private:
                                }
                        }
                };
+
                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];
@@ -599,6 +582,7 @@ private:
                        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),
@@ -606,7 +590,7 @@ private:
                        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).
@@ -615,7 +599,7 @@ private:
                        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).
@@ -628,7 +612,7 @@ private:
                                                sizes->elems[indexIt->second].isItem = true;
                                }
                        } else {
-                               sizes->all.hasError = true;
+                               failedCallback();
                        }
                });
 
@@ -641,23 +625,23 @@ private:
                                                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();
                        });
                }
        }