1 #include "BridgeCollection.hpp"
4 #include <unordered_set>
7 using namespace Dali::Accessibility;
9 void BridgeCollection::RegisterInterfaces()
11 DBus::DBusInterfaceDescription desc{ATSPI_DBUS_INTERFACE_COLLECTION};
12 AddFunctionToInterface( desc, "GetMatches", &BridgeCollection::GetMatches );
13 dbusServer.addInterface( "/", desc, true );
16 Collection* BridgeCollection::FindSelf() const
18 auto s = BridgeBase::FindSelf();
20 auto s2 = dynamic_cast< Collection* >( s );
22 throw AccessibleError{"object " + s->GetAddress().ToString() + " doesn't have Collection interface"};
28 ATSPI_Collection_MATCH_INVALID,
29 ATSPI_Collection_MATCH_ALL,
30 ATSPI_Collection_MATCH_ANY,
31 ATSPI_Collection_MATCH_NONE,
32 ATSPI_Collection_MATCH_EMPTY,
33 ATSPI_Collection_MATCH_LAST_DEFINED,
36 struct BridgeCollection::Comparer
38 using Mode = MatchType;
40 enum class CompareFuncExit
46 static Mode ConvertToMatchType( int32_t mode )
50 case ATSPI_Collection_MATCH_INVALID:
54 case ATSPI_Collection_MATCH_ALL:
58 case ATSPI_Collection_MATCH_ANY:
62 case ATSPI_Collection_MATCH_NONE:
66 case ATSPI_Collection_MATCH_EMPTY:
74 struct ComparerInterfaces
76 std::unordered_set< std::string > object;
77 std::vector< std::string > requested;
78 Mode mode = Mode::Invalid;
80 ComparerInterfaces( MatchRule* rule ) : mode( ConvertToMatchType( std::get< Index::InterfacesMatchType >( *rule ) ) )
82 requested = {std::get< Index::Interfaces >( *rule ).begin(), std::get< Index::Interfaces >( *rule ).end()};
84 void Update( Accessible* obj )
87 for( auto& q : obj->GetInterfaces() )
88 object.insert( std::move( q ) );
90 bool RequestEmpty() const { return requested.empty(); }
91 bool ObjectEmpty() const { return object.empty(); }
92 bool Compare( CompareFuncExit exit )
94 bool foundAny = false;
95 for( auto& iname : requested )
97 bool found = ( object.find( iname ) != object.end() );
100 if( found == ( exit == CompareFuncExit::firstFound ) )
106 struct ComparerAttributes
108 std::unordered_map< std::string, std::string > requested, object;
109 Mode mode = Mode::Invalid;
111 ComparerAttributes( MatchRule* rule ) : mode( ConvertToMatchType( std::get< Index::AttributesMatchType >( *rule ) ) )
113 requested = std::get< Index::Attributes >( *rule );
115 void Update( Accessible* obj )
117 object = obj->GetAttributes();
119 bool RequestEmpty() const { return requested.empty(); }
120 bool ObjectEmpty() const { return object.empty(); }
121 bool Compare( CompareFuncExit exit )
123 bool foundAny = false;
124 for( auto& iname : requested )
126 auto it = object.find( iname.first );
127 bool found = it != object.end() && iname.second == it->second;
130 if( found == ( exit == CompareFuncExit::firstFound ) )
140 using Roles = BitStates< 4, Role >;
141 Roles requested, object;
142 Mode mode = Mode::Invalid;
144 ComparerRoles( MatchRule* rule ) : mode( ConvertToMatchType( std::get< Index::RolesMatchType >( *rule ) ) )
146 requested = Roles{std::get< Index::Roles >( *rule )};
148 void Update( Accessible* obj )
151 object[obj->GetRole()] = true;
154 bool RequestEmpty() const { return !requested; }
155 bool ObjectEmpty() const { return !object; }
156 bool Compare( CompareFuncExit exit )
167 return requested == ( object & requested );
171 return bool( object & requested );
175 return bool( object & requested );
181 struct ComparerStates
183 States requested, object;
184 Mode mode = Mode::Invalid;
186 ComparerStates( MatchRule* rule ) : mode( ConvertToMatchType( std::get< Index::StatesMatchType >( *rule ) ) )
188 requested = States{std::get< Index::States >( *rule )};
190 void Update( Accessible* obj )
192 object = obj->GetStates();
194 bool RequestEmpty() const { return !requested; }
195 bool ObjectEmpty() const { return !object; }
196 bool Compare( CompareFuncExit exit )
207 return requested == ( object & requested );
211 return bool( object & requested );
215 return bool( object & requested );
222 template < typename T >
223 bool compareFunc( T& cmp, Accessible* obj )
225 if( cmp.mode == Mode::Invalid )
232 if( cmp.RequestEmpty() || cmp.ObjectEmpty() )
238 if( cmp.RequestEmpty() )
240 if( cmp.ObjectEmpty() )
246 if( cmp.RequestEmpty() || cmp.ObjectEmpty() )
252 if( cmp.RequestEmpty() && cmp.ObjectEmpty() )
254 if( cmp.RequestEmpty() || cmp.ObjectEmpty() )
269 if( !cmp.Compare( CompareFuncExit::firstNotFound ) )
275 if( cmp.Compare( CompareFuncExit::firstFound ) )
281 if( cmp.Compare( CompareFuncExit::firstFound ) )
310 ComparerInterfaces ci;
311 ComparerAttributes ca;
315 Comparer( MatchRule* mr ) : ci( mr ), ca( mr ), cr( mr ), cs( mr ) {}
317 bool operator()( Accessible* obj )
319 return compareFunc( ci, obj ) &&
320 compareFunc( ca, obj ) &&
321 compareFunc( cr, obj ) &&
322 compareFunc( cs, obj );
326 void BridgeCollection::VisitNodes( Accessible* obj, std::vector< Accessible* >& result, Comparer& cmp, size_t maxCount )
328 if( result.size() >= maxCount )
332 result.emplace_back( obj );
334 for( auto i = 0u; i < obj->GetChildCount(); ++i )
335 VisitNodes( obj->GetChildAtIndex( i ), result, cmp, maxCount );
338 DBus::ValueOrError< std::vector< Accessible* > > BridgeCollection::GetMatches( MatchRule rule, uint32_t sortBy, int32_t count, bool traverse )
340 std::vector< Accessible* > res;
341 auto self = BridgeBase::FindSelf();
342 auto matcher = Comparer{&rule};
343 VisitNodes( self, res, matcher, count );
345 switch( static_cast< SortOrder >( sortBy ) )
347 case SortOrder::Canonical:
352 case SortOrder::ReverseCanonical:
354 std::reverse( res.begin(), res.end() );
360 throw AccessibleError{"unsupported sorting order"};