libaurum: add synchronize API
authorHosang Kim <hosang12.kim@samsung.com>
Mon, 12 Apr 2021 10:45:34 +0000 (19:45 +0900)
committerHosang Kim <hosang12.kim@samsung.com>
Fri, 7 May 2021 10:24:30 +0000 (19:24 +0900)
Add two api for synchronize, waitForEvents, sendKeyAndWaitForEvents.

sample:
mDevice->sendKeyAndWaitForEvents("Left", A11yEvent::EVENT_STATE_CHANGED_FOCUSED, 5000)
mDevice->waitForEvents(A11yEvent::EVENT_WINDOW_DEACTIVATE, 5000)

Change-Id: If3886af4b2331f5e50f35e1dfcd27780c9618b93

18 files changed:
libaurum/inc/A11yEvent.h [new file with mode: 0644]
libaurum/inc/Accessibility/AccessibleWatcher.h
libaurum/inc/Impl/Accessibility/AtspiAccessibleWatcher.h
libaurum/inc/Impl/Accessibility/MockAccessibleWatcher.h
libaurum/inc/Runnable/Runnable.h [new file with mode: 0644]
libaurum/inc/Runnable/Runnables.h [new file with mode: 0644]
libaurum/inc/Runnable/SendKeyRunnable.h [new file with mode: 0644]
libaurum/inc/UiDevice.h
libaurum/inc/bitmask.h [new file with mode: 0644]
libaurum/meson.build
libaurum/src/A11yEvent.cc [new file with mode: 0644]
libaurum/src/Impl/Accessibility/AtspiAccessibleNode.cc
libaurum/src/Impl/Accessibility/AtspiAccessibleWatcher.cc
libaurum/src/Impl/Accessibility/MockAccessibleWatcher.cc
libaurum/src/Runnable/SendKeyRunnable.cc [new file with mode: 0644]
libaurum/src/Runnable/meson.build [new file with mode: 0644]
libaurum/src/UiDevice.cc
libaurum/src/meson.build

diff --git a/libaurum/inc/A11yEvent.h b/libaurum/inc/A11yEvent.h
new file mode 100644 (file)
index 0000000..43da498
--- /dev/null
@@ -0,0 +1,49 @@
+#pragma once
+#include "bitmask.h"
+
+#include <string>
+
+enum class A11yEvent {
+     EVENT_NONE = 0x00000,
+     EVENT_WINDOW_CREATE = 0x00001,
+     EVENT_WINDOW_CLOSE = 0x00002,
+     EVENT_WINDOW_MINIMIZE = 0x00004,
+     EVENT_WINDOW_MAXIMIZE = 0x00008,
+     EVENT_WINDOW_RESTORE = 0x00010,
+     EVENT_WINDOW_ACTIVATE = 0x00020,
+     EVENT_WINDOW_DEACTIVATE = 0x00040,
+     EVENT_WINDOW_RAISE = 0x00080,
+     EVENT_WINDOW_LOWER = 0x00100,
+     EVENT_WINDOW_MOVE = 0x00200,
+     EVENT_WINDOW_RESIZE = 0x00400,
+
+     EVENT_TEXT_CHANGED_INSERT = 0x00800,
+     EVENT_TEXT_CHANGED_DELETE = 0x01000,
+
+     EVENT_STATE_CHANGED_VISIBLE = 0x02000,
+     EVENT_STATE_CHANGED_FOCUSED = 0x04000,
+     EVENT_STATE_CHANGED_CHECKED = 0x08000,
+     EVENT_STATE_CHANGED_PRESSED = 0x10000,
+     EVENT_STATE_CHANGED_SELECTED = 0x20000,
+};
+
+enableEnumClassBitfield(A11yEvent);
+
+class A11yEventInfo {
+public:
+       A11yEventInfo();
+       A11yEventInfo(A11yEvent event, std::string name = "", std::string pkg = "");
+       A11yEventInfo(std::string event, std::string name = "", std::string pkg = "");
+       ~A11yEventInfo();
+public:
+       A11yEvent getEvent();
+    A11yEvent getEvent(std::string event);
+       std::string getName();
+       std::string getPkg();
+
+protected:
+       const A11yEvent mEvent;
+       const std::string mName;
+       const std::string mPkg;
+};
+
index d767742..e695057 100644 (file)
@@ -6,6 +6,8 @@
 #include "AccessibleNode.h"
 #include "AccessibleUtils.h"
 #include "IEventSource.h"
