From: Hosang Kim Date: Tue, 5 Dec 2023 06:17:04 +0000 (+0900) Subject: Introduce new getMatches API. X-Git-Tag: accepted/tizen/unified/20240205.162750~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a32a33877abf145c82d2a58842cacbc5b905f97a;p=platform%2Fcore%2Fuifw%2Faurum.git Introduce new getMatches API. the getMatches can find objects under specific conditions. It runs quickly because the search happens in the app. Internally, this API uses atspi_collection_get_matches and includes a new class, AtspiMatchRuleConvertor, to convert UiSelector to AtspiMatchRule. Change-Id: I2856a81aa5e70d8290e33faa0df231c95749eb35 --- diff --git a/libaurum/inc/Accessibility/AccessibleNode.h b/libaurum/inc/Accessibility/AccessibleNode.h index 8c3e555..b65f316 100644 --- a/libaurum/inc/Accessibility/AccessibleNode.h +++ b/libaurum/inc/Accessibility/AccessibleNode.h @@ -27,6 +27,7 @@ #include "IEventConsumer.h" #include "IObject.h" #include "Rect.h" +#include "UiSelector.h" #include "config.h" namespace Aurum { @@ -132,6 +133,11 @@ public: virtual std::shared_ptr getParent() const = 0; /** + * @copydoc UiObject::getMatches() + */ + virtual std::vector> getMatches(const std::shared_ptr selector, const bool ealryReturn) const = 0; + + /** * @brief Called by @AccessibleWatcher::notifyAll. * Changes Node property If it's @EventType, @ObjectEventType are matches. * diff --git a/libaurum/inc/Impl/Accessibility/AtspiAccessibleNode.h b/libaurum/inc/Impl/Accessibility/AtspiAccessibleNode.h index b4572b8..54d091a 100644 --- a/libaurum/inc/Impl/Accessibility/AtspiAccessibleNode.h +++ b/libaurum/inc/Impl/Accessibility/AtspiAccessibleNode.h @@ -71,6 +71,11 @@ public: std::shared_ptr getParent() const override; /** + * @copydoc UiObject::getMatches() + */ + std::vector> getMatches(const std::shared_ptr selector, const bool ealryReturn) const override; + + /** * @copydoc AccessibleNode::isValid() */ bool isValid() const override; diff --git a/libaurum/inc/Impl/Accessibility/AtspiMatchRuleConvertor.h b/libaurum/inc/Impl/Accessibility/AtspiMatchRuleConvertor.h new file mode 100644 index 0000000..1b3a57b --- /dev/null +++ b/libaurum/inc/Impl/Accessibility/AtspiMatchRuleConvertor.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _ATSPI_MATCH_RULE_CONVERTOR_H_ +#define _ATSPI_MATCH_RULE_CONVERTOR_H_ + +#include + +#include + +#include "UiSelector.h" + +using namespace Aurum; + +namespace AurumInternal { + +class AtspiMatchRuleConvertor { +public: + AtspiMatchRuleConvertor(const std::shared_ptr selector); + ~AtspiMatchRuleConvertor(); + + operator AtspiMatchRule*(); + +private: + std::shared_ptr mSelector; +}; + +} + +#endif diff --git a/libaurum/inc/Impl/Accessibility/AtspiWrapper.h b/libaurum/inc/Impl/Accessibility/AtspiWrapper.h index 6f3ebeb..fbca138 100644 --- a/libaurum/inc/Impl/Accessibility/AtspiWrapper.h +++ b/libaurum/inc/Impl/Accessibility/AtspiWrapper.h @@ -71,6 +71,8 @@ public: 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); + static AtspiCollection *Atspi_accessible_get_collection_iface(AtspiAccessible *node); + static GArray *Atspi_collection_get_matches(AtspiCollection *obj, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, gint count, gboolean traverse, GError **error); private: static std::recursive_mutex mMutex; diff --git a/libaurum/inc/Impl/Accessibility/MockAccessibleNode.h b/libaurum/inc/Impl/Accessibility/MockAccessibleNode.h index abb23c4..77f9ce3 100644 --- a/libaurum/inc/Impl/Accessibility/MockAccessibleNode.h +++ b/libaurum/inc/Impl/Accessibility/MockAccessibleNode.h @@ -68,6 +68,12 @@ public: */ std::shared_ptr getParent() const override; + /** + * @brief TBD + * @since_tizen 8.0 + */ + std::vector> getMatches(const std::shared_ptr selector, const bool ealryReturn) const override; + public: /** * @brief TBD diff --git a/libaurum/inc/UiDevice.h b/libaurum/inc/UiDevice.h index e9d519c..7315f7b 100644 --- a/libaurum/inc/UiDevice.h +++ b/libaurum/inc/UiDevice.h @@ -314,6 +314,20 @@ public: const std::shared_ptr selector) const override; /** + * @brief Get the Matches object that satisfied with the selector condition in the object tree. + * This method is similar to findObjects, but getMatches is more faster than findObjects. + * + * @param[in] selector @UiSelector + * @param[in] earlyReturn boolean + * + * @return the list of found UiObject pointer vector + * + * @since_tizen 8.0 + */ + std::vector> getMatches( + const std::shared_ptr selector, const bool earlyReturn) const; + + /** * TODO */ bool waitFor( diff --git a/libaurum/inc/UiObject.h b/libaurum/inc/UiObject.h index 52d4a9c..3f7911b 100644 --- a/libaurum/inc/UiObject.h +++ b/libaurum/inc/UiObject.h @@ -139,6 +139,20 @@ public: const std::shared_ptr selector) const override; /** + * @brief Get the Matches object that satisfied with the selector condition in the object tree. + * This method is similar to findObjects, but getMatches is more faster than findObjects. + * + * @param[in] selector @UiSelector + * @param[in] earlyReturn boolean + * + * @return the list of found UiObject pointer vector + * + * @since_tizen 8.0 + */ + std::vector> getMatches( + const std::shared_ptr selector, const bool earlyReturn) const; + + /** * TODO */ bool waitFor( diff --git a/libaurum/inc/UiSelector.h b/libaurum/inc/UiSelector.h index 2eca30d..4d2a129 100644 --- a/libaurum/inc/UiSelector.h +++ b/libaurum/inc/UiSelector.h @@ -24,6 +24,8 @@ #include #include +#include "Rect.h" + namespace Aurum { /** diff --git a/libaurum/src/Impl/Accessibility/AtspiAccessibleNode.cc b/libaurum/src/Impl/Accessibility/AtspiAccessibleNode.cc index 1301c8b..e4572d4 100644 --- a/libaurum/src/Impl/Accessibility/AtspiAccessibleNode.cc +++ b/libaurum/src/Impl/Accessibility/AtspiAccessibleNode.cc @@ -18,6 +18,7 @@ #include "Aurum.h" #include "AtspiAccessibleNode.h" +#include "AtspiMatchRuleConvertor.h" #include "AtspiWrapper.h" #include @@ -612,3 +613,31 @@ void AtspiAccessibleNode::setFeatureProperty(AtspiStateType type) break; } } + +std::vector> AtspiAccessibleNode::getMatches(const std::shared_ptr selector, const bool ealryReturn) const +{ + std::vector> ret{}; + + AtspiCollection *collection = AtspiWrapper::Atspi_accessible_get_collection_iface(mNode); + if (collection) { + AtspiMatchRule *rule = AtspiMatchRuleConvertor(selector); + if (!rule) return ret; + + int count = ealryReturn ? 1 : 0; + GArray *matches = AtspiWrapper::Atspi_collection_get_matches(collection, rule, ATSPI_Collection_SORT_ORDER_CANONICAL, count, false, NULL); + if (matches) { + ret.reserve(matches->len); + AtspiAccessible *match = nullptr; + for (unsigned int i = 0; i < matches->len; i++) { + match = g_array_index(matches, AtspiAccessible *, i); + if (match) { + ret.push_back(std::make_shared(match)); + } + } + g_array_free(matches, true); + } + g_object_unref(rule); + } + + return ret; +} diff --git a/libaurum/src/Impl/Accessibility/AtspiMatchRuleConvertor.cc b/libaurum/src/Impl/Accessibility/AtspiMatchRuleConvertor.cc new file mode 100644 index 0000000..d5c9294 --- /dev/null +++ b/libaurum/src/Impl/Accessibility/AtspiMatchRuleConvertor.cc @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include + +#include "Aurum.h" +#include "AtspiMatchRuleConvertor.h" + +using namespace Aurum; +using namespace AurumInternal; + +AtspiMatchRuleConvertor::AtspiMatchRuleConvertor(const std::shared_ptr selector) +: mSelector(selector) +{ +} + +AtspiMatchRuleConvertor::~AtspiMatchRuleConvertor() +{ +} + +AtspiMatchRuleConvertor::operator AtspiMatchRule *() +{ + if (!mSelector) return nullptr; + + AtspiCollectionMatchType stateMatchType = ATSPI_Collection_MATCH_INVALID; + AtspiCollectionMatchType attributeMatchType = ATSPI_Collection_MATCH_INVALID; + + // Add rule of states + AtspiStateSet *ss = atspi_state_set_new(nullptr); + if (mSelector->mIschecked) atspi_state_set_add(ss, ATSPI_STATE_CHECKED); + if (mSelector->mIscheckable) atspi_state_set_add(ss, ATSPI_STATE_CHECKABLE); + if (mSelector->mIsclickable) atspi_state_set_add(ss, ATSPI_STATE_SENSITIVE); + if (mSelector->mIsenabled) atspi_state_set_add(ss, ATSPI_STATE_ENABLED); + if (mSelector->mIsfocused) atspi_state_set_add(ss, ATSPI_STATE_FOCUSED); + if (mSelector->mIsfocusable) atspi_state_set_add(ss, ATSPI_STATE_FOCUSABLE); + if (mSelector->mIsselected) atspi_state_set_add(ss, ATSPI_STATE_SELECTED); + if (mSelector->mIsshowing) atspi_state_set_add(ss, ATSPI_STATE_SHOWING); + if (mSelector->mIsactive) atspi_state_set_add(ss, ATSPI_STATE_ACTIVE); + if (mSelector->mIsvisible) atspi_state_set_add(ss, ATSPI_STATE_VISIBLE); + if (mSelector->mIsselectable) atspi_state_set_add(ss, ATSPI_STATE_SELECTABLE); + if (mSelector->mIshighlightable) atspi_state_set_add(ss, ATSPI_STATE_HIGHLIGHTABLE); + + if (atspi_state_set_is_empty(ss)) + { + g_object_unref(ss); + ss = nullptr; + } + else + { + stateMatchType = ATSPI_Collection_MATCH_ALL; + } + + // Add rule of attributes + GHashTable *attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + if (mSelector->mMatchType) + { + g_hash_table_insert(attributes, g_strdup("class"), g_strdup(mSelector->mType.c_str())); + } + + if (mSelector->mMatchAutomationId) + { + g_hash_table_insert(attributes, g_strdup("automationId"), g_strdup(mSelector->mAutomationId.c_str())); + } + + if (g_hash_table_size(attributes) == 0) + { + g_hash_table_unref (attributes); + attributes = nullptr; + } + else + { + attributeMatchType = ATSPI_Collection_MATCH_ALL; + } + + AtspiMatchRule* rule = atspi_match_rule_new(ss, stateMatchType, + attributes, attributeMatchType, + nullptr, ATSPI_Collection_MATCH_INVALID, + nullptr, ATSPI_Collection_MATCH_INVALID, + false); + + if (ss) g_object_unref(ss); + if (attributes) g_hash_table_unref (attributes); + + return rule; +} diff --git a/libaurum/src/Impl/Accessibility/AtspiWrapper.cc b/libaurum/src/Impl/Accessibility/AtspiWrapper.cc index e9b8228..4d78d75 100644 --- a/libaurum/src/Impl/Accessibility/AtspiWrapper.cc +++ b/libaurum/src/Impl/Accessibility/AtspiWrapper.cc @@ -235,4 +235,16 @@ void AtspiWrapper::Atspi_accessible_set_listen_post_render(AtspiAccessible *obj, { std::unique_lock lock(mMutex); atspi_accessible_set_listen_post_render(obj, enabled, error); +} + +AtspiCollection *AtspiWrapper::Atspi_accessible_get_collection_iface(AtspiAccessible *node) +{ + std::unique_lock lock(mMutex); + return atspi_accessible_get_collection_iface(node); +} + +GArray *AtspiWrapper::Atspi_collection_get_matches(AtspiCollection *obj, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, gint count, gboolean traverse, GError **error) +{ + std::unique_lock lock(mMutex); + return atspi_collection_get_matches(obj, rule, sortby, count, traverse, error); } \ No newline at end of file diff --git a/libaurum/src/Impl/Accessibility/MockAccessibleNode.cc b/libaurum/src/Impl/Accessibility/MockAccessibleNode.cc index a397f37..860a089 100644 --- a/libaurum/src/Impl/Accessibility/MockAccessibleNode.cc +++ b/libaurum/src/Impl/Accessibility/MockAccessibleNode.cc @@ -61,6 +61,13 @@ std::shared_ptr MockAccessibleNode::getParent() const return mParentNode; } +std::vector> MockAccessibleNode::getMatches(const std::shared_ptr selector, const bool ealryReturn) const +{ + std::vector> ret{}; + + return ret; +} + void* MockAccessibleNode::getRawHandler(void) const { printf("%s:%d / %s\n",__FILE__, __LINE__, __PRETTY_FUNCTION__); diff --git a/libaurum/src/Impl/Accessibility/meson.build b/libaurum/src/Impl/Accessibility/meson.build index fd535cc..f7b23b4 100644 --- a/libaurum/src/Impl/Accessibility/meson.build +++ b/libaurum/src/Impl/Accessibility/meson.build @@ -4,6 +4,7 @@ files('AtspiAccessibleNode.cc'), files('AtspiAccessibleWatcher.cc'), files('AtspiWrapper.cc'), + files('AtspiMatchRuleConvertor.cc'), ] libaurum_src += [ @@ -11,4 +12,4 @@ files('MockAccessibleWindow.cc'), files('MockAccessibleNode.cc'), files('MockAccessibleWatcher.cc'), - ] \ No newline at end of file + ] diff --git a/libaurum/src/UiDevice.cc b/libaurum/src/UiDevice.cc index 60f9ab2..9bb7e42 100644 --- a/libaurum/src/UiDevice.cc +++ b/libaurum/src/UiDevice.cc @@ -113,6 +113,21 @@ std::vector> UiDevice::findObjects( } return ret; } + +std::vector> UiDevice::getMatches( + const std::shared_ptr selector, const bool earlyReturn) const +{ + std::vector> ret{}; + + auto rootNodes = getWindowRoot(); + for (const auto &window : rootNodes) { + auto nodes = window->getMatches(selector, earlyReturn); + for (auto &node : nodes) + ret.push_back(std::make_shared(getInstance(), nullptr, node)); + } + return ret; +} + bool UiDevice::waitFor( const std::function condition) const { diff --git a/libaurum/src/UiObject.cc b/libaurum/src/UiObject.cc index 411cd4d..ca0946b 100644 --- a/libaurum/src/UiObject.cc +++ b/libaurum/src/UiObject.cc @@ -105,6 +105,18 @@ std::vector> UiObject::findObjects( return result; } +std::vector> UiObject::getMatches( + const std::shared_ptr selector, const bool earlyReturn) const +{ + std::vector> result{}; + + auto nodes = getAccessibleNode()->getMatches(selector, earlyReturn); + for (auto &node : nodes) { + result.push_back(std::make_shared(mDevice, selector, std::move(node))); + } + return result; +} + bool UiObject::waitFor( const std::function condition) const {