Key context changes with id 93/184993/1
authorRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Wed, 25 Jul 2018 06:09:26 +0000 (08:09 +0200)
committerRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Wed, 25 Jul 2018 06:09:26 +0000 (08:09 +0200)
Context changes are now keyed with id (with newer context change
getting next id), only the newest context change result will be used in
navigation. This fixes race, when two context change processes running
in parallel could result in wrong one being picked.

Change-Id: I3aad796e1f840d4b9918f8c7f02cda676174c5d6

src/NavigationInterface.cpp

index 9726fbc..f056c73 100644 (file)
@@ -123,6 +123,7 @@ private:
        std::unique_ptr<Atspi::WatchHandler> watchHandle;
        ecore::Timer rebuildContextTimer;
        std::shared_ptr<AtspiAccessible> rootObject, keyboardRootObject;
+       unsigned int contextRebuildId = 0;
 
        std::unique_ptr<AtspiEventListener, utils::GObjectUnref> eventListener;
 
@@ -671,7 +672,7 @@ private:
                rebuildContextTimer.reset();
        }
 
-       void rebuildContextFromZero(bool force)
+       void rebuildContextFromZero(unsigned int rebuildId, bool force)
        {
                auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
                if (!atspi) {
@@ -791,15 +792,17 @@ private:
                                struct Contextes {
                                        NavigationImpl *self;
                                        Optional<NavigationRows> real, keyboard;
+                                       unsigned int rebuildId;
                                        ~Contextes()
                                        {
                                                ASSERT(real || keyboard);
                                                if (!real)
                                                        real = std::move(keyboard);
-                                               self->buildNavigationElementsTreeAndEmitContextChanged(std::move(*real), std::move(keyboard));
+                                               self->buildNavigationElementsTreeAndEmitContextChanged(rebuildId, std::move(*real), std::move(keyboard));
                                        }
                                };
                                auto contextes = std::make_shared<Contextes>();
+                               contextes->rebuildId = rebuildId;
                                contextes->self = this;
                                buildNavigationRows(root, application, [ = ](Optional<NavigationRows> rows) {
                                        contextes->real = std::move(rows);
@@ -813,7 +816,7 @@ private:
                                auto nav = std::dynamic_pointer_cast<NavigationImpl>(Singleton<UniversalSwitch>::instance().getNavigationInterface());
                                if (nav) {
                                        DEBUG("restarting context navigation, as selected window was lost");
-                                       nav->initializeRebuildingContext(force, 0.2f);
+                                       nav->initializeRebuildingContext(force);
                                } else {
                                        DEBUG("no navigation");
                                }
@@ -965,8 +968,9 @@ private:
                        out << "*  " << pos.toString() << "  " << Atspi::getUniqueId(obj) << " app " << (int)getApplicationCategory() << "\n";
                }
        };
-       void buildNavigationElementsTree(NavigationRows realContext, Optional<NavigationRows> keyboardContext)
+       void buildNavigationElementsTree(unsigned int rebuildId, NavigationRows realContext, Optional<NavigationRows> keyboardContext)
        {
+               if (contextRebuildId != rebuildId) return;
                using ParentType = const std::shared_ptr<NavigationElement> &;
                std::function<std::shared_ptr<NavigationElement>(ParentType parent, size_t indexInParent, NavigationRows &ctx)> buildRows;
                std::function<std::shared_ptr<NavigationElement>(ParentType parent, size_t indexInParent, NavigationRows &ctx, size_t)> buildSingleRow;
@@ -1028,9 +1032,10 @@ private:
                }
        }
 
-       void buildNavigationElementsTreeAndEmitContextChanged(NavigationRows realContext, Optional<NavigationRows> keyboardContext)
+       void buildNavigationElementsTreeAndEmitContextChanged(unsigned int rebuildId, NavigationRows realContext, Optional<NavigationRows> keyboardContext)
        {
-               buildNavigationElementsTree(realContext, keyboardContext);
+               if (rebuildId != contextRebuildId) return;
+               buildNavigationElementsTree(rebuildId, realContext, keyboardContext);
 
                auto root = realContext.getRootVisibleObject();
                auto pos = (*realContext.getRowSize(0)).getCenterPoint();
@@ -1044,11 +1049,12 @@ private:
        void initializeRebuildingContext(bool force, float delay = 0.2f)
        {
                DEBUG("requesting context rebuild");
+               auto id = ++contextRebuildId;
                rebuildContextTimer.reset(delay,
                [ = ]() {
                        auto nav = std::dynamic_pointer_cast<NavigationImpl>(Singleton<UniversalSwitch>::instance().getNavigationInterface());
                        if (nav) {
-                               nav->rebuildContextFromZero(force);
+                               nav->rebuildContextFromZero(id, force);
                        }
                        return ecore::TimerRepetitionPolicy::cancel;
                });