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 dbusServer.addInterface("/", desc, true);
36 Collection* BridgeCollection::FindSelf() const
38 auto s = BridgeBase::FindSelf();
40 auto s2 = dynamic_cast<Collection*>(s);
42 throw std::domain_error{"object " + s->GetAddress().ToString() + " doesn't have Collection interface"};
48 ATSPI_Collection_MATCH_INVALID,
49 ATSPI_Collection_MATCH_ALL,
50 ATSPI_Collection_MATCH_ANY,
51 ATSPI_Collection_MATCH_NONE,
52 ATSPI_Collection_MATCH_EMPTY,
53 ATSPI_Collection_MATCH_LAST_DEFINED,
56 struct BridgeCollection::Comparer
58 using Mode = MatchType;
60 enum class CompareFuncExit
66 static Mode ConvertToMatchType(int32_t mode)
70 case ATSPI_Collection_MATCH_INVALID:
74 case ATSPI_Collection_MATCH_ALL:
78 case ATSPI_Collection_MATCH_ANY:
82 case ATSPI_Collection_MATCH_NONE:
86 case ATSPI_Collection_MATCH_EMPTY:
94 struct ComparerInterfaces
96 std::unordered_set<std::string> object;
97 std::vector<std::string> requested;
98 Mode mode = Mode::INVALID;
100 ComparerInterfaces(MatchRule* rule)
101 : mode(ConvertToMatchType(std::get<Index::InterfacesMatchType>(*rule)))
103 requested = {std::get<Index::Interfaces>(*rule).begin(), std::get<Index::Interfaces>(*rule).end()};
105 void Update(Accessible* obj)
108 for(auto& q : obj->GetInterfaces())
109 object.insert(std::move(q));
111 bool RequestEmpty() const
113 return requested.empty();
115 bool ObjectEmpty() const
117 return object.empty();
119 bool Compare(CompareFuncExit exit)
121 bool foundAny = false;
122 for(auto& iname : requested)
124 bool found = (object.find(iname) != object.end());
127 if(found == (exit == CompareFuncExit::FIRST_FOUND))
133 struct ComparerAttributes
135 std::unordered_map<std::string, std::string> requested, object;
136 Mode mode = Mode::INVALID;
138 ComparerAttributes(MatchRule* rule)
139 : mode(ConvertToMatchType(std::get<Index::AttributesMatchType>(*rule)))
141 requested = std::get<Index::Attributes>(*rule);
143 void Update(Accessible* obj)
145 object = obj->GetAttributes();
147 bool RequestEmpty() const
149 return requested.empty();
151 bool ObjectEmpty() const
153 return object.empty();
155 bool Compare(CompareFuncExit exit)
157 bool foundAny = false;
158 for(auto& iname : requested)
160 auto it = object.find(iname.first);
161 bool found = it != object.end() && iname.second == it->second;
164 if(found == (exit == CompareFuncExit::FIRST_FOUND))
174 using Roles = BitSets<4, Role>;
175 Roles requested, object;
176 Mode mode = Mode::INVALID;
178 ComparerRoles(MatchRule* rule)
179 : mode(ConvertToMatchType(std::get<Index::RolesMatchType>(*rule)))
181 requested = Roles{std::get<Index::Roles>(*rule)};
183 void Update(Accessible* obj)
186 object[obj->GetRole()] = true;
189 bool RequestEmpty() const
193 bool ObjectEmpty() const
197 bool Compare(CompareFuncExit exit)
208 return requested == (object & requested);
212 return bool(object & requested);
216 return bool(object & requested);
222 struct ComparerStates
224 States requested, object;
225 Mode mode = Mode::INVALID;
227 ComparerStates(MatchRule* rule)
228 : mode(ConvertToMatchType(std::get<Index::StatesMatchType>(*rule)))
230 requested = States{std::get<Index::States>(*rule)};
232 void Update(Accessible* obj)
234 object = obj->GetStates();
236 bool RequestEmpty() const
240 bool ObjectEmpty() const
244 bool Compare(CompareFuncExit exit)
255 return requested == (object & requested);
259 return bool(object & requested);
263 return bool(object & requested);
271 bool compareFunc(T& cmp, Accessible* obj)
273 if(cmp.mode == Mode::INVALID)
280 if(cmp.RequestEmpty() || cmp.ObjectEmpty())
286 if(cmp.RequestEmpty())
288 if(cmp.ObjectEmpty())
294 if(cmp.RequestEmpty() || cmp.ObjectEmpty())
300 if(cmp.RequestEmpty() && cmp.ObjectEmpty())
302 if(cmp.RequestEmpty() || cmp.ObjectEmpty())
317 if(!cmp.Compare(CompareFuncExit::FIRST_NOT_FOUND))
323 if(cmp.Compare(CompareFuncExit::FIRST_FOUND))
329 if(cmp.Compare(CompareFuncExit::FIRST_FOUND))
358 ComparerInterfaces ci;
359 ComparerAttributes ca;
363 Comparer(MatchRule* mr)
371 bool operator()(Accessible* obj)
373 return compareFunc(ci, obj) &&
374 compareFunc(ca, obj) &&
375 compareFunc(cr, obj) &&
376 compareFunc(cs, obj);
380 void BridgeCollection::VisitNodes(Accessible* obj, std::vector<Accessible*>& result, Comparer& cmp, size_t maxCount)
382 if(maxCount > 0 && result.size() >= maxCount)
386 result.emplace_back(obj);
388 for(auto i = 0u; i < obj->GetChildCount(); ++i)
389 VisitNodes(obj->GetChildAtIndex(i), result, cmp, maxCount);
392 DBus::ValueOrError<std::vector<Accessible*> > BridgeCollection::GetMatches(MatchRule rule, uint32_t sortBy, int32_t count, bool traverse)
394 std::vector<Accessible*> res;
395 auto self = BridgeBase::FindSelf();
396 auto matcher = Comparer{&rule};
397 VisitNodes(self, res, matcher, count);
399 switch(static_cast<SortOrder>(sortBy))
401 case SortOrder::CANONICAL:
406 case SortOrder::REVERSE_CANONICAL:
408 std::reverse(res.begin(), res.end());
414 throw std::domain_error{"unsupported sorting order"};