+#include "Runnable.h"
+#include "A11yEvent.h"
 
 #include <memory>
 #include <vector>
@@ -57,6 +59,12 @@ public:
      */
     virtual std::vector<std::shared_ptr<AccessibleApplication>> getApplications(void) const = 0;
 
+    /**s
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout) = 0;
+
 public:
     /**
      * @brief TBD
@@ -92,4 +100,4 @@ private:
      * @brief TBD
      */
     std::mutex mLock;
-};
\ No newline at end of file
+};
index 3eb3566..3d8294f 100644 (file)
@@ -97,6 +97,12 @@ public:
      */
     virtual std::vector<std::shared_ptr<AccessibleApplication>> getApplications(void) const override;
 
+    /**
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout) override;
+
 public:
     /**
      * @brief TBD
@@ -140,6 +146,11 @@ public:
      */
     void onObjectDefunct(AtspiAccessible* node) override;
 
+    /**
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    static void onEventListener(AtspiEvent *event, void *user_data);
 private:
     /**
      * @brief TBD
@@ -167,12 +178,25 @@ private:
 
     void print_debug();
 
-private:
+    /**
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    void addEventListener(AtspiEventListener *listener, A11yEvent type);
+
+    /**
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    void removeEventListener(AtspiEventListener *listener, A11yEvent type);
+
+public:
     /**
      * @brief TBD
      */
-    static AtspiEventListener *                   listener;
+    static guint timeoutId;
 
+private:
     /**
      * @brief TBD
      */
@@ -198,4 +222,13 @@ private:
      */
     std::map<AtspiAccessible *, AtspiAccessible *> mWindowAppMap;
 
-};
\ No newline at end of file
+    /**
+     * @brief TBD
+     */
+    static GThread *                                      mEventThread;
+
+    /**
+     * @brief TBD
+     */
+       static std::vector<std::shared_ptr<A11yEventInfo>>    mEventQueue;
+};
index 5262cf2..c183248 100644 (file)
@@ -42,6 +42,12 @@ public:
      */
     virtual std::vector<std::shared_ptr<AccessibleApplication>> getApplications(void) const override;
 
+    /**
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout) override;
+
 public:
     /**
      * @brief TBD
@@ -60,4 +66,4 @@ private:
      * @brief TBD
      */
     std::vector<std::shared_ptr<AccessibleApplication>> mApplicationList;
-};
\ No newline at end of file
+};
diff --git a/libaurum/inc/Runnable/Runnable.h b/libaurum/inc/Runnable/Runnable.h
new file mode 100644 (file)
index 0000000..354c90f
--- /dev/null
@@ -0,0 +1,9 @@
+#pragma once
+
+class Runnable
+{
+public:
+       virtual ~Runnable() { }
+       virtual void run() const = 0;
+};
+
diff --git a/libaurum/inc/Runnable/Runnables.h b/libaurum/inc/Runnable/Runnables.h
new file mode 100644 (file)
index 0000000..1428466
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+#include "SendKeyRunnable.h"
diff --git a/libaurum/inc/Runnable/SendKeyRunnable.h b/libaurum/inc/Runnable/SendKeyRunnable.h
new file mode 100644 (file)
index 0000000..57cf886
--- /dev/null
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <string>
+
+#include "Runnable.h"
+
+class SendKeyRunnable : public Runnable {
+protected:
+       std::string mKeycode;
+
+public:
+    SendKeyRunnable(std::string keycode);
+    void run() const override;
+};
index ce9fd1f..504ceff 100644 (file)
@@ -10,6 +10,9 @@
 #include "AccessibleNode.h"
 #include "Waiter.h"
 
+#include "Runnable.h"
+#include "A11yEvent.h"
+
 #include <functional>
 #include <string>
 
@@ -158,6 +161,23 @@ public:
     std::shared_ptr<UiObject> waitFor(
         const std::function<std::shared_ptr<UiObject>(const ISearchable *)>
             condition) const;
+
+    /**
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    bool waitForEvents(
+        const A11yEvent type, const int timeout) const;
+
+    /**
+     * @brief TBD
+     * @since_tizen 6.5
+     */
+    bool sendKeyAndWaitForEvents(
+        const std::string keycode, const A11yEvent type, const int timeout) const;
+private:
+    bool executeAndWaitForEvents(
+        const Runnable *cmd, const A11yEvent type, const int timeout) const;
 public:
     /**
      * @brief TBD
@@ -206,4 +226,4 @@ private:
      * @brief TBD
      */
     const Waiter *mWaiter;
