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>
24 #include <unordered_set>
27 using namespace Dali::Accessibility;
29 void BridgeCollection::RegisterInterfaces()
31 DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCollection};
32 AddFunctionToInterface(desc, "GetMatches", &BridgeCollection::GetMatches);
33 mDbusServer.addInterface("/", desc, true);
36 Collection* BridgeCollection::FindSelf() const
38 auto self = BridgeBase::FindSelf();
40 auto collectionInterface = dynamic_cast<Collection*>(self);
41 if(!collectionInterface)
43 throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Collection interface"};
45 return collectionInterface;
50 ATSPI_Collection_MATCH_INVALID,
51 ATSPI_Collection_MATCH_ALL,
52 ATSPI_Collection_MATCH_ANY,
53 ATSPI_Collection_MATCH_NONE,
54 ATSPI_Collection_MATCH_EMPTY,
55 ATSPI_Collection_MATCH_LAST_DEFINED,
58 struct BridgeCollection::Comparer
60 using Mode = MatchType;
62 enum class CompareFuncExit
68 static Mode ConvertToMatchType(int32_t mode)
72 case ATSPI_Collection_MATCH_INVALID:
76 case ATSPI_Collection_MATCH_ALL:
80 case ATSPI_Collection_MATCH_ANY:
84 case ATSPI_Collection_MATCH_NONE:
88 case ATSPI_Collection_MATCH_EMPTY:
96 struct ComparerInterfaces
98 std::unordered_set<std::string> object;
99 std::vector<std::string> requested;
100 Mode mode = Mode::INVALID;
102 ComparerInterfaces(MatchRule* rule)
103 : mode(ConvertToMatchType(std::get<Index::InterfacesMatchType>(*rule)))
105 requested = {std::get<Index::Interfaces>(*rule).begin(), std::get<Index::Interfaces>(*rule).end()};
108 void Update(Accessible* obj)
111 for(auto& interface : obj->GetInterfaces())
113 object.insert(std::move(interface));
117 bool RequestEmpty() const
119 return requested.empty();
122 bool ObjectEmpty() const
124 return object.empty();
127 bool Compare(CompareFuncExit exit)
129 bool foundAny = false;
130 for(auto& iname : requested)
132 bool found = (object.find(iname) != object.end());
138 if(found == (exit == CompareFuncExit::FIRST_FOUND))
145 }; // ComparerInterfaces struct
147 struct ComparerAttributes
149 std::unordered_map<std::string, std::string> requested, object;
150 Mode mode = Mode::INVALID;
152 ComparerAttributes(MatchRule* rule)
153 : mode(ConvertToMatchType(std::get<Index::AttributesMatchType>(*rule)))
155 requested = std::get<Index::Attributes>(*rule);
158 void Update(Accessible* obj)
160 object = obj->GetAttributes();
163 bool RequestEmpty() const
165 return requested.empty();
168 bool ObjectEmpty() const
170 return object.empty();
173 bool Compare(CompareFuncExit exit)
175 bool foundAny = false;
176 for(auto& iname : requested)
178 auto it = object.find(iname.first);
179 bool found = it != object.end() && iname.second == it->second;
185 if(found == (exit == CompareFuncExit::FIRST_FOUND))
192 }; // ComparerAttributes struct
196 using Roles = BitSets<4, Role>;
197 Roles requested, object;
198 Mode mode = Mode::INVALID;
200 ComparerRoles(MatchRule* rule)
201 : mode(ConvertToMatchType(std::get<Index::RolesMatchType>(*rule)))
203 requested = Roles{std::get<Index::Roles>(*rule)};
206 void Update(Accessible* obj)
209 object[obj->GetRole()] = true;
213 bool RequestEmpty() const
218 bool ObjectEmpty() const
223 bool Compare(CompareFuncExit exit)
234 return requested == (object & requested);
238 return bool(object & requested);
242 return bool(object & requested);
247 }; // ComparerRoles struct
249 struct ComparerStates
251 States requested, object;
252 Mode mode = Mode::INVALID;
254 ComparerStates(MatchRule* rule)
255 : mode(ConvertToMatchType(std::get<Index::StatesMatchType>(*rule)))
257 requested = States{std::get<Index::States>(*rule)};
260 void Update(Accessible* obj)
262 object = obj->GetStates();
265 bool RequestEmpty() const
270 bool ObjectEmpty() const
275 bool Compare(CompareFuncExit exit)
286 return requested == (object & requested);
290 return bool(object & requested);
294 return bool(object & requested);
299 }; // ComparerStates struct
302 bool CompareFunc(T& cmp, Accessible* obj)
304 if(cmp.mode == Mode::INVALID)
314 if(cmp.RequestEmpty() || cmp.ObjectEmpty())
322 if(cmp.RequestEmpty())
326 if(cmp.ObjectEmpty())
334 if(cmp.RequestEmpty() || cmp.ObjectEmpty())
342 if(cmp.RequestEmpty() && cmp.ObjectEmpty())
346 if(cmp.RequestEmpty() || cmp.ObjectEmpty())
363 if(!cmp.Compare(CompareFuncExit::FIRST_NOT_FOUND))
371 if(cmp.Compare(CompareFuncExit::FIRST_FOUND))
379 if(cmp.Compare(CompareFuncExit::FIRST_FOUND))
410 ComparerInterfaces interface;
411 ComparerAttributes attribute;
413 ComparerStates state;
415 Comparer(MatchRule* mr)
423 bool operator()(Accessible* obj)
425 return CompareFunc(interface, obj) &&
426 CompareFunc(attribute, obj) &&
427 CompareFunc(role, obj) &&
428 CompareFunc(state, obj);
430 }; // BridgeCollection::Comparer struct
432 void BridgeCollection::VisitNodes(Accessible* obj, std::vector<Accessible*>& result, Comparer& cmp, size_t maxCount)
434 if(maxCount > 0 && result.size() >= maxCount)
441 result.emplace_back(obj);
444 for(auto i = 0u; i < obj->GetChildCount(); ++i)
446 VisitNodes(obj->GetChildAtIndex(i), result, cmp, maxCount);
450 DBus::ValueOrError<std::vector<Accessible*> > BridgeCollection::GetMatches(MatchRule rule, uint32_t sortBy, int32_t count, bool traverse)
452 std::vector<Accessible*> res;
453 auto self = BridgeBase::FindSelf();
454 auto matcher = Comparer{&rule};
455 VisitNodes(self, res, matcher, count);
457 switch(static_cast<SortOrder>(sortBy))
459 case SortOrder::CANONICAL:
464 case SortOrder::REVERSE_CANONICAL:
466 std::reverse(res.begin(), res.end());
472 throw std::domain_error{"unsupported sorting order"};