2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/accessibility/bridge/bridge-collection.h>
23 #include <unordered_set>
26 using namespace Dali::Accessibility;
31 * @brief Enumeration used for quering Accessibility objects.
33 * Refer to MatchType enumeration.
35 enum class AtspiCollection
44 } // anonymous namespace
46 void BridgeCollection::RegisterInterfaces()
48 DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::COLLECTION)};
49 AddFunctionToInterface(desc, "GetMatches", &BridgeCollection::GetMatches);
50 AddFunctionToInterface(desc, "GetMatchesInMatches", &BridgeCollection::GetMatchesInMatches);
52 mDbusServer.addInterface("/", desc, true);
55 Collection* BridgeCollection::FindSelf() const
57 return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::COLLECTION>();
61 * @brief The BridgeCollection::Comparer structure.
63 * Once the data is de-serialized by DBusWrapper, the data of match rule is passed
64 * to Comparer type which do the comparison against a single accessible object.
66 struct BridgeCollection::Comparer
68 using Mode = MatchType;
71 * @brief Enumeration to check the object is found first.
73 enum class CompareFuncExit
79 static Mode ConvertToMatchType(int32_t mode)
83 case static_cast<int32_t>(AtspiCollection::MATCH_INVALID):
87 case static_cast<int32_t>(AtspiCollection::MATCH_ALL):
91 case static_cast<int32_t>(AtspiCollection::MATCH_ANY):
95 case static_cast<int32_t>(AtspiCollection::MATCH_NONE):
99 case static_cast<int32_t>(AtspiCollection::MATCH_EMPTY):
104 return Mode::INVALID;
108 * @brief The ComparerInterfaces structure
110 struct ComparerInterfaces
112 std::unordered_set<std::string> mObject;
113 std::vector<std::string> mRequested;
114 Mode mMode = Mode::INVALID;
116 ComparerInterfaces(MatchRule* rule)
117 : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::INTERFACES_MATCH_TYPE)>(*rule)))
119 mRequested = {std::get<static_cast<std::size_t>(Index::INTERFACES)>(*rule).begin(), std::get<static_cast<std::size_t>(Index::INTERFACES)>(*rule).end()};
122 void Update(Accessible* obj)
125 for(auto& interface : obj->GetInterfacesAsStrings())
127 mObject.insert(std::move(interface));
131 bool IsRequestEmpty() const
133 return mRequested.empty();
136 bool IsObjectEmpty() const
138 return mObject.empty();
141 bool Compare(CompareFuncExit exit)
143 bool foundAny = false;
144 for(auto& iname : mRequested)
146 bool found = (mObject.find(iname) != mObject.end());
152 if(found == (exit == CompareFuncExit::FIRST_FOUND))
159 }; // ComparerInterfaces struct
162 * @brief The ComparerAttributes structure
164 struct ComparerAttributes
166 std::unordered_map<std::string, std::string> mRequested;
167 std::unordered_map<std::string, std::string> mObject;
168 Mode mMode = Mode::INVALID;
170 ComparerAttributes(MatchRule* rule)
171 : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::ATTRIBUTES_MATCH_TYPE)>(*rule)))
173 mRequested = std::get<static_cast<std::size_t>(Index::ATTRIBUTES)>(*rule);
176 void Update(Accessible* obj)
178 mObject = obj->GetAttributes();
181 bool IsRequestEmpty() const
183 return mRequested.empty();
186 bool IsObjectEmpty() const
188 return mObject.empty();
191 bool Compare(CompareFuncExit exit)
193 bool foundAny = false;
194 for(auto& iname : mRequested)
196 auto it = mObject.find(iname.first);
197 bool found = it != mObject.end() && iname.second == it->second;
203 if(found == (exit == CompareFuncExit::FIRST_FOUND))
210 }; // ComparerAttributes struct
213 * @brief The ComparerRoles structure
217 using Roles = EnumBitSet<Role, Role::MAX_COUNT>;
221 Mode mMode = Mode::INVALID;
223 ComparerRoles(MatchRule* rule)
224 : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::ROLES_MATCH_TYPE)>(*rule)))
226 mRequested = Roles{std::get<static_cast<std::size_t>(Index::ROLES)>(*rule)};
229 void Update(Accessible* obj)
232 mObject[obj->GetRole()] = true;
236 bool IsRequestEmpty() const
241 bool IsObjectEmpty() const
246 bool Compare(CompareFuncExit exit)
257 return mRequested == (mObject & mRequested);
261 return bool(mObject & mRequested);
265 return bool(mObject & mRequested);
270 }; // ComparerRoles struct
273 * @brief The ComparerStates structure
275 struct ComparerStates
279 Mode mMode = Mode::INVALID;
281 ComparerStates(MatchRule* rule)
282 : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::STATES_MATCH_TYPE)>(*rule)))
284 mRequested = States{std::get<static_cast<std::size_t>(Index::STATES)>(*rule)};
287 void Update(Accessible* obj)
289 mObject = obj->GetStates();
292 bool IsRequestEmpty() const
297 bool IsObjectEmpty() const
302 bool Compare(CompareFuncExit exit)
313 return mRequested == (mObject & mRequested);
317 return bool(mObject & mRequested);
321 return bool(mObject & mRequested);
326 }; // ComparerStates struct
329 bool CompareFunc(T& cmp, Accessible* obj)
331 if(cmp.mMode == Mode::INVALID)
341 if(cmp.IsRequestEmpty() || cmp.IsObjectEmpty())
349 if(cmp.IsRequestEmpty())
353 if(cmp.IsObjectEmpty())
361 if(cmp.IsRequestEmpty() || cmp.IsObjectEmpty())
369 if(cmp.IsRequestEmpty() && cmp.IsObjectEmpty())
373 if(cmp.IsRequestEmpty() || cmp.IsObjectEmpty())
390 if(!cmp.Compare(CompareFuncExit::FIRST_NOT_FOUND))
398 if(cmp.Compare(CompareFuncExit::FIRST_FOUND))
406 if(cmp.Compare(CompareFuncExit::FIRST_FOUND))
438 Comparer(MatchRule* rule)
446 bool operator()(Accessible* obj)
448 return CompareFunc(mInterface, obj) &&
449 CompareFunc(mAttribute, obj) &&
450 CompareFunc(mRole, obj) &&
451 CompareFunc(mState, obj);
454 bool IsShowing(Accessible* obj)
456 if (mState.mMode == Mode::NONE) return true;
458 if (mState.IsRequestEmpty() || mState.IsObjectEmpty()) return true;
459 if (!mState.mRequested[State::SHOWING] ) return true;
460 if (mState.mObject[State::SHOWING]) return true;
465 ComparerInterfaces mInterface;
466 ComparerAttributes mAttribute;
468 ComparerStates mState;
469 }; // BridgeCollection::Comparer struct
472 void BridgeCollection::VisitNodes(Accessible* obj, std::vector<Accessible*>& result, Comparer& comparer, size_t maxCount)
474 if(maxCount > 0 && result.size() >= maxCount)
481 result.emplace_back(obj);
482 // the code below will never return for maxCount equal 0
483 if(result.size() == maxCount)
489 if (!comparer.IsShowing(obj))
494 for(auto i = 0u; i < obj->GetChildCount(); ++i)
496 VisitNodes(obj->GetChildAtIndex(i), result, comparer, maxCount);
500 DBus::ValueOrError<std::vector<Accessible*> > BridgeCollection::GetMatches(MatchRule rule, uint32_t sortBy, int32_t count, bool traverse)
502 std::vector<Accessible*> res;
503 auto self = BridgeBase::FindCurrentObject();
504 auto matcher = Comparer{&rule};
505 VisitNodes(self, res, matcher, count);
507 switch(static_cast<SortOrder>(sortBy))
509 case SortOrder::CANONICAL:
514 case SortOrder::REVERSE_CANONICAL:
516 std::reverse(res.begin(), res.end());
522 throw std::domain_error{"unsupported sorting order"};
530 DBus::ValueOrError<std::vector<Accessible*> > BridgeCollection::GetMatchesInMatches(MatchRule firstRule, MatchRule secondRule, uint32_t sortBy, int32_t firstCount, int32_t secondCount, bool traverse)
532 std::vector<Accessible*> res;
533 std::vector<Accessible*> firstRes;
534 std::vector<Accessible*> secondRes;
535 auto self = BridgeBase::FindCurrentObject();
536 auto firstMatcher = Comparer{&firstRule};
537 auto secondMatcher = Comparer{&secondRule};
538 VisitNodes(self, firstRes, firstMatcher, firstCount);
540 for (auto &obj : firstRes)
542 VisitNodes(obj, secondRes, secondMatcher, secondCount);
544 res.insert(res.end(), secondRes.begin(), secondRes.end());
548 switch(static_cast<SortOrder>(sortBy))
550 case SortOrder::CANONICAL:
555 case SortOrder::REVERSE_CANONICAL:
557 std::reverse(res.begin(), res.end());
563 throw std::domain_error{"unsupported sorting order"};