2 * Copyright (c) 2019 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/tizen-wayland/atspi/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 ) : mode( ConvertToMatchType( std::get< Index::InterfacesMatchType >( *rule ) ) )
102 requested = {std::get< Index::Interfaces >( *rule ).begin(), std::get< Index::Interfaces >( *rule ).end()};
104 void Update( Accessible* obj )
107 for( auto& q : obj->GetInterfaces() )
108 object.insert( std::move( q ) );
110 bool RequestEmpty() const { return requested.empty(); }
111 bool ObjectEmpty() const { return object.empty(); }
112 bool Compare( CompareFuncExit exit )
114 bool foundAny = false;
115 for( auto& iname : requested )
117 bool found = ( object.find( iname ) != object.end() );
120 if( found == ( exit == CompareFuncExit::FIRST_FOUND ) )
126 struct ComparerAttributes
128 std::unordered_map< std::string, std::string > requested, object;
129 Mode mode = Mode::INVALID;
131 ComparerAttributes( MatchRule* rule ) : mode( ConvertToMatchType( std::get< Index::AttributesMatchType >( *rule ) ) )
133 requested = std::get< Index::Attributes >( *rule );
135 void Update( Accessible* obj )
137 object = obj->GetAttributes();
139 bool RequestEmpty() const { return requested.empty(); }
140 bool ObjectEmpty() const { return object.empty(); }
141 bool Compare( CompareFuncExit exit )
143 bool foundAny = false;
144 for( auto& iname : requested )
146 auto it = object.find( iname.first );
147 bool found = it != object.end() && iname.second == it->second;
150 if( found == ( exit == CompareFuncExit::FIRST_FOUND ) )
160 using Roles = BitSets< 4, Role >;
161 Roles requested, object;
162 Mode mode = Mode::INVALID;
164 ComparerRoles( MatchRule* rule ) : mode( ConvertToMatchType( std::get< Index::RolesMatchType >( *rule ) ) )
166 requested = Roles{std::get< Index::Roles >( *rule )};
168 void Update( Accessible* obj )
171 object[obj->GetRole()] = true;
174 bool RequestEmpty() const { return !requested; }
175 bool ObjectEmpty() const { return !object; }
176 bool Compare( CompareFuncExit exit )
187 return requested == ( object & requested );
191 return bool( object & requested );
195 return bool( object & requested );
201 struct ComparerStates
203 States requested, object;
204 Mode mode = Mode::INVALID;
206 ComparerStates( MatchRule* rule ) : mode( ConvertToMatchType( std::get< Index::StatesMatchType >( *rule ) ) )
208 requested = States{std::get< Index::States >( *rule )};
210 void Update( Accessible* obj )
212 object = obj->GetStates();
214 bool RequestEmpty() const { return !requested; }
215 bool ObjectEmpty() const { return !object; }
216 bool Compare( CompareFuncExit exit )
227 return requested == ( object & requested );
231 return bool( object & requested );
235 return bool( object & requested );
242 template < typename T >
243 bool compareFunc( T& cmp, Accessible* obj )
245 if( cmp.mode == Mode::INVALID )
252 if( cmp.RequestEmpty() || cmp.ObjectEmpty() )
258 if( cmp.RequestEmpty() )
260 if( cmp.ObjectEmpty() )
266 if( cmp.RequestEmpty() || cmp.ObjectEmpty() )
272 if( cmp.RequestEmpty() && cmp.ObjectEmpty() )
274 if( cmp.RequestEmpty() || cmp.ObjectEmpty() )
289 if( !cmp.Compare( CompareFuncExit::FIRST_NOT_FOUND ) )
295 if( cmp.Compare( CompareFuncExit::FIRST_FOUND ) )
301 if( cmp.Compare( CompareFuncExit::FIRST_FOUND ) )
330 ComparerInterfaces ci;
331 ComparerAttributes ca;
335 Comparer( MatchRule* mr ) : ci( mr ), ca( mr ), cr( mr ), cs( mr ) {}
337 bool operator()( Accessible* obj )
339 return compareFunc( ci, obj ) &&
340 compareFunc( ca, obj ) &&
341 compareFunc( cr, obj ) &&
342 compareFunc( cs, obj );
346 void BridgeCollection::VisitNodes( Accessible* obj, std::vector< Accessible* >& result, Comparer& cmp, size_t maxCount )
348 if( result.size() >= maxCount )
352 result.emplace_back( obj );
354 for( auto i = 0u; i < obj->GetChildCount(); ++i )
355 VisitNodes( obj->GetChildAtIndex( i ), result, cmp, maxCount );
358 DBus::ValueOrError< std::vector< Accessible* > > BridgeCollection::GetMatches( MatchRule rule, uint32_t sortBy, int32_t count, bool traverse )
360 std::vector< Accessible* > res;
361 auto self = BridgeBase::FindSelf();
362 auto matcher = Comparer{&rule};
363 VisitNodes( self, res, matcher, count );
365 switch( static_cast< SortOrder >( sortBy ) )
367 case SortOrder::CANONICAL:
372 case SortOrder::REVERSE_CANONICAL:
374 std::reverse( res.begin(), res.end() );
380 throw std::domain_error{"unsupported sorting order"};