From: Woochan Lee Date: Fri, 17 Feb 2023 04:15:45 +0000 (+0900) Subject: Introduce EVENT_WINDOW_IDLE event X-Git-Tag: accepted/tizen/unified/20230310.062704^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=eeb36fcc145a8a9f6962f1bf8bbf1e9a8fa4d3e7;p=platform%2Fcore%2Fuifw%2Faurum.git Introduce EVENT_WINDOW_IDLE event It support device idle point to user. user can use this event instead of waiting ramdom time for ui update. Change-Id: I72b24ff39b7613484c75280583ce2c41dceddc9b --- diff --git a/libaurum/inc/A11yEvent.h b/libaurum/inc/A11yEvent.h index d891e88..beb1ab7 100644 --- a/libaurum/inc/A11yEvent.h +++ b/libaurum/inc/A11yEvent.h @@ -43,6 +43,7 @@ enum class A11yEvent { EVENT_WINDOW_LOWER = 0x00100, EVENT_WINDOW_MOVE = 0x00200, EVENT_WINDOW_RESIZE = 0x00400, + EVENT_WINDOW_RENDER_POST = 0x00800, EVENT_TEXT_CHANGED_INSERT = 0x00800, EVENT_TEXT_CHANGED_DELETE = 0x01000, diff --git a/libaurum/inc/Accessibility/AccessibleWatcher.h b/libaurum/inc/Accessibility/AccessibleWatcher.h index c3b9308..df6a0a4 100644 --- a/libaurum/inc/Accessibility/AccessibleWatcher.h +++ b/libaurum/inc/Accessibility/AccessibleWatcher.h @@ -104,12 +104,14 @@ public: * @param[in] cmd @Runnable * @param[in] type @A11yEvent * @param[in] timeout time(millisecond) to wait event occur + * @param[in] obj @AccessibleNode + * @param[in] count count of render post evnet * * @return true if event occur in time, else false * * @since_tizen 6.5 */ - virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName) = 0; + virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName, std::shared_ptr obj, const int count) = 0; /** * @brief Gets active application map. diff --git a/libaurum/inc/Impl/Accessibility/AtspiAccessibleWatcher.h b/libaurum/inc/Impl/Accessibility/AtspiAccessibleWatcher.h index 967b010..fb9968a 100644 --- a/libaurum/inc/Impl/Accessibility/AtspiAccessibleWatcher.h +++ b/libaurum/inc/Impl/Accessibility/AtspiAccessibleWatcher.h @@ -50,6 +50,19 @@ enum class WindowActivateInfoType { KEYBOARD = 0x04, }; +/** + * @internal + * + * @brief Idle event state enum class. + * + * @since_tizen 7.5 + */ +enum class IdleEventState { + IDLE_LISTEN_START = 0x00, + IDLE_LISTEN_READY = 0x01, + IDLE_LISTEN_DONE = 0x02, +}; + /** * @internal * @@ -105,7 +118,7 @@ public: /** * @copydoc @AccessibleWatcher::executeAndWaitForEvents() */ - virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName) override; + virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName, std::shared_ptr obj, const int count) override; /** * @copydoc @AccessibleWatcher::getActiveAppMap() @@ -149,6 +162,7 @@ private: bool removeFromWindowSet(AtspiAccessible *node); bool addToWindowSet(AtspiAccessible *node); static gpointer eventThreadLoop(gpointer data); + static gpointer timerThread(gpointer data); void appendApp(AtspiAccessibleWatcher *instance, AtspiAccessible *app, char *pkg); void removeApp(AtspiAccessibleWatcher *instance, AtspiAccessible *app, char *pkg); @@ -166,6 +180,10 @@ private: bool isTv; std::mutex XMLMutex; std::map>> mHandlers; + static GThread *mTimerThread; + static gint64 mStartTime; + static IdleEventState isIdle; + static int mRenderCount; }; } diff --git a/libaurum/inc/Impl/Accessibility/AtspiWrapper.h b/libaurum/inc/Impl/Accessibility/AtspiWrapper.h index 0389c30..1cdd2a8 100644 --- a/libaurum/inc/Impl/Accessibility/AtspiWrapper.h +++ b/libaurum/inc/Impl/Accessibility/AtspiWrapper.h @@ -69,6 +69,7 @@ public: static guint Atspi_accessible_get_process_id(AtspiAccessible *node, GError **error); static gchar *Atspi_accessible_get_toolkit_name(AtspiAccessible *node, GError **error); static AtspiRect *Atspi_text_get_minimum_bounding_rectangles(AtspiText* obj, gint start_offset, gint end_offset, AtspiCoordType type, GError** error); + static void Atspi_accessible_set_listen_post_render(AtspiAccessible *obj, gboolean enabled, GError **error); private: static std::recursive_mutex mMutex; diff --git a/libaurum/inc/Impl/Accessibility/MockAccessibleWatcher.h b/libaurum/inc/Impl/Accessibility/MockAccessibleWatcher.h index 80209bf..622e26d 100644 --- a/libaurum/inc/Impl/Accessibility/MockAccessibleWatcher.h +++ b/libaurum/inc/Impl/Accessibility/MockAccessibleWatcher.h @@ -71,7 +71,7 @@ public: * @brief TBD * @since_tizen 6.5 */ - virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName) override; + virtual bool executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName, std::shared_ptr obj, const int count) override; virtual bool registerCallback(const A11yEvent type, EventHandler cb, void *data) override; diff --git a/libaurum/inc/UiDevice.h b/libaurum/inc/UiDevice.h index b79fbe6..1bc1f31 100644 --- a/libaurum/inc/UiDevice.h +++ b/libaurum/inc/UiDevice.h @@ -365,13 +365,14 @@ public: * @param[in] type one of @A11yEvent * @param[in] timeout time(millisecond) to wait event occur * @param[in] packageName package name that event occurs + * @param[in] count count of render post evnet * * @return true if event happened in time, otherwise false * * @since_tizen 6.5 */ bool executeAndWaitForEvents( - const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName) const; + const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName, const int count) const; /** * @brief Register atspi event callback. diff --git a/libaurum/src/A11yEvent.cc b/libaurum/src/A11yEvent.cc index e91ed94..6505dc5 100644 --- a/libaurum/src/A11yEvent.cc +++ b/libaurum/src/A11yEvent.cc @@ -51,6 +51,7 @@ static std::unordered_map const table = { {"window:create {"window:lower", A11yEvent::EVENT_WINDOW_LOWER}, {"window:resize", A11yEvent::EVENT_WINDOW_RESIZE}, {"window:move", A11yEvent::EVENT_WINDOW_MOVE}, + {"window:renderpost", A11yEvent::EVENT_WINDOW_RENDER_POST}, {"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}, diff --git a/libaurum/src/Impl/Accessibility/AtspiAccessibleWatcher.cc b/libaurum/src/Impl/Accessibility/AtspiAccessibleWatcher.cc index 27f332e..c3400c0 100644 --- a/libaurum/src/Impl/Accessibility/AtspiAccessibleWatcher.cc +++ b/libaurum/src/Impl/Accessibility/AtspiAccessibleWatcher.cc @@ -39,6 +39,11 @@ std::vector> AtspiAccessibleWatcher::mEventQueue; GThread *AtspiAccessibleWatcher::mEventThread = nullptr; std::mutex AtspiAccessibleWatcher::mMutex = std::mutex{}; GMainLoop *AtspiAccessibleWatcher::mLoop = nullptr; +GThread *AtspiAccessibleWatcher::mTimerThread = nullptr; +gint64 AtspiAccessibleWatcher::mStartTime = 0; +IdleEventState AtspiAccessibleWatcher::isIdle = IdleEventState::IDLE_LISTEN_READY; +static const unsigned int WAIT_FOR_IDLE_MICRO_SEC = 100000; // 0.1 sec +int AtspiAccessibleWatcher::mRenderCount = 10; static bool iShowingNode(AtspiAccessible *node) { @@ -222,6 +227,28 @@ void AtspiAccessibleWatcher::removeApp(AtspiAccessibleWatcher *instance, AtspiAc g_object_unref(app); } +gpointer AtspiAccessibleWatcher::timerThread(gpointer data) +{ + mStartTime = g_get_monotonic_time(); + for (;;) + { + //FIXME: User can change waiting time and count of render post + // instead of waiting spelcific time + if ((g_get_monotonic_time() - mStartTime) > WAIT_FOR_IDLE_MICRO_SEC) + { + break; + } + + usleep(100); + } + + mTimerThread = nullptr; + isIdle = IdleEventState::IDLE_LISTEN_DONE; + g_thread_exit(NULL); + + return NULL; +} + void AtspiAccessibleWatcher::onAtspiEvents(AtspiEvent *event, void *watcher) { if (!event->source) @@ -232,6 +259,30 @@ void AtspiAccessibleWatcher::onAtspiEvents(AtspiEvent *event, void *watcher) AtspiAccessibleWatcher *instance = (AtspiAccessibleWatcher *)watcher; name = AtspiWrapper::Atspi_accessible_get_name(event->source, NULL); + LOGE("WCC event = %s", event->type); + if (isIdle == IdleEventState::IDLE_LISTEN_START && !strncmp(event->type, "window:post-render", 18)) + { + if (mTimerThread == nullptr) + { + LOGI("Timer Thread Start"); + mTimerThread = g_thread_new("TimerThread", timerThread, instance); + } + else + { + mStartTime = g_get_monotonic_time(); + } + + mRenderCount--; + if (mRenderCount == 0) + { + LOGI("RenderCount is 0. Stop to listen RenderPost"); + mStartTime = g_get_monotonic_time() + WAIT_FOR_IDLE_MICRO_SEC; + } + + if (name) free(name); + return; + } + AtspiAccessible *app = AtspiWrapper::Atspi_accessible_get_application(event->source, NULL); if (name && app) { @@ -321,11 +372,24 @@ std::vector> AtspiAccessibleWatcher::getA return ret; } -bool AtspiAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName) +bool AtspiAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName, std::shared_ptr obj, const int count) { mMutex.lock(); mEventQueue.clear(); mMutex.unlock(); + + // Call atspi method for start to listen atspi event. + if (type == A11yEvent::EVENT_WINDOW_RENDER_POST) + { + LOGI("RenderPost listen start with pkg (%s) timeout (%d) count (%d)", obj->getPkg().c_str(), timeout, count); + isIdle = IdleEventState::IDLE_LISTEN_START; + if (count == 0 || count < 0) + mRenderCount = 10; + else + mRenderCount = count; + AtspiWrapper::Atspi_accessible_set_listen_post_render((AtspiAccessible *)(obj->getRawHandler()), true, NULL); + } + if (cmd) cmd->run(); @@ -339,6 +403,9 @@ bool AtspiAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const mEventQueue.clear(); mMutex.unlock(); + if (isIdle == IdleEventState::IDLE_LISTEN_DONE) + break; + if (!localEvents.empty()) { for (const auto &event : localEvents) { @@ -356,6 +423,15 @@ bool AtspiAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const std::chrono::milliseconds{100}); } + if (isIdle != IdleEventState::IDLE_LISTEN_READY) + { + LOGI("RenderPost listen finish"); + isIdle = IdleEventState::IDLE_LISTEN_READY; + AtspiWrapper::Atspi_accessible_set_listen_post_render((AtspiAccessible *)(obj->getRawHandler()), false, NULL); + + return true; + } + return false; } diff --git a/libaurum/src/Impl/Accessibility/AtspiWrapper.cc b/libaurum/src/Impl/Accessibility/AtspiWrapper.cc index b923969..02fa126 100644 --- a/libaurum/src/Impl/Accessibility/AtspiWrapper.cc +++ b/libaurum/src/Impl/Accessibility/AtspiWrapper.cc @@ -225,3 +225,8 @@ AtspiRect *AtspiWrapper::Atspi_text_get_minimum_bounding_rectangles(AtspiText* o return atspi_text_get_range_extents(obj, start_offset, end_offset, type, error); } +void AtspiWrapper::Atspi_accessible_set_listen_post_render(AtspiAccessible *obj, gboolean enabled, GError **error) +{ + std::unique_lock lock(mMutex); + atspi_accessible_set_listen_post_render(obj, enabled, error); +} \ No newline at end of file diff --git a/libaurum/src/Impl/Accessibility/MockAccessibleWatcher.cc b/libaurum/src/Impl/Accessibility/MockAccessibleWatcher.cc index ac44651..e054ced 100644 --- a/libaurum/src/Impl/Accessibility/MockAccessibleWatcher.cc +++ b/libaurum/src/Impl/Accessibility/MockAccessibleWatcher.cc @@ -68,7 +68,7 @@ std::shared_ptr MockAccessibleWatcher::addApplication return app; } -bool MockAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName) +bool MockAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName, std::shared_ptr obj, const int count) { return true; } @@ -76,4 +76,4 @@ bool MockAccessibleWatcher::executeAndWaitForEvents(const Runnable *cmd, const A bool MockAccessibleWatcher::registerCallback(const A11yEvent type, EventHandler cb, void *data) { return true; -} \ No newline at end of file +} diff --git a/libaurum/src/UiDevice.cc b/libaurum/src/UiDevice.cc index 0d710c8..328c5bb 100644 --- a/libaurum/src/UiDevice.cc +++ b/libaurum/src/UiDevice.cc @@ -285,20 +285,24 @@ bool UiDevice::waitForIdle() const bool UiDevice::waitForEvents( const A11yEvent type, const int timeout) const { - return executeAndWaitForEvents(NULL, type, timeout, std::string()); + return executeAndWaitForEvents(NULL, type, timeout, std::string(), 0); } -bool UiDevice::executeAndWaitForEvents( - const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName) const +//FIXME: obj only need for idle event +bool UiDevice::executeAndWaitForEvents + (const Runnable *cmd, const A11yEvent type, const int timeout, const std::string packageName, const int count) const { - return AccessibleWatcher::getInstance()->executeAndWaitForEvents(cmd, type, timeout, packageName); + //FIXME: Need to get top window + auto wins = this->getWindowRoot(); + + return AccessibleWatcher::getInstance()->executeAndWaitForEvents(cmd, type, timeout, packageName, wins[0], count); } bool UiDevice::sendKeyAndWaitForEvents( const std::string keycode, const A11yEvent type, const int timeout) const { std::unique_ptr cmd = std::make_unique(keycode); - return executeAndWaitForEvents(cmd.get(), type, timeout, std::string()); + return executeAndWaitForEvents(cmd.get(), type, timeout, std::string(), 0); } bool UiDevice::click(const int x, const int y) diff --git a/org.tizen.aurum-bootstrap/src/Commands/ActionAndWaitEventCommand.cc b/org.tizen.aurum-bootstrap/src/Commands/ActionAndWaitEventCommand.cc index 4449c2f..3439879 100644 --- a/org.tizen.aurum-bootstrap/src/Commands/ActionAndWaitEventCommand.cc +++ b/org.tizen.aurum-bootstrap/src/Commands/ActionAndWaitEventCommand.cc @@ -34,6 +34,8 @@ A11yEvent convertEventType(const ::aurum::ReqActionAndWaitEvent_EventType type) return A11yEvent::EVENT_WINDOW_ACTIVATE; else if (type == ::aurum::ReqActionAndWaitEvent_EventType::ReqActionAndWaitEvent_EventType_EVENT_WINDOW_DEACTIVATE) return A11yEvent::EVENT_WINDOW_DEACTIVATE; + else if (type == ::aurum::ReqActionAndWaitEvent_EventType::ReqActionAndWaitEvent_EventType_EVENT_WINDOW_IDLE) + return A11yEvent::EVENT_WINDOW_RENDER_POST; else return A11yEvent::EVENT_STATE_CHANGED_FOCUSED; } @@ -44,7 +46,8 @@ A11yEvent convertEventType(const ::aurum::ReqActionAndWaitEvent_EventType type) std::unique_ptr cmd = std::make_unique( mRequest->type(), mRequest->elementid(), mRequest->xf86keycode()); std::shared_ptr obj = UiDevice::getInstance(); - bool ret = obj->executeAndWaitForEvents(cmd.get(), convertEventType(mRequest->eventtype()), mRequest->timeoutms(), mRequest->packagename()); + //FIXME: Separation of params according to event type + bool ret = obj->executeAndWaitForEvents(cmd.get(), convertEventType(mRequest->eventtype()), mRequest->timeoutms(), mRequest->packagename(), mRequest->count()); if (ret) mResponse->set_status(::aurum::RspStatus::OK); else mResponse->set_status(::aurum::RspStatus::ERROR); diff --git a/org.tizen.aurum-bootstrap/src/Commands/LaunchAppCommand.cc b/org.tizen.aurum-bootstrap/src/Commands/LaunchAppCommand.cc index 401ac0a..64dd8cc 100644 --- a/org.tizen.aurum-bootstrap/src/Commands/LaunchAppCommand.cc +++ b/org.tizen.aurum-bootstrap/src/Commands/LaunchAppCommand.cc @@ -35,7 +35,7 @@ LaunchAppCommand::LaunchAppCommand(const ::aurum::ReqLaunchApp *request, LOGI("LaunchApp --------------- "); std::unique_ptr cmd = std::make_unique(mRequest->packagename(), mRequest->data()); std::shared_ptr obj = UiDevice::getInstance(); - obj->executeAndWaitForEvents(cmd.get(), A11yEvent::EVENT_WINDOW_ACTIVATE, WAIT_APP_LAUNCH, mRequest->packagename()); + obj->executeAndWaitForEvents(cmd.get(), A11yEvent::EVENT_WINDOW_ACTIVATE, WAIT_APP_LAUNCH, mRequest->packagename(), 0); return grpc::Status::OK; } \ No newline at end of file diff --git a/protocol/aurum.proto b/protocol/aurum.proto index 9e4a42a..2f087d5 100644 --- a/protocol/aurum.proto +++ b/protocol/aurum.proto @@ -590,6 +590,7 @@ message ReqActionAndWaitEvent { EVENT_WINDOW_ACTIVATE = 0; EVENT_WINDOW_DEACTIVATE = 1; EVENT_STATE_CHANGED_FOCUSED = 2; + EVENT_WINDOW_IDLE = 3; } ActionType type = 1; oneof params { @@ -599,6 +600,7 @@ message ReqActionAndWaitEvent { EventType eventType = 4; int32 timeoutMs = 5; string packageName = 6; + int32 count = 7; } message RspActionAndWaitEvent {