-};
\ No newline at end of file
+};
diff --git a/libaurum/inc/bitmask.h b/libaurum/inc/bitmask.h
new file mode 100644 (file)
index 0000000..0dda2f6
--- /dev/null
@@ -0,0 +1,72 @@
+#pragma once
+#include <type_traits>
+
+template<typename E>
+struct enable_bitmask_operators{
+    static const bool enable=false;
+};
+
+#define enableEnumClassBitfield(E) template<> \
+        struct enable_bitmask_operators<E>{   \
+            static const bool enable=true;    \
+        }
+
+template<typename E>
+typename std::enable_if_t<enable_bitmask_operators<E>::enable,E>
+operator|(E lhs,E rhs){
+    typedef typename std::underlying_type_t<E> underlying;
+    return static_cast<E>(
+        static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
+}
+
+template<typename E>
+typename std::enable_if_t<enable_bitmask_operators<E>::enable,E>
+operator&(E lhs,E rhs){
+    typedef typename std::underlying_type_t<E> underlying;
+    return static_cast<E>(
+        static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
+}
+
+template<typename E>
+typename std::enable_if_t<enable_bitmask_operators<E>::enable,E>
+operator^(E lhs,E rhs){
+    typedef typename std::underlying_type_t<E> underlying;
+    return static_cast<E>(
+        static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
+}
+
+template<typename E>
+typename std::enable_if_t<enable_bitmask_operators<E>::enable,E>
+operator~(E lhs){
+    typedef typename std::underlying_type_t<E> underlying;
+    return static_cast<E>(
+        ~static_cast<underlying>(lhs));
+}
+
+template<typename E>
+typename std::enable_if_t<enable_bitmask_operators<E>::enable,E&>
+operator|=(E& lhs,E rhs){
+    typedef typename std::underlying_type_t<E> underlying;
+    lhs=static_cast<E>(
+        static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
+    return lhs;
+}
+
+template<typename E>
+typename std::enable_if_t<enable_bitmask_operators<E>::enable,E&>
+operator&=(E& lhs,E rhs){
+    typedef typename std::underlying_type_t<E> underlying;
+    lhs=static_cast<E>(
+        static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
+    return lhs;
+}
+
+template<typename E>
+typename std::enable_if_t<enable_bitmask_operators<E>::enable,E&>
+operator^=(E& lhs,E rhs){
+    typedef typename std::underlying_type_t<E> underlying;
+    lhs=static_cast<E>(
+        static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
+    return lhs;
+}
+
index 83417cb..85afdb3 100644 (file)
@@ -9,6 +9,8 @@ libaurum_install_inc = [
   './inc/Waiter.h',
   './inc/ISearchable.h',
   './inc/IDevice.h',
+  './inc/A11yEvent.h',
+  './inc/bitmask.h',
   './inc/Accessibility/AccessibleNode.h',
   './inc/Accessibility/AccessibleUtils.h',
   './inc/Accessibility/AccessibleWatcher.h',
@@ -16,6 +18,7 @@ libaurum_install_inc = [
   './inc/Accessibility/AccessibleWindow.h',
   './inc/Accessibility/IEventConsumer.h',
   './inc/Accessibility/IEventSource.h',
+  './inc/Runnable/Runnable.h',
   './inc/Misc/Point2D.h',
   './inc/Misc/Rect.h',
   './inc/Aurum.h',
@@ -27,6 +30,7 @@ libaurum_inc = [
   include_directories('./inc/Impl'),
   include_directories('./inc/Impl/Accessibility'),
   include_directories('./inc/Misc'),
+  include_directories('./inc/Runnable/'),
   root_inc,
   loguru_inc,
 ]
diff --git a/libaurum/src/A11yEvent.cc b/libaurum/src/A11yEvent.cc
new file mode 100644 (file)
index 0000000..325d6fb
--- /dev/null
@@ -0,0 +1,65 @@
+#include "A11yEvent.h"
+
+#include <unordered_map>
+
+A11yEventInfo::A11yEventInfo() : A11yEventInfo(A11yEvent::EVENT_NONE, nullptr, nullptr) {}
+
+A11yEventInfo::~A11yEventInfo() {}
+
+A11yEventInfo::A11yEventInfo(A11yEvent event, std::string name, std::string pkg)
+       : mEvent(event),
+         mName(name),
+         mPkg(pkg)
+{
+}
+
+A11yEventInfo::A11yEventInfo(std::string event, std::string name, std::string pkg)
+       : mEvent(getEvent(event)),
+         mName(name),
+         mPkg(pkg)
+{
+}
+
+
+static std::unordered_map<std::string,A11yEvent> const table = { {"window:create", A11yEvent::EVENT_WINDOW_CREATE},
+                                                                                                                                {"window:close", A11yEvent::EVENT_WINDOW_CLOSE},
+                                                                                                                                {"window:minimize", A11yEvent::EVENT_WINDOW_MINIMIZE},
+                                                                                                                                {"window:maxmize", A11yEvent::EVENT_WINDOW_MAXIMIZE},
+                                                                                                                                {"window:restore", A11yEvent::EVENT_WINDOW_RESTORE},
+                                                                                                                                {"window:activate", A11yEvent::EVENT_WINDOW_ACTIVATE},
+                                                                                                                                {"window:deactivate", A11yEvent::EVENT_WINDOW_DEACTIVATE},
+                                                                                                                                {"window:raise", A11yEvent::EVENT_WINDOW_RAISE},
+                                                                                                                                {"window:lower", A11yEvent::EVENT_WINDOW_LOWER},
+                                                                                                                                {"window:resize", A11yEvent::EVENT_WINDOW_RESIZE},
+                                                                                                                                {"window:move", A11yEvent::EVENT_WINDOW_MOVE},
+                                                                                                                                {"object:text-changed:insert", A11yEvent::EVENT_TEXT_CHANGED_INSERT},
+                                                                                                                                {"object:text-changed:delete", A11yEvent::EVENT_TEXT_CHANGED_DELETE},
+                                                                                                                                {"object:state-changed:VISIBLE", A11yEvent::EVENT_STATE_CHANGED_VISIBLE},
+                                                                                                                                {"object:state-changed:focused", A11yEvent::EVENT_STATE_CHANGED_FOCUSED},
+                                                                                                                                {"object:state-changed:checked", A11yEvent::EVENT_STATE_CHANGED_CHECKED},
+                                                                                                                                {"object:state-changed:pressed", A11yEvent::EVENT_STATE_CHANGED_PRESSED},
+                                                                                                                                {"object:state-changed:selected", A11yEvent::EVENT_STATE_CHANGED_SELECTED} };
+
+A11yEvent A11yEventInfo::getEvent()
+{
+       return mEvent;
+}
+
+A11yEvent A11yEventInfo::getEvent(std::string event)
+{
+       auto it = table.find(event);
+       if (it != table.end()) {
+               return it->second;
+       }
+       return A11yEvent::EVENT_NONE;
+}
+
+std::string A11yEventInfo::getName()
+{
+       return mName;
+}
+
+std::string A11yEventInfo::getPkg()
+{
+       return mPkg;
+}
index 2cf3fe1..1b2c4db 100644 (file)
@@ -398,4 +398,4 @@ void AtspiAccessibleNode::setFeatureProperty(AtspiStateType type)
         default:
         break;
     }
-}
\ No newline at end of file
+}
index 59dfe94..0925ef6 100644 (file)
@@ -5,10 +5,14 @@
 #include "AtspiAccessibleNode.h"
 #include "AtspiWrapper.h"
 #include <algorithm>
+#include <chrono>
+#include <thread>
+#include <iostream>
 
 #include <loguru.hpp>
 
-AtspiEventListener *AtspiAccessibleWatcher::listener = nullptr;
+std::vector<std::shared_ptr<A11yEventInfo>> AtspiAccessibleWatcher::mEventQueue;
+GThread *AtspiAccessibleWatcher::mEventThread = nullptr;
 
 static bool iShowingNode(AtspiAccessible *node)
 {
@@ -40,7 +44,6 @@ findActiveNode(AtspiAccessible *node, int depth,
     std::vector<AtspiAccessible *> ret{};
 
     if (iShowingNode(node)) {
-        g_object_ref(node);
         char *name = AtspiWrapper::Atspi_accessible_get_name(node, NULL);
         if (name) {
             LOG_SCOPE_F(INFO, "%s", name);
@@ -67,6 +70,27 @@ findActiveNode(AtspiAccessible *node, int depth,
     return ret;
 }
 
+static gpointer _event_thread_loop (gpointer data)
+{
+    LOG_F(INFO, "event thread start");
+    AtspiEventListener * listener =
+        atspi_event_listener_new(AtspiAccessibleWatcher::onAtspiEvents, NULL, NULL);
+
+    atspi_event_listener_register(listener, "window:", NULL);
+    atspi_event_listener_register(listener, "object:state-changed:focused", NULL);
+    atspi_event_listener_register(listener, "object:text-changed:insert", NULL);
+
+    atspi_event_main();
+end:
+    LOG_F(INFO, "event thread end");
+    atspi_event_listener_deregister(listener, "object:state-changed:focused", NULL);
+    atspi_event_listener_deregister(listener, "object:text-changed:insert", NULL);
+    atspi_event_listener_deregister(listener, "window:", NULL);
+
+    g_object_unref(listener);
+
+    return NULL;
+}
 AtspiAccessibleWatcher::AtspiAccessibleWatcher()
 : mDbusProxy{nullptr}
 {
@@ -75,11 +99,7 @@ AtspiAccessibleWatcher::AtspiAccessibleWatcher()
     atspi_set_main_context (g_main_context_default ());
     atspi_init();
 
-    listener =
-        atspi_event_listener_new(AtspiAccessibleWatcher::onAtspiEvents, this, NULL);
-
-    atspi_event_listener_register(listener, "window:", NULL);
-    atspi_event_listener_register(listener, "object:", NULL);
+    mEventThread = g_thread_new("AtspiEventThread", _event_thread_loop, nullptr);
 
     mDbusProxy = g_dbus_proxy_new_for_bus_sync(
         G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE,
@@ -93,7 +113,6 @@ AtspiAccessibleWatcher::AtspiAccessibleWatcher()
         g_variant_new("(ssv)", "org.a11y.Status", "IsEnabled", enabled_variant),
         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
 
-    g_variant_unref(enabled_variant);
     g_variant_unref(result);
 }
 
@@ -108,23 +127,38 @@ AtspiAccessibleWatcher::~AtspiAccessibleWatcher()
         g_variant_new("(ssv)", "org.a11y.Status", "IsEnabled", enabled_variant),
         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
 
-    atspi_event_listener_deregister(listener, "window:", NULL);
-    atspi_event_listener_deregister(listener, "object:", NULL);
-
-    g_object_unref(listener);
     g_object_unref(mDbusProxy);
-    g_variant_unref(enabled_variant);
     g_variant_unref(result);
 
     atspi_event_quit();
+    g_thread_join(mEventThread);
     atspi_exit();
 }
 
-
 void AtspiAccessibleWatcher::onAtspiEvents(AtspiEvent *event, void *user_data)
 {
     AtspiWrapper::lock();
-    char *name = NULL, *pname = NULL;
+    if (!event->source)
+    {
+        AtspiWrapper::unlock();
+        return;
+    }
+    char *name = NULL, *pkg = NULL;
+    name = AtspiWrapper::Atspi_accessible_get_name(event->source, NULL);
+
+    AtspiAccessible *app = AtspiWrapper::Atspi_accessible_get_application(event->source, NULL);
+    if (app)
+    {
+        pkg = AtspiWrapper::Atspi_accessible_get_name(app, NULL);
+        g_object_unref(app);
+    }
+    else
+        pkg = strdup("");
+
+    mEventQueue.push_back(std::make_shared<A11yEventInfo>(std::string(event->type), std::string(name), std::string(pkg)));
+    if (name) free(name);
+    if (pkg) free(pkg);
+/*    char *name = NULL, *pname = NULL;
     AtspiAccessibleWatcher *instance = (AtspiAccessibleWatcher *)user_data;
 
     if (!event->source)
@@ -159,7 +193,7 @@ void AtspiAccessibleWatcher::onAtspiEvents(AtspiEvent *event, void *user_data)
             static_cast<AtspiAccessible *>(event->source));
     }
     if (name) free(name);
-    if (pname) free(pname);
+    if (pname) free(pname);*/
     AtspiWrapper::unlock();
 }
 
@@ -268,6 +302,47 @@ std::vector<std::shared_ptr<AccessibleApplication>> AtspiAccessibleWatcher::getA
     return ret;
 }
 
+#define COMPARE(A, B) \
+    (B != A11yEvent::EVENT_NONE) && ((A & B) == B)
+
+bool AtspiAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout)
+{
+    AtspiWrapper::lock();
+    mEventQueue.clear();
+    AtspiWrapper::unlock();
+    if (cmd)
+        cmd->run();
+
+    std::chrono::system_clock::time_point start =
+        std::chrono::system_clock::now();
+       while (true)
+    {
+        std::vector<std::shared_ptr<A11yEventInfo>> localEvents;
+        AtspiWrapper::lock();
+        localEvents.assign(mEventQueue.begin(), mEventQueue.end());
+        mEventQueue.clear();
+        AtspiWrapper::unlock();
+
+               if (!localEvents.empty())
+               {
+            for (const auto &event : localEvents) {
+                if (COMPARE(type, event->getEvent()))
+                               {
+                    LOG_F(INFO, "type %d == %d name %s pkg %s",static_cast<int>(type), static_cast<int>(event->getEvent()), event->getName().c_str(), event->getPkg().c_str()); 
+                                   return true; 
+                               }
+                       }
+               }
+        if ((std::chrono::system_clock::now() - start) >
+            std::chrono::milliseconds{timeout})
+            break;
+        std::this_thread::sleep_for(
+            std::chrono::milliseconds{100});
+    }
+
+    return false;
+}
+
 bool AtspiAccessibleWatcher::removeFromActivatedList(AtspiAccessible *node)
 {
     LOG_SCOPE_F(INFO,"remove from activelist node %p", node);
index 68f7f54..379a25b 100644 (file)
@@ -37,4 +37,9 @@ std::shared_ptr<MockAccessibleApplication> MockAccessibleWatcher::addApplication
     std::shared_ptr<MockAccessibleApplication> app = std::make_shared<MockAccessibleApplication>(appNode);
     this->addApplication(app);
     return app;
-}
\ No newline at end of file
+}
+
+bool MockAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout)
+{
+    return true;
+}
diff --git a/libaurum/src/Runnable/SendKeyRunnable.cc b/libaurum/src/Runnable/SendKeyRunnable.cc
new file mode 100644 (file)
index 0000000..88e1fef
--- /dev/null
@@ -0,0 +1,18 @@
+#include "SendKeyRunnable.h"
+
+#include <UiDevice.h>
+#include <loguru.hpp>
+
+SendKeyRunnable::SendKeyRunnable(std::string keycode)
+    : mKeycode{keycode}
+{
+}
+
+void SendKeyRunnable::run() const
+{
+       LOG_F(INFO, "sendKey %s",mKeycode.c_str());
+       std::shared_ptr<UiDevice> mDevice = UiDevice::getInstance();
+       mDevice->pressKeyCode(mKeycode.c_str(), KeyRequestType::PRESS);
+       mDevice->pressKeyCode(mKeycode.c_str(), KeyRequestType::RELEASE);
+}
+
diff --git a/libaurum/src/Runnable/meson.build b/libaurum/src/Runnable/meson.build
new file mode 100644 (file)
index 0000000..f92c75d
--- /dev/null
@@ -0,0 +1,3 @@
+libaurum_src += [
+    files('SendKeyRunnable.cc')
+]
index 6b6a788..b9b5ab4 100644 (file)
@@ -7,6 +7,8 @@
 #endif
 #include "MockDeviceImpl.h"
 
+#include "Runnables.h"
+
 #include <unistd.h>
 #include <utility>
 #include <vector>
@@ -121,6 +123,25 @@ bool UiDevice::waitForIdle() const
     return true;
 }
 
+bool UiDevice::waitForEvents(
+       const A11yEvent type, const int timeout) const
+{
+    return executeAndWaitForEvents(NULL, type, timeout);
+}
+
+bool UiDevice::executeAndWaitForEvents(
+       const Runnable *cmd, const A11yEvent type, const int timeout) const
+{
+    return AccessibleWatcher::getInstance()->executeAndWaitForEvents(cmd, type, timeout);
+}
+
+bool UiDevice::sendKeyAndWaitForEvents(
+       const std::string keycode, const A11yEvent type, const int timeout) const
+{
+    std::unique_ptr<SendKeyRunnable> cmd = std::make_unique<SendKeyRunnable>(keycode);
+    return executeAndWaitForEvents(cmd.get(), type, timeout);
+}
+
 bool UiDevice::click(const int x, const int y)
 {
     bool result =  mDeviceImpl->click(x, y);
index be6ee85..0a651e5 100644 (file)
@@ -8,7 +8,9 @@ libaurum_src += [
   files('Until.cc'),
   files('Waiter.cc'),
   files('PartialMatch.cc'),
+  files('A11yEvent.cc'),
 ]
 
 subdir('Accessibility')
-subdir('Impl')
\ No newline at end of file
+subdir('Impl')
+subdir('Runnable')