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
#include "IEventConsumer.h"
#include "IObject.h"
#include "Rect.h"
+#include "UiSelector.h"
#include "config.h"
namespace Aurum {
virtual std::shared_ptr<AccessibleNode> getParent() const = 0;
/**
+ * @copydoc UiObject::getMatches()
+ */
+ virtual std::vector<std::shared_ptr<AccessibleNode>> getMatches(const std::shared_ptr<UiSelector> selector, const bool ealryReturn) const = 0;
+
+ /**
* @brief Called by @AccessibleWatcher::notifyAll.
* Changes Node property If it's @EventType, @ObjectEventType are matches.
*
std::shared_ptr<AccessibleNode> getParent() const override;
/**
+ * @copydoc UiObject::getMatches()
+ */
+ std::vector<std::shared_ptr<AccessibleNode>> getMatches(const std::shared_ptr<UiSelector> selector, const bool ealryReturn) const override;
+
+ /**
* @copydoc AccessibleNode::isValid()
*/
bool isValid() const override;
--- /dev/null
+/*
+ * 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 <memory>
+
+#include <atspi/atspi.h>
+
+#include "UiSelector.h"
+
+using namespace Aurum;
+
+namespace AurumInternal {
+
+class AtspiMatchRuleConvertor {
+public:
+ AtspiMatchRuleConvertor(const std::shared_ptr<UiSelector> selector);
+ ~AtspiMatchRuleConvertor();
+
+ operator AtspiMatchRule*();
+
+private:
+ std::shared_ptr<UiSelector> mSelector;
+};
+
+}
+
+#endif
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;
*/
std::shared_ptr<AccessibleNode> getParent() const override;
+ /**
+ * @brief TBD
+ * @since_tizen 8.0
+ */
+ std::vector<std::shared_ptr<AccessibleNode>> getMatches(const std::shared_ptr<UiSelector> selector, const bool ealryReturn) const override;
+
public:
/**
* @brief TBD
const std::shared_ptr<UiSelector> 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<std::shared_ptr<UiObject>> getMatches(
+ const std::shared_ptr<UiSelector> selector, const bool earlyReturn) const;
+
+ /**
* TODO
*/
bool waitFor(
const std::shared_ptr<UiSelector> 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<std::shared_ptr<UiObject>> getMatches(
+ const std::shared_ptr<UiSelector> selector, const bool earlyReturn) const;
+
+ /**
* TODO
*/
bool waitFor(
#include <vector>
#include <memory>
+#include "Rect.h"
+
namespace Aurum {
/**
#include "Aurum.h"
#include "AtspiAccessibleNode.h"
+#include "AtspiMatchRuleConvertor.h"
#include "AtspiWrapper.h"
#include <gio/gio.h>
break;
}
}
+
+std::vector<std::shared_ptr<AccessibleNode>> AtspiAccessibleNode::getMatches(const std::shared_ptr<UiSelector> selector, const bool ealryReturn) const
+{
+ std::vector<std::shared_ptr<AccessibleNode>> 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<AtspiAccessibleNode>(match));
+ }
+ }
+ g_array_free(matches, true);
+ }
+ g_object_unref(rule);
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * 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 <atspi/atspi.h>
+
+#include "Aurum.h"
+#include "AtspiMatchRuleConvertor.h"
+
+using namespace Aurum;
+using namespace AurumInternal;
+
+AtspiMatchRuleConvertor::AtspiMatchRuleConvertor(const std::shared_ptr<UiSelector> 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;
+}
{
std::unique_lock<std::recursive_mutex> lock(mMutex);
atspi_accessible_set_listen_post_render(obj, enabled, error);
+}
+
+AtspiCollection *AtspiWrapper::Atspi_accessible_get_collection_iface(AtspiAccessible *node)
+{
+ std::unique_lock<std::recursive_mutex> 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<std::recursive_mutex> lock(mMutex);
+ return atspi_collection_get_matches(obj, rule, sortby, count, traverse, error);
}
\ No newline at end of file
return mParentNode;
}
+std::vector<std::shared_ptr<AccessibleNode>> MockAccessibleNode::getMatches(const std::shared_ptr<UiSelector> selector, const bool ealryReturn) const
+{
+ std::vector<std::shared_ptr<AccessibleNode>> ret{};
+
+ return ret;
+}
+
void* MockAccessibleNode::getRawHandler(void) const
{
printf("%s:%d / %s\n",__FILE__, __LINE__, __PRETTY_FUNCTION__);
files('AtspiAccessibleNode.cc'),
files('AtspiAccessibleWatcher.cc'),
files('AtspiWrapper.cc'),
+ files('AtspiMatchRuleConvertor.cc'),
]
libaurum_src += [
files('MockAccessibleWindow.cc'),
files('MockAccessibleNode.cc'),
files('MockAccessibleWatcher.cc'),
- ]
\ No newline at end of file
+ ]
}
return ret;
}
+
+std::vector<std::shared_ptr<UiObject>> UiDevice::getMatches(
+ const std::shared_ptr<UiSelector> selector, const bool earlyReturn) const
+{
+ std::vector<std::shared_ptr<UiObject>> 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<UiObject>(getInstance(), nullptr, node));
+ }
+ return ret;
+}
+
bool UiDevice::waitFor(
const std::function<bool(const ISearchable *)> condition) const
{
return result;
}
+std::vector<std::shared_ptr<UiObject>> UiObject::getMatches(
+ const std::shared_ptr<UiSelector> selector, const bool earlyReturn) const
+{
+ std::vector<std::shared_ptr<UiObject>> result{};
+
+ auto nodes = getAccessibleNode()->getMatches(selector, earlyReturn);
+ for (auto &node : nodes) {
+ result.push_back(std::make_shared<UiObject>(mDevice, selector, std::move(node)));
+ }
+ return result;
+}
+
bool UiObject::waitFor(
const std::function<bool(const ISearchable *)> condition) const
{