autoscroll functionality 79/157879/16
authorRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Wed, 18 Oct 2017 08:34:01 +0000 (10:34 +0200)
committerRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Tue, 7 Nov 2017 17:08:24 +0000 (18:08 +0100)
Adds support for scrolling operations to universal-switch,
based on additional (non-standard) at-spi functionality.
Requires at-spi functions:
- GetScrollableElement - finds scrollable element (self or ancestor)
- ScrollAuto - starts or continues scrolling animation
- ScrollPage - scrolls single page
- ScrollToEnd - scrolls to the end

Scroll* functions work on scrollable element found by call to
GetScrollableElement.

Change-Id: I1c85201b857ac4c209fdfd9457336079c2d398a6

13 files changed:
src/Atspi.cpp
src/Atspi.hpp
src/MenuBuilder.cpp
src/NavigationInterface.cpp
src/ScrollActivities.cpp [new file with mode: 0644]
src/ScrollActivities.hpp [new file with mode: 0644]
src/SelectActivity.cpp
src/ToggleBoolVconfKeyActivity.cpp
src/UIElement.cpp
src/UIElement.hpp
src/UniversalSwitch.cpp
src/UniversalSwitch.hpp
tests/ui-scenarios/MenuBuilderTests.cpp

index 924189d..bb67d31 100644 (file)
@@ -684,6 +684,66 @@ void Atspi::getRelationSet(const AtspiAccessiblePtr &accessibleObj,
        });
 }
 
+AtspiComponentPtr Atspi::getScrollableElement(const AtspiAccessiblePtr &obj)
+{
+       auto bus = Atspi::getBusName(obj);
+       auto path = Atspi::getPath(obj);
+       auto interface = InterfaceNameFromType<AtspiAccessible>::interfaceName;
+
+       auto dbus = DBusClient { bus, path, interface, eldbusConnection };
+       auto res = dbus.method<AtspiAccessiblePtr()>("GetScrollableElement").call();
+       if (!res) {
+               ERROR("%s", res.getError().message.c_str());
+               return {};
+       }
+       AtspiComponentPtr ptr;
+       convert(ptr, std::get<0>(res));
+       return std::move(ptr);
+}
+
+Optional<double> Atspi::scrollAuto(const AtspiComponentPtr &obj, ScrollDirection direction, size_t pixelsPerSec)
+{
+       auto bus = Atspi::getBusName(obj);
+       auto path = Atspi::getPath(obj);
+       auto interface = InterfaceNameFromType<AtspiComponent>::interfaceName;
+
+       auto dbus = DBusClient { bus, path, interface, eldbusConnection };
+       auto res = dbus.method<double(int32_t, uint32_t)>("ScrollAuto").call((int32_t)direction, (uint32_t)pixelsPerSec);
+       if (!res) {
+               ERROR("%s", res.getError().message.c_str());
+               return {};
+       }
+       return std::get<0>(res);
+}
+
+bool Atspi::scrollPage(const AtspiComponentPtr &obj, ScrollDirection direction)
+{
+       auto bus = Atspi::getBusName(obj);
+       auto path = Atspi::getPath(obj);
+       auto interface = InterfaceNameFromType<AtspiComponent>::interfaceName;
+
+       auto dbus = DBusClient { bus, path, interface, eldbusConnection };
+       auto res = dbus.method<void(int32_t)>("ScrollPage").call((int32_t)direction);
+       if (!res) {
+               ERROR("%s", res.getError().message.c_str());
+       }
+       return bool(res);
+}
+
+bool Atspi::scrollToEnd(const AtspiComponentPtr &obj, ScrollDirection direction)
+{
+       auto bus = Atspi::getBusName(obj);
+       auto path = Atspi::getPath(obj);
+       auto interface = InterfaceNameFromType<AtspiComponent>::interfaceName;
+
+       auto dbus = DBusClient { bus, path, interface, eldbusConnection };
+       auto res = dbus.method<void(int32_t)>("ScrollToEnd").call((int32_t)direction);
+       if (!res) {
+               ERROR("%s", res.getError().message.c_str());
+       }
+       return bool(res);
+}
+
 void Atspi::getScreenPosition(const AtspiComponentPtr &accessibleObj, AsyncCallback<Rectangle> callback) const
 {
        callFunction<DBus::ValueOrError<std::tuple<int32_t, int32_t, int32_t, int32_t>>(uint32_t)>(
@@ -698,7 +758,6 @@ void Atspi::getScreenPosition(const AtspiComponentPtr &accessibleObj, AsyncCallb
                        callback(Rectangle{ { std::get<0>(p), std::get<1>(p) }, { std::get<2>(p), std::get<3>(p) } });
                }
        }, (uint32_t)ATSPI_COORD_TYPE_SCREEN);
-
 }
 
 void Atspi::getObjectInRelation(const AtspiAccessiblePtr &accessibleObj, AtspiRelationType searchType,
@@ -922,6 +981,34 @@ bool Atspi::doActionName(const AtspiActionPtr &accessibleObj, const std::string
        return true;
 }
 
+Optional<size_t> Atspi::getActionCount(const AtspiActionPtr &accessibleObj) const
+{
+       EXIT_IF_NULLPTR(accessibleObj);
+       GError *error = nullptr;
+       auto res = atspi_action_get_n_actions(accessibleObj.get(), &error);
+       PRINT_ERROR_AND_FREE(error);
+       if (res < 0) {
+               DEBUG("res (%d) < 0", res);
+               return {};
+       }
+       return (size_t)res;
+}
+
+Optional<std::string> Atspi::getActionName(const AtspiActionPtr &accessibleObj, size_t num) const
+{
+       EXIT_IF_NULLPTR(accessibleObj);
+       GError *error = nullptr;
+       auto res = atspi_action_get_action_name(accessibleObj.get(), (int)num, &error);
+       PRINT_ERROR_AND_FREE(error);
+       if (!res) {
+               DEBUG("no name");
+               return {};
+       }
+       std::string n { res };
+       g_free(res);
+       return std::move(n);
+}
+
 AtspiCollectionPtr Atspi::getCollectionInterface(const AtspiAccessiblePtr &accessibleObj) const
 {
        EXIT_IF_NULLPTR(accessibleObj);
index 9176245..756acad 100644 (file)
@@ -50,6 +50,8 @@ public:
        AtspiActionPtr getActionInterface(const AtspiAccessiblePtr &accessibleObj) const;
        bool doAction(const AtspiActionPtr &accessibleObj, int action) const;
        bool doActionName(const AtspiActionPtr &accessibleObj, const std::string &action) const;
+       Optional<size_t> getActionCount(const AtspiActionPtr &accessibleObj) const;
+       Optional<std::string> getActionName(const AtspiActionPtr &accessibleObj, size_t num) const;
 
        AtspiCollectionPtr getCollectionInterface(const AtspiAccessiblePtr &accessibleObj) const;
        AtspiValuePtr getValueInterface(const AtspiAccessiblePtr &accessibleObj) const;
@@ -177,6 +179,14 @@ public:
        void getMinimumValue(const AtspiValuePtr &valueInterface, AsyncCallback<double> callback) const;
        void getScreenPosition(const AtspiComponentPtr &obj, AsyncCallback<Rectangle> callback) const;
 
+       enum class ScrollDirection {
+               up = 1, down = 2, right = 3, left = 4
+       };
+       AtspiComponentPtr getScrollableElement(const AtspiAccessiblePtr &obj);
+       Optional<double> scrollAuto(const AtspiComponentPtr &obj, ScrollDirection direction, size_t pixelsPerSec);
+       bool scrollPage(const AtspiComponentPtr &obj, ScrollDirection direction);
+       bool scrollToEnd(const AtspiComponentPtr &obj, ScrollDirection direction);
+
        enum class WindowVisibility : int32_t {
                unknown = -1,
                unobscured = 0,
index 36ec1e7..0edb8c9 100644 (file)
@@ -382,35 +382,35 @@ MenuBuilderImplementation::MenuBuilderImplementation()
        auto speedUpAutoScroll          =       std::make_shared<MenuItemImplementation>(
                                                                                std::vector<std::string> {"IDS_SPEED_UP_AUTO_SCROLL"},
                                                                                defaultImg,
-                                                                               std::string {},
+                                                                               "SCROLL_SPEED_UP",
                                                                                std::string {},
                                                                                std::string {},
                                                                                RepetitionPolicy::multiple);
        auto slowDownAutoScroll         =       std::make_shared<MenuItemImplementation>(
                                                                                std::vector<std::string> {"IDS_SLOW_DOWN_AUTO_SCROLL"},
                                                                                defaultImg,
-                                                                               std::string {},
+                                                                               "SCROLL_SLOW_DOWN",
                                                                                std::string {},
                                                                                std::string {},
                                                                                RepetitionPolicy::multiple);
        auto scrollUp                           =       std::make_shared<MenuItemImplementation>(
                                                                                std::vector<std::string> {"IDS_SCROLL_UP"},
                                                                                defaultImg,
-                                                                               std::string {},
+                                                                               "SCROLL_PAGE_UP",
                                                                                std::string {},
                                                                                std::string {},
                                                                                RepetitionPolicy::multiple);
        auto scrollDown                         =       std::make_shared<MenuItemImplementation>(
                                                                                std::vector<std::string> {"IDS_SCROLL_DOWN"},
                                                                                defaultImg,
-                                                                               std::string {},
+                                                                               "SCROLL_PAGE_DOWN",
                                                                                std::string {},
                                                                                std::string {},
                                                                                RepetitionPolicy::multiple);
        auto scrollTop                          =       std::make_shared<MenuItemImplementation>(
                                                                                std::vector<std::string> {"IDS_SCROLL_TOP"},
                                                                                defaultImg,
-                                                                               std::string {},
+                                                                               "SCROLL_TO_TOP",
                                                                                std::string {},
                                                                                std::string {},
                                                                                RepetitionPolicy::multiple);
@@ -705,7 +705,7 @@ MenuBuilderImplementation::MenuBuilderImplementation()
                }
        }));
        addToMap("IDS_MENU_AUTO_SCROLL_OFF", std::make_shared<MenuImplementation>(MenuImplementation {
-               {turnOnOffAutoScroll, scrollUp, scrollDown, scrollTop},
+               {turnOnOffAutoScroll, scrollDown, scrollUp, scrollTop},
                Alignment::BOTTOM, NavigateToSuperMenu::DENY
        }));
        addToMap("IDS_MENU_AUTO_SCROLL_ON", std::make_shared<MenuImplementation>(MenuImplementation {
index b635497..5cb3112 100644 (file)
@@ -293,9 +293,11 @@ private:
                {
                        if (l.getRowCount() != r.getRowCount()) return false;
                        for (size_t y = 1; y <= l.getRowCount(); ++y) {
+                               ASSERT(l.getColumnCountInRow(y) && r.getColumnCountInRow(y));
                                if (*l.getColumnCountInRow(y) != *r.getColumnCountInRow(y)) return false;
                                auto s = *l.getColumnCountInRow(y);
                                for (size_t x = 1; x <= s; ++x) {
+                                       ASSERT(l.getElement(y, x) && r.getElement(y, x));
                                        auto a = *l.getElement(y, x);
                                        auto b = *r.getElement(y, x);
                                        if (a.obj != b.obj) return false;
@@ -492,8 +494,9 @@ private:
                                        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;
-                               callback(nav->reconstructNavigationRows(objects, r));
+                               auto &r = result.all.rootPos ? result.all.rootPos : result.all.rootPos2;
+                               if (!r) callback({});
+                               else callback(nav->reconstructNavigationRows(objects, *r));
                        } else {
                                DEBUG("no navigation");
                                callback({});
@@ -716,6 +719,7 @@ private:
                        }
 
                        auto ui = std::make_shared<UIElement>(root);
+                       ASSERT(current_rows.getRowSize(0));
                        emitCallback<NavigationCallbackType::ContextChanged>(ui, *current_rows.getRowSize(0));
 
                        emitCallback<NavigationCallbackType::BoxMoved>(Rectangle{}, BoxPositionMode::NONE);
diff --git a/src/ScrollActivities.cpp b/src/ScrollActivities.cpp
new file mode 100644 (file)
index 0000000..e8867d0
--- /dev/null
@@ -0,0 +1,227 @@
+#include "UIActivity.hpp"
+#include "Observer.hpp"
+#include "ActivityFactory.hpp"
+#include "ecore.hpp"
+#include "UniversalSwitch.hpp"
+#include "ScrollActivities.hpp"
+#include "Atspi.hpp"
+#include "VConfKeys.hpp"
+
+struct ScrollActivitiesData {
+       static constexpr size_t stepSize = 50, maxValue = 1000, defaultValue = 200;
+
+       size_t pixelsPerSec = defaultValue;
+       Atspi::ScrollDirection direction = Atspi::ScrollDirection::down;
+       AtspiComponentPtr scrollable;
+       ecore::Timer scrollTimer;
+
+       ScrollActivitiesData(AtspiComponentPtr scrollable) : scrollable(std::move(scrollable))
+       {
+               if (Singleton<VConfInterface>::instance().get(VCONF_KEY_AUTO_SCROLL_ENABLED, false)) {
+                       Singleton<VConfInterface>::instance().set(VCONF_KEY_AUTO_SCROLL_ENABLED, false);
+               }
+       }
+
+       ~ScrollActivitiesData()
+       {
+               stopAutoScroll();
+       }
+
+       ecore::TimerRepetitionPolicy timerCb()
+       {
+               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+               if (!atspi) {
+                       DEBUG("no atspi");
+                       return ecore::TimerRepetitionPolicy::cancel;
+               }
+               atspi->scrollAuto(scrollable, direction, pixelsPerSec);
+               return ecore::TimerRepetitionPolicy::renew;
+       }
+
+       void setScrollable(AtspiComponentPtr scrollableObj)
+       {
+               DEBUG("setting scrollable to %s", Atspi::getUniqueId(scrollableObj).c_str());
+               scrollable = std::move(scrollableObj);
+               direction = Atspi::ScrollDirection::down;
+               stopAutoScroll();
+       }
+       void startAutoScroll()
+       {
+               if (!scrollable) {
+                       DEBUG("no scrollable");
+                       return;
+               }
+               DEBUG("start");
+               scrollTimer.reset(0.5f, [this]() {
+                       return timerCb();
+               });
+       }
+       void stopAutoScroll()
+       {
+               if (!scrollable) {
+                       DEBUG("no scrollable");
+                       return;
+               }
+               DEBUG("stop");
+               scrollTimer.reset();
+               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+               if (!atspi) {
+                       DEBUG("no atspi");
+                       return;
+               }
+               atspi->scrollAuto(scrollable, direction, 0);
+       }
+       void scrollPage(Atspi::ScrollDirection direction)
+       {
+               if (!scrollable) {
+                       DEBUG("no scrollable");
+                       return;
+               }
+               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+               if (!atspi) {
+                       DEBUG("no atspi");
+                       return;
+               }
+               DEBUG("scrolling page (%d)", (int)direction);
+               atspi->scrollPage(scrollable, direction);
+       }
+       void scrollToEnd(Atspi::ScrollDirection direction)
+       {
+               if (!scrollable) {
+                       DEBUG("no scrollable");
+                       return;
+               }
+               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+               if (!atspi) {
+                       DEBUG("no atspi");
+                       return;
+               }
+               DEBUG("scrolling to end (%d)", (int)direction);
+               atspi->scrollToEnd(scrollable, direction);
+       }
+       void speedUp()
+       {
+               if (!scrollable) {
+                       DEBUG("no scrollable");
+                       return;
+               }
+               if (pixelsPerSec + stepSize < maxValue)
+                       pixelsPerSec += stepSize;
+               DEBUG("new speed is %d", (unsigned int)pixelsPerSec);
+       }
+       void slowDown()
+       {
+               if (!scrollable) {
+                       DEBUG("no scrollable");
+                       return;
+               }
+               if (pixelsPerSec >= 2 * stepSize)
+                       pixelsPerSec -= stepSize;
+               DEBUG("new speed is %d", (unsigned int)pixelsPerSec);
+       }
+};
+
+std::shared_ptr<ScrollActivitiesData> createScrollActivitiesData(AtspiComponentPtr scrollable)
+{
+       return std::make_shared<ScrollActivitiesData>(std::move(scrollable));
+}
+
+void toggleAutoScroll(bool turnOn)
+{
+       auto sd = Singleton<UniversalSwitch>::instance().getScrollActivitiesData();
+       DEBUG("turn %s", turnOn ? "on" : "off");
+       if (sd) {
+               if (turnOn) {
+                       sd->startAutoScroll();
+               } else {
+                       sd->stopAutoScroll();
+               }
+       } else {
+               DEBUG("no scroll activities data");
+       }
+}
+
+class ScrollSpeedUpActivity : public UIActivity, RegisterBindableActivity<ScrollSpeedUpActivity>
+{
+public:
+       constexpr static const char *activityType = "SCROLL_SPEED_UP";
+       ScrollSpeedUpActivity() : UIActivity(activityType) {}
+
+       void process() override
+       {
+               auto sd = Singleton<UniversalSwitch>::instance().getScrollActivitiesData();
+               if (sd)
+                       sd->speedUp();
+               else
+                       DEBUG("no scroll activities data");
+               markAsCompleted();
+       }
+};
+
+class ScrollSlowDownActivity : public UIActivity, RegisterBindableActivity<ScrollSlowDownActivity>
+{
+public:
+       constexpr static const char *activityType = "SCROLL_SLOW_DOWN";
+       ScrollSlowDownActivity() : UIActivity(activityType) {}
+
+       void process() override
+       {
+               auto sd = Singleton<UniversalSwitch>::instance().getScrollActivitiesData();
+               if (sd)
+                       sd->slowDown();
+               else
+                       DEBUG("no scroll activities data");
+               markAsCompleted();
+       }
+};
+
+class ScrollPageUpActivity : public UIActivity, RegisterBindableActivity<ScrollPageUpActivity>
+{
+public:
+       constexpr static const char *activityType = "SCROLL_PAGE_UP";
+       ScrollPageUpActivity() : UIActivity(activityType) {}
+
+       void process() override
+       {
+               auto sd = Singleton<UniversalSwitch>::instance().getScrollActivitiesData();
+               if (sd)
+                       sd->scrollPage(Atspi::ScrollDirection::up);
+               else
+                       DEBUG("no scroll activities data");
+               markAsCompleted();
+       }
+};
+
+class ScrollPageDownActivity : public UIActivity, RegisterBindableActivity<ScrollPageDownActivity>
+{
+public:
+       constexpr static const char *activityType = "SCROLL_PAGE_DOWN";
+       ScrollPageDownActivity() : UIActivity(activityType) {}
+
+       void process() override
+       {
+               auto sd = Singleton<UniversalSwitch>::instance().getScrollActivitiesData();
+               if (sd)
+                       sd->scrollPage(Atspi::ScrollDirection::down);
+               else
+                       DEBUG("no scroll activities data");
+               markAsCompleted();
+       }
+};
+
+class ScrollToTopActivity : public UIActivity, RegisterBindableActivity<ScrollToTopActivity>
+{
+public:
+       constexpr static const char *activityType = "SCROLL_TO_TOP";
+       ScrollToTopActivity() : UIActivity(activityType) {}
+
+       void process() override
+       {
+               auto sd = Singleton<UniversalSwitch>::instance().getScrollActivitiesData();
+               if (sd)
+                       sd->scrollToEnd(Atspi::ScrollDirection::up);
+               else
+                       DEBUG("no scroll activities data");
+               markAsCompleted();
+       }
+};
diff --git a/src/ScrollActivities.hpp b/src/ScrollActivities.hpp
new file mode 100644 (file)
index 0000000..732798f
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef SCROLL_ACTIVITIES_HPP
+#define SCROLL_ACTIVITIES_HPP
+
+#include "Atspi.hpp"
+#include <memory>
+
+class ScrollActivitiesData;
+std::shared_ptr<ScrollActivitiesData> createScrollActivitiesData(AtspiComponentPtr scrollable);
+void toggleAutoScroll(bool turnOn);
+
+#endif
index 6f4544c..fd84db4 100644 (file)
@@ -11,6 +11,7 @@
 #include "ecore.hpp"
 #include "ConditionAll.hpp"
 #include "dbusLocators.hpp"
+#include "ScrollActivities.hpp"
 
 #include <Elementary.h>
 #include <ui/efl_util.h>
@@ -44,6 +45,7 @@ public:
 private:
        typedef std::pair<std::shared_ptr<MenuItem>, Elm_Widget_Item *> GengridItemData;
 
+       void deleteScrollActivitiesData();
        void createMenu();
        void removeMenu();
        void createMenuContent();
@@ -62,6 +64,7 @@ private:
        std::string getCompleteLabelOfButtonsKeysMenu();
        void addItemsToMenu(Evas_Object *);
        void gengridItemSelected(Elm_Gengrid_Item *);
+       void markAsCompleted();
 
        static void popupDismissedCb(void *, Evas_Object *, void *);
        static void popupBackCb(void *, Evas_Object *, void *);
@@ -74,6 +77,8 @@ private:
        std::vector<GengridItemData> gengridItemsData;
        std::shared_ptr<Menu> menu;
        std::shared_ptr<UIElement> realUiElement;
+       AtspiComponentPtr scrollableUiElement;
+       std::shared_ptr<ScrollActivitiesData> scrollActivitiesData;
        Optional<bool> realUiElementIsSlider;
        Optional<bool> realUiElementHasEditableText;
        std::unique_ptr<Evas_Object, void(*)(Evas_Object *)> popup;
@@ -90,6 +95,21 @@ SelectActivity::SelectActivity(): UIActivity(activityType), popup(nullptr, evas_
 SelectActivity::~SelectActivity()
 {
        removeMenu();
+       deleteScrollActivitiesData();
+}
+
+void SelectActivity::markAsCompleted()
+{
+       deleteScrollActivitiesData();
+       UIActivity::markAsCompleted();
+}
+
+void SelectActivity::deleteScrollActivitiesData()
+{
+       DEBUG("deleting scroll activities data");
+       Singleton<UniversalSwitch>::instance().setScrollActivitiesData({});
+       ASSERT(scrollActivitiesData.use_count() <= 1);
+       scrollActivitiesData = {};
 }
 
 void SelectActivity::process()
@@ -117,6 +137,16 @@ void SelectActivity::update(const std::shared_ptr<UIElement> &elem)
        }
 
        realUiElement = elem;
+       if (elem->getObject()) {
+               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+               ASSERT(atspi);
+               auto scrollable = atspi->getScrollableElement(elem->getObject());
+               if (scrollable) {
+                       DEBUG("found %s", Atspi::getUniqueId(scrollable).c_str());
+                       scrollableUiElement = std::move(scrollable);
+               }
+       }
+
        if (Singleton<VConfInterface>::instance().get(AUTO_TAP_KEY, false)) {
                autoTapWaitingPeriodCallbackHandle = Singleton<VConfInterface>::instance().registerAndGet<double>(AUTO_TAP_WAITING_PERIOD_KEY, AUTO_TAP_WAITING_PERIOD_DEFAULT_TIME,
                [this](auto x) {
@@ -300,6 +330,11 @@ void SelectActivity::navigateThroughSubMenu(const std::string &subMenuLabel)
                        Singleton<VConfInterface>::instance().set(TEXT_EDITION_MODE, 1);
 
                nestedMenusLabels.push_back(subMenuLabel);
+               if (subMenuLabel == "IDS_MENU_AUTO_SCROLL" && scrollableUiElement) {
+                       DEBUG("creating scroll activities data");
+                       scrollActivitiesData = createScrollActivitiesData(scrollableUiElement);
+                       Singleton<UniversalSwitch>::instance().setScrollActivitiesData(scrollActivitiesData);
+               }
        }
 
        refreshMenu();
@@ -307,6 +342,9 @@ void SelectActivity::navigateThroughSubMenu(const std::string &subMenuLabel)
 
 void SelectActivity::navigateBack()
 {
+       if (nestedMenusLabels.back() == "IDS_MENU_AUTO_SCROLL")
+               deleteScrollActivitiesData();
+
        nestedMenusLabels.pop_back();
        if (nestedMenusLabels.empty()) {
                removeMenu();
index bcd7d2e..109105a 100644 (file)
@@ -2,6 +2,7 @@
 #include "ActivityFactory.hpp"
 #include "VConf.hpp"
 #include "VConfKeys.hpp"
+#include "ScrollActivities.hpp"
 
 template <typename DerivedType>
 class ToggleBoolVconfKeyActivity : public Activity, private RegisterActivity<DerivedType>
@@ -11,10 +12,20 @@ public:
        ToggleBoolVconfKeyActivity() : Activity(activityType)
        {}
 
+       bool toggleVconfKey()
+       {
+               auto isEnabled = getVconfKey();
+               isEnabled = !isEnabled;
+               Singleton<VConfInterface>::instance().set(DerivedType::KEY, isEnabled);
+               return isEnabled;
+       }
+       bool getVconfKey() const
+       {
+               return Singleton<VConfInterface>::instance().get(DerivedType::KEY, false);
+       }
        void process() override
        {
-               auto isEnabled = Singleton<VConfInterface>::instance().get(DerivedType::KEY, false);
-               Singleton<VConfInterface>::instance().set(DerivedType::KEY, !isEnabled);
+               toggleVconfKey();
                markAsCompleted();
        }
 };
@@ -33,9 +44,18 @@ public:
        static constexpr const char *KEY = VCONF_KEY_FEEDBACK_SOUND_ENABLED;
 };
 
-class ToggleAutoScrollEnabledActivity : public ToggleBoolVconfKeyActivity<ToggleAutoScrollEnabledActivity>
+// TODO: class shouldnt back it's boolean state in vconf - we need internal mechanism
+// for communicating state between menu items and activities
+class ScrollTurnOnOffActivity : public ToggleBoolVconfKeyActivity<ScrollTurnOnOffActivity>
 {
 public:
        static constexpr const char *activityType = "TOGGLE_AUTO_SCROLL_ENABLED_ACTIVITY";
        static constexpr const char *KEY = VCONF_KEY_AUTO_SCROLL_ENABLED;
+
+       void process() override
+       {
+               bool isEnabled = toggleVconfKey();
+               toggleAutoScroll(isEnabled);
+               markAsCompleted();
+       }
 };
index 418bb60..dc64814 100644 (file)
@@ -19,12 +19,13 @@ std::shared_ptr<AtspiAccessible> UIElement::getObject() const
        return obj;
 }
 
-void UIElement::getAttributesAsync(std::function<void()> callback)
+void UIElement::getAttributesAsync(std::function<void(bool)> callback)
 {
        atspi->getAttributes(obj,
        [ptr = shared_from_this(), callback](DBus::ValueOrError<std::unordered_map<std::string, std::string>> data) {
                if (!data) {
-                       ASSERT(0, "getAttributesAsync failed");
+                       DEBUG("failed");
+                       callback(false);
                        return;
                }
 
@@ -33,17 +34,19 @@ void UIElement::getAttributesAsync(std::function<void()> callback)
                for (const auto &a : *ptr->attributes)
                        DEBUG("%s = %s", std::get<0>(a).c_str(), std::get<1>(a).c_str());
 
-               callback();
+               callback(true);
        });
 }
 
 void UIElement::getAttributeAsync(const std::string &key, std::function<void(std::string value)> callback)
 {
-       auto find = [ptr = shared_from_this(), key, callback]() {
-               auto value = ptr->attributes->find(key);
-               if (value != ptr->attributes->end()) {
-                       callback(value->second);
-                       return;
+       auto find = [ptr = shared_from_this(), key, callback](bool success) {
+               if (success) {
+                       auto value = ptr->attributes->find(key);
+                       if (value != ptr->attributes->end()) {
+                               callback(value->second);
+                               return;
+                       }
                }
                callback({});
        };
@@ -52,7 +55,7 @@ void UIElement::getAttributeAsync(const std::string &key, std::function<void(std
                getAttributesAsync(find);
                return;
        }
-       find();
+       find(true);
 }
 
 Point UIElement::getScanningCoordinates() const
index 1acbd6d..8147d34 100644 (file)
@@ -26,7 +26,7 @@ public:
        void printDebug();
 
 private:
-       void getAttributesAsync(std::function<void()> callback);
+       void getAttributesAsync(std::function<void(bool)> callback);
 
        std::shared_ptr<Atspi> atspi;
        std::shared_ptr<AtspiAccessible> obj;
index 3932b9d..30e181e 100644 (file)
@@ -78,6 +78,16 @@ void UniversalSwitch::resetA11yDbusProperties()
        dbusClient->method<void(bool)>(dbusLocators::accessibilityEMod::ACCESSORIES_SP_ENABLED).call(false);
 }
 
+std::shared_ptr<ScrollActivitiesData> UniversalSwitch::getScrollActivitiesData() const
+{
+       return scrollActivitiesData.lock();
+}
+
+void UniversalSwitch::setScrollActivitiesData(std::shared_ptr<ScrollActivitiesData> ptr)
+{
+       scrollActivitiesData = ptr;
+}
+
 std::shared_ptr<ScreenScannerManager> UniversalSwitch::getScreenScannerManager() const
 {
        return screenScannerManager;
index 3f3a15a..f3fd265 100644 (file)
@@ -16,6 +16,7 @@ class SwitchManager;
 class TextToSpeech;
 class Window;
 class NavigationInterface;
+class ScrollActivitiesData;
 
 
 class UniversalSwitch
@@ -31,6 +32,8 @@ public:
        std::shared_ptr<Window> getMainWindow();
        std::shared_ptr<TextToSpeech> getTextToSpeech() const;
        std::shared_ptr<NavigationInterface> getNavigationInterface() const;
+       std::shared_ptr<ScrollActivitiesData> getScrollActivitiesData() const;
+       void setScrollActivitiesData(std::shared_ptr<ScrollActivitiesData>);
 
        void initialize();
        void terminate();
@@ -54,6 +57,7 @@ private:
 
        std::shared_ptr<ScreenScannerManager> screenScannerManager;
        std::weak_ptr<Window> mainWindow;
+       std::weak_ptr<ScrollActivitiesData> scrollActivitiesData;
        VConfInterface::CallbackHandle callbackHandle;
 };
 
index 7472c55..c434a83 100644 (file)
@@ -315,7 +315,7 @@ TEST_F(MenuBuilderTest, testContentOfMenuAutoScroll)
                Singleton<VConfInterface>::instance().set(VCONF_KEY_AUTO_SCROLL_ENABLED, false);
        });
        testMenuContent("IDS_MENU_AUTO_SCROLL_OFF", {
-               "IDS_TURN_ON_AUTO_SCROLL", "IDS_SCROLL_UP", "IDS_SCROLL_DOWN", "IDS_SCROLL_TOP"
+               "IDS_TURN_ON_AUTO_SCROLL", "IDS_SCROLL_DOWN", "IDS_SCROLL_UP", "IDS_SCROLL_TOP"
        });
 
        eventLoop::run([]() {