Use existing callback ID for recurring callbacks
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-accessible.cpp
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/accessibility/bridge/bridge-accessible.h>
20
21 // EXTERNAL INCLUDES
22 #include <iostream>
23
24 //comment out 2 lines below to get more logs
25 #undef LOG
26 #define LOG() _LoggerEmpty()
27
28 using namespace Dali::Accessibility;
29
30 #define GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH 10000
31
32 BridgeAccessible::BridgeAccessible()
33 {
34 }
35
36 void BridgeAccessible::RegisterInterfaces()
37 {
38   DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceAccessible};
39   AddGetPropertyToInterface( desc, "ChildCount", &BridgeAccessible::GetChildCount );
40   AddGetPropertyToInterface( desc, "Name", &BridgeAccessible::GetName );
41   AddGetPropertyToInterface( desc, "Description", &BridgeAccessible::GetDescription );
42   AddGetPropertyToInterface( desc, "Parent", &BridgeAccessible::GetParent );
43   AddFunctionToInterface( desc, "GetRole", &BridgeAccessible::GetRole );
44   AddFunctionToInterface( desc, "GetRoleName", &BridgeAccessible::GetRoleName );
45   AddFunctionToInterface( desc, "GetLocalizedRoleName", &BridgeAccessible::GetLocalizedRoleName );
46   AddFunctionToInterface( desc, "GetState", &BridgeAccessible::GetStates );
47   AddFunctionToInterface( desc, "GetAttributes", &BridgeAccessible::GetAttributes );
48   AddFunctionToInterface( desc, "GetInterfaces", &BridgeAccessible::GetInterfaces );
49   AddFunctionToInterface( desc, "GetChildAtIndex", &BridgeAccessible::GetChildAtIndex );
50   AddFunctionToInterface( desc, "GetChildren", &BridgeAccessible::GetChildren );
51   AddFunctionToInterface( desc, "GetIndexInParent", &BridgeAccessible::GetIndexInParent );
52   AddFunctionToInterface( desc, "GetNavigableAtPoint", &BridgeAccessible::GetNavigableAtPoint );
53   AddFunctionToInterface( desc, "GetNeighbor", &BridgeAccessible::GetNeighbor );
54   AddFunctionToInterface( desc, "GetDefaultLabelInfo", &BridgeAccessible::GetDefaultLabelInfo );
55   AddFunctionToInterface( desc, "DoGesture", &BridgeAccessible::DoGesture );
56   AddFunctionToInterface( desc, "GetReadingMaterial", &BridgeAccessible::GetReadingMaterial );
57   AddFunctionToInterface( desc, "GetRelationSet", &BridgeAccessible::GetRelationSet );
58   dbusServer.addInterface( "/", desc, true );
59 }
60
61 static bool AcceptObjectCheckRole( Component* obj )
62 {
63   if( !obj )
64     return false;
65   switch( obj->GetRole() )
66   {
67     case Role::APPLICATION:
68     case Role::FILLER:
69     case Role::SCROLL_PANE:
70     case Role::SPLIT_PANE:
71     case Role::WINDOW:
72     case Role::IMAGE:
73     case Role::IMAGE_MAP:
74     case Role::LIST:
75     case Role::ICON:
76     case Role::TOOL_BAR:
77     case Role::REDUNDANT_OBJECT:
78     case Role::COLOR_CHOOSER:
79     case Role::TREE_TABLE:
80     case Role::PAGE_TAB_LIST:
81     case Role::PAGE_TAB:
82     case Role::SPIN_BUTTON:
83     case Role::INPUT_METHOD_WINDOW:
84     case Role::EMBEDDED:
85     case Role::INVALID:
86     case Role::NOTIFICATION:
87     case Role::DATE_EDITOR:
88     case Role::TABLE:
89     {
90       return false;
91     }
92     default:
93     {
94       break;
95     }
96   }
97
98   return true;
99 }
100
101 static bool AcceptObjectCheckRelations( Component* obj)
102 {
103   auto r = obj->GetRelationSet();
104
105   for (const auto& it : r)
106     if (it.relationType == RelationType::CONTROLLED_BY)
107       return false;
108
109   return true;
110 }
111
112 static Component* GetScrollableParent( Accessible* obj )
113 {
114   while( obj )
115   {
116     obj = obj->GetParent();
117     auto comp = dynamic_cast< Component* >( obj );
118     if( comp && comp->IsScrollable() )
119       return comp;
120   }
121   return nullptr;
122 }
123
124 static bool ObjectIsItem( Component* obj )
125 {
126   if( !obj )
127     return false;
128   auto role = obj->GetRole();
129   return role == Role::LIST_ITEM || role == Role::MENU_ITEM;
130 }
131
132 static bool ObjectIsCollapsed( Component* obj )
133 {
134   if( !obj )
135     return false;
136   const auto states = obj->GetStates();
137   return states[State::EXPANDABLE] && !states[State::EXPANDED];
138 }
139
140 static bool OobjectIsZeroSize( Component* obj )
141 {
142   if( !obj )
143     return false;
144   auto extents = obj->GetExtents( CoordType::WINDOW );
145   return extents.height == 0 || extents.width == 0;
146 }
147
148 static bool AcceptObject( Component* obj )
149 {
150   if( !obj )
151     return false;
152   const auto states = obj->GetStates();
153   if( !states[State::VISIBLE] )
154     return false;
155   if( !AcceptObjectCheckRole( obj ) )
156     return false;
157   if ( !AcceptObjectCheckRelations( obj ) )
158     return false;
159   if( !states[State::HIGHLIGHTABLE] )
160     return false;
161
162   if( GetScrollableParent( obj ) != nullptr )
163   {
164     auto parent = dynamic_cast< Component* >( obj->GetParent() );
165
166     if( parent )
167     {
168       return !ObjectIsItem( obj ) || !ObjectIsCollapsed( parent );
169     }
170   }
171   else
172   {
173     if( OobjectIsZeroSize( obj ) )
174     {
175       return false;
176     }
177     if( !states[State::SHOWING] )
178     {
179       return false;
180     }
181   }
182   return true;
183 }
184
185 static bool AcceptObject( Accessible* obj )
186 {
187   auto c = dynamic_cast< Component* >( obj );
188   return AcceptObject( c );
189 }
190
191 static std::string objDump( Component* obj )
192 {
193   if ( !obj )
194     return "nullptr";
195   std::ostringstream o;
196   auto e = obj->GetExtents( CoordType::SCREEN );
197   o << "name: " << obj->GetName() << " extent: (" << e.x << ", "
198       << e.y << "), [" << e.width << ", " << e.height << "]";
199   return o.str();
200 }
201
202 Component * BridgeAccessible::GetObjectInRelation( Accessible * obj, RelationType ralationType )
203 {
204   if ( !obj )
205     return nullptr;
206   for ( auto &relation : obj->GetRelationSet() )
207   {
208     if ( relation.relationType == ralationType )
209     {
210       for ( auto &address : relation.targets )
211       {
212         auto component = dynamic_cast<Component*>( Find( address ) );
213         if ( component )
214           return component;
215       }
216     }
217   }
218   return nullptr;
219 }
220
221 static std::string makeIndent( unsigned int maxRecursionDepth )
222 {
223   return std::string( GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH - maxRecursionDepth, ' ' );
224 }
225
226 Component* BridgeAccessible::CalculateNavigableAccessibleAtPoint( Accessible* root, Point p, CoordType cType, unsigned int maxRecursionDepth )
227 {
228   if( !root || maxRecursionDepth == 0 )
229     return nullptr;
230   auto root_component = dynamic_cast< Component* >( root );
231   LOG() << "CalculateNavigableAccessibleAtPoint: checking: " << makeIndent(maxRecursionDepth) << objDump(root_component);
232
233   if( root_component && !root_component->Contains( p, cType ) )
234     return nullptr;
235
236   auto children = root->GetChildren();
237   for( auto childIt = children.rbegin(); childIt != children.rend(); childIt++ )
238   {
239     //check recursively all children first
240     auto result = CalculateNavigableAccessibleAtPoint( *childIt, p, cType, maxRecursionDepth - 1 );
241     if( result )
242       return result;
243   }
244   if( root_component )
245   {
246     //Found a candidate, all its children are already checked
247     auto controledBy = GetObjectInRelation( root_component, RelationType::CONTROLLED_BY );
248     if ( !controledBy )
249       controledBy = root_component;
250
251     if ( controledBy->IsProxy() || AcceptObject( controledBy ) )
252     {
253       LOG() << "CalculateNavigableAccessibleAtPoint: found:    " << makeIndent(maxRecursionDepth) << objDump( root_component );
254       return controledBy;
255     }
256   }
257   return nullptr;
258 }
259
260 BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
261 {
262   auto self = FindSelf();
263   auto attributes = self->GetAttributes();
264   auto name = self->GetName();
265   std::string labeledByName = "";
266   std::string textIfceName = "";
267   auto role = static_cast< uint32_t >( self->GetRole() );
268   auto states = self->GetStates();
269   auto localizedName = self->GetLocalizedRoleName();
270   auto childCount = static_cast< int32_t >( self->GetChildCount() );
271
272   double currentValue = 0.0;
273   double minimumIncrement = 0.0;
274   double maximumValue = 0.0;
275   double minimumValue = 0.0;
276
277   auto *value = dynamic_cast<Dali::Accessibility::Value *>(self);
278   if (value)
279   {
280     currentValue = value->GetCurrent();
281     minimumIncrement = value->GetMinimumIncrement();
282     maximumValue = value->GetMaximum();
283     minimumValue = value->GetMinimum();
284   }
285
286   auto description = self->GetDescription();
287   auto indexInParent = static_cast< int32_t >( self->GetIndexInParent() );
288   bool isSelectedInParent = false;
289   bool hasCheckBoxChild = false;
290   int32_t firstSelectedChildIndex = -1;
291   int32_t selectedChildCount = 0;
292
293   for( auto i = 0u; i < static_cast< size_t >( childCount ); ++i )
294   {
295     auto q = self->GetChildAtIndex( i );
296     auto s = q->GetStates();
297     if( s[State::SELECTABLE] )
298     {
299       if( s[State::SELECTED] )
300       {
301         ++selectedChildCount;
302         if( firstSelectedChildIndex < 0 )
303           firstSelectedChildIndex = static_cast< int32_t >( i );
304       }
305     }
306     if( q->GetRole() == Role::CHECK_BOX )
307       hasCheckBoxChild = true;
308   }
309
310   int32_t listChildrenCount = 0;
311   Accessible* parent = self->GetParent();
312   auto parentStateSet = parent ? parent->GetStates() : States{};
313   auto parentChildCount = parent ? static_cast< int32_t >( parent->GetChildCount() ) : 0;
314   auto parentRole = static_cast< uint32_t >( parent ? parent->GetRole() : Role{} );
315   Accessible* describedByObject = nullptr;
316
317   return {
318       attributes,
319       name,
320       labeledByName,
321       textIfceName,
322       role,
323       states,
324       localizedName,
325       childCount,
326       currentValue,
327       minimumIncrement,
328       maximumValue,
329       minimumValue,
330       description,
331       indexInParent,
332       isSelectedInParent,
333       hasCheckBoxChild,
334       listChildrenCount,
335       firstSelectedChildIndex,
336       parent,
337       parentStateSet,
338       parentChildCount,
339       parentRole,
340       selectedChildCount,
341       describedByObject};
342 }
343
344 DBus::ValueOrError< bool > BridgeAccessible::DoGesture( Dali::Accessibility::Gesture type, int32_t xBeg, int32_t xEnd, int32_t yBeg, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime )
345 {
346  return FindSelf()->DoGesture( Dali::Accessibility::GestureInfo {type, xBeg, xEnd, yBeg, yEnd, state, eventTime});
347 }
348
349 DBus::ValueOrError< Accessible*, uint8_t, Accessible* > BridgeAccessible::GetNavigableAtPoint( int32_t x, int32_t y, uint32_t coordType )
350 {
351   Accessible* deputy = nullptr;
352   auto accessible = FindSelf();
353   auto cType = static_cast< CoordType >( coordType );
354   LOG() << "GetNavigableAtPoint: " << x << ", " << y << " type: " << coordType;
355   auto component = CalculateNavigableAccessibleAtPoint( accessible, {x, y}, cType, GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH );
356   bool recurse = false;
357   if( component )
358   {
359     recurse = component->IsProxy();
360   }
361   //TODO: add deputy
362   return {component, recurse, deputy};
363 }
364
365 static bool CheckChainEndWithAttribute( Accessible* obj, unsigned char forward )
366 {
367   if( !obj )
368     return false;
369   auto attrs = obj->GetAttributes();
370   for( auto& attr : attrs )
371   {
372     if( attr.first == "relation_chain_end" )
373     {
374       if( ( attr.second == "prev,end" && forward == 0 ) || ( attr.second == "next,end" && forward == 1 ) || attr.second == "prev,next,end" )
375       {
376         return true;
377       }
378     }
379   }
380   return false;
381 }
382
383 static Accessible* DeputyOfProxyInParentGet( Accessible* obj )
384 {
385   return nullptr;
386 }
387
388 Accessible* BridgeAccessible::GetCurrentlyHighlighted()
389 {
390   //TODO: add currently highlighted object
391   return nullptr;
392 }
393
394 std::vector< Accessible* > BridgeAccessible::ValidChildrenGet( const std::vector< Accessible* >& children, Accessible* start, Accessible* root )
395 {
396   return children;
397 }
398
399 static bool DeputyIs( Accessible* obj )
400 {
401   //TODO: add deputy
402   return false;
403 }
404
405 static Accessible* ProxyInParentGet( Accessible* obj )
406 {
407   if( !obj )
408     return nullptr;
409   auto children = obj->GetChildren();
410   for( auto& child : children )
411   {
412     if( child->IsProxy() )
413       return child;
414   }
415   return nullptr;
416 }
417
418 static bool ObjectRoleIsAcceptableWhenNavigatingNextPrev( Accessible* obj )
419 {
420   if( !obj )
421     return false;
422   auto role = obj->GetRole();
423   return role != Role::POPUP_MENU && role != Role::DIALOG;
424 }
425
426 template < class T >
427 struct CycleDetection
428 {
429   CycleDetection( const T value ) : key( value ), currentSearchSize( 1 ), counter( 1 ) {}
430   bool check( const T value )
431   {
432     if( key == value )
433       return true;
434     if( --counter == 0 )
435     {
436       currentSearchSize <<= 1;
437       if( currentSearchSize == 0 )
438         return true; // UNDEFINED BEHAVIOR
439       counter = currentSearchSize;
440       key = value;
441     }
442     return false;
443   }
444   T key;
445   unsigned int currentSearchSize;
446   unsigned int counter;
447 };
448
449 static Accessible* FindNonDefunctChild( const std::vector< Accessible* >& children, unsigned int currentIndex, unsigned char forward )
450 {
451   unsigned int childrenCount = children.size();
452   for( ; currentIndex < childrenCount; forward ? ++currentIndex : --currentIndex )
453   {
454     Accessible* n = children[currentIndex];
455     if( n && !n->GetStates()[State::DEFUNCT] )
456       return n;
457   }
458   return nullptr;
459 }
460
461 static Accessible* DirectionalDepthFirstSearchTryNonDefunctChild( Accessible* node, const std::vector< Accessible* >& children, unsigned char forward )
462 {
463   if( !node )
464     return nullptr;
465   auto childrenCount = children.size();
466   if( childrenCount > 0 )
467   {
468     const bool isShowing = GetScrollableParent( node ) == nullptr ? node->GetStates()[State::SHOWING] : true;
469     if( isShowing )
470     {
471       return FindNonDefunctChild( children, forward ? 0 : childrenCount - 1, forward );
472     }
473   }
474   return nullptr;
475 }
476
477 Accessible* BridgeAccessible::GetNextNonDefunctSibling( Accessible* obj, Accessible* start, Accessible* root, unsigned char forward )
478 {
479   if( !obj )
480     return nullptr;
481   auto parent = obj->GetParent();
482   if( !parent )
483     return nullptr;
484
485   auto children = ValidChildrenGet( parent->GetChildren(), start, root );
486
487   unsigned int children_count = children.size();
488   if( children_count == 0 )
489   {
490     return nullptr;
491   }
492   unsigned int current = 0;
493   for( ; current < children_count && children[current] != obj; ++current )
494     ;
495   if( current >= children_count )
496   {
497     return nullptr;
498   }
499   forward ? ++current : --current;
500   auto ret = FindNonDefunctChild( children, current, forward );
501   return ret;
502 }
503
504 Accessible* BridgeAccessible::DirectionalDepthFirstSearchTryNonDefunctSibling( bool& all_children_visited, Accessible* node, Accessible* start, Accessible* root, unsigned char forward )
505 {
506   while( true )
507   {
508     Accessible* sibling = GetNextNonDefunctSibling( node, start, root, forward );
509     if( sibling )
510     {
511       node = sibling;
512       all_children_visited = false;
513       break;
514     }
515     // walk up...
516     node = node->GetParent();
517     if( node == nullptr || node == root )
518       return nullptr;
519
520     // in backward traversing stop the walk up on parent
521     if( !forward )
522       break;
523   }
524   return node;
525 }
526
527 Accessible* BridgeAccessible::CalculateNeighbor( Accessible* root, Accessible* start, unsigned char forward, BridgeAccessible::GetNeighborSearchMode search_mode )
528 {
529   if( start && CheckChainEndWithAttribute( start, forward ) )
530     return start;
531   if( root && root->GetStates()[State::DEFUNCT] )
532     return NULL;
533   if( start && start->GetStates()[State::DEFUNCT] )
534   {
535     start = NULL;
536     forward = 1;
537   }
538
539   if( search_mode == BridgeAccessible::GetNeighborSearchMode::recurseToOutside )
540   {
541     // This only works if we navigate backward, and it is not possible to
542     // find in embedded process. In this case the deputy should be used */
543     return DeputyOfProxyInParentGet( start );
544   }
545
546   Accessible* node = start ? start : root;
547   if( !node )
548     return nullptr;
549
550   // initialization of all-children-visited flag for start node - we assume
551   // that when we begin at start node and we navigate backward, then all children
552   // are visited, so navigation will ignore start's children and go to
553   // previous sibling available.
554   // Regarding condtion (start != root):
555   // The last object can be found only if all_children_visited is false.
556   // The start is same with root, when looking for the last object.
557   bool all_children_visited = ( start != root ) && ( search_mode != BridgeAccessible::GetNeighborSearchMode::recurseFromRoot && !forward );
558   // true, if starting element should be ignored. this is only used in rare case of
559   // recursive search failing to find an object.
560   // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
561   // element A algorithm has to descend into BUS_B and search element B and its children. this is done
562   // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
563   // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
564   // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
565   // this flag means, that object A was already checked previously and we should skip it and its children.
566   bool force_next = ( search_mode == BridgeAccessible::GetNeighborSearchMode::continueAfterFailedRecursion );
567
568   CycleDetection< Accessible* > cycleDetection( node );
569   while( node )
570   {
571     if( node->GetStates()[State::DEFUNCT] )
572       return nullptr;
573
574     // always accept proxy object from different world
575     if( !force_next && node->IsProxy() )
576       return node;
577
578     auto children = node->GetChildren();
579     children = ValidChildrenGet( children, start, root );
580
581     // do accept:
582     // 1. not start node
583     // 2. parent after all children in backward traversing
584     // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
585     //    Objects with those roles shouldnt be reachable, when navigating next / prev.
586     bool all_children_visited_or_moving_forward = ( children.size() == 0 || forward || all_children_visited );
587     if( !force_next && node != start && all_children_visited_or_moving_forward && AcceptObject( node ) )
588     {
589       if( start == NULL || ObjectRoleIsAcceptableWhenNavigatingNextPrev( node ) )
590         return node;
591     }
592
593     Accessible* next_related_in_direction = !force_next ? GetObjectInRelation( node, forward ? RelationType::FLOWS_TO : RelationType::FLOWS_FROM ) : nullptr;
594     // force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
595     // in this case the node is elm_layout which is parent of proxy object.
596     // There is an access object working for the proxy object, and the access
597     // object could have relation information. This relation information should
598     // be checked first before using the elm_layout as a node.
599     if( force_next && forward )
600     {
601       auto deputy = DeputyOfProxyInParentGet( node );
602       next_related_in_direction =
603           GetObjectInRelation( deputy, RelationType::FLOWS_TO );
604     }
605
606     if( next_related_in_direction && start && start->GetStates()[State::DEFUNCT] )
607     {
608       next_related_in_direction = NULL;
609     }
610
611     unsigned char want_cycle_detection = 0;
612     if( next_related_in_direction )
613     {
614       // Check next_related_in_direction is deputy object
615       Accessible* parent;
616       if( !forward )
617       {
618         // If the prev object is deputy, then go to inside of its proxy first
619         if( DeputyIs( next_related_in_direction ) )
620         {
621           parent = next_related_in_direction->GetParent();
622           next_related_in_direction = ProxyInParentGet( parent );
623         }
624       }
625       else
626       {
627         // If current object is deputy, and it has relation next object,
628         // then do not use the relation next object, and use proxy first
629         if( DeputyIs( node ) )
630         {
631           parent = node->GetParent();
632           next_related_in_direction = ProxyInParentGet( parent );
633         }
634       }
635       node = next_related_in_direction;
636       want_cycle_detection = 1;
637     }
638     else
639     {
640       auto child = !force_next && !all_children_visited ? DirectionalDepthFirstSearchTryNonDefunctChild( node, children, forward ) : nullptr;
641       if( child )
642       {
643         want_cycle_detection = 1;
644       }
645       else
646       {
647         if( !force_next && node == root )
648           return NULL;
649         all_children_visited = true;
650         child = DirectionalDepthFirstSearchTryNonDefunctSibling( all_children_visited, node, start, root, forward );
651       }
652       node = child;
653     }
654     force_next = 0;
655     if( want_cycle_detection && cycleDetection.check( node ) )
656     {
657       return NULL;
658     }
659   }
660   return NULL;
661 }
662
663 DBus::ValueOrError< Accessible*, uint8_t > BridgeAccessible::GetNeighbor( std::string rootPath, int32_t direction, int32_t search_mode )
664 {
665   auto start = FindSelf();
666   rootPath = StripPrefix( rootPath );
667   auto root = !rootPath.empty() ? Find( rootPath ) : nullptr;
668   auto accessible = CalculateNeighbor( root, start, direction == 1, static_cast< GetNeighborSearchMode >( search_mode ) );
669   unsigned char recurse = 0;
670   if( accessible )
671   {
672     recurse = accessible->IsProxy();
673   }
674   return {accessible, recurse};
675 }
676
677 Accessible* BridgeAccessible::GetParent()
678 {
679   // NOTE: currently bridge supports single application root element.
680   // only element set as application root might return nullptr from GetParent
681   // if you want more, then you need to change setApplicationRoot to
682   // add/remove ApplicationRoot and make roots a vector.
683   auto p = FindSelf()->GetParent();
684   assert( p );
685   return p;
686 }
687 DBus::ValueOrError< std::vector< Accessible* > > BridgeAccessible::GetChildren()
688 {
689   return FindSelf()->GetChildren();
690 }
691 std::string BridgeAccessible::GetDescription()
692 {
693   return FindSelf()->GetDescription();
694 }
695 DBus::ValueOrError< uint32_t > BridgeAccessible::GetRole()
696 {
697   return static_cast< unsigned int >( FindSelf()->GetRole() );
698 }
699 DBus::ValueOrError< std::string > BridgeAccessible::GetRoleName()
700 {
701   return FindSelf()->GetRoleName();
702 }
703 DBus::ValueOrError< std::string > BridgeAccessible::GetLocalizedRoleName()
704 {
705   return FindSelf()->GetLocalizedRoleName();
706 }
707 DBus::ValueOrError< int32_t > BridgeAccessible::GetIndexInParent()
708 {
709   return FindSelf()->GetIndexInParent();
710 }
711 DBus::ValueOrError< std::array< uint32_t, 2 > > BridgeAccessible::GetStates()
712 {
713   return FindSelf()->GetStates().GetRawData();
714 }
715 DBus::ValueOrError< std::unordered_map< std::string, std::string > > BridgeAccessible::GetAttributes()
716 {
717   return FindSelf()->GetAttributes();
718 }
719 DBus::ValueOrError< std::vector< std::string > > BridgeAccessible::GetInterfaces()
720 {
721   return FindSelf()->GetInterfaces();
722 }
723 int BridgeAccessible::GetChildCount()
724 {
725   return FindSelf()->GetChildCount();
726 }
727 DBus::ValueOrError< Accessible* > BridgeAccessible::GetChildAtIndex( int index )
728 {
729   if( index < 0 )
730     throw std::domain_error{"negative index (" + std::to_string( index ) + ")"};
731   return FindSelf()->GetChildAtIndex( static_cast< size_t >( index ) );
732 }
733
734 std::string BridgeAccessible::GetName()
735 {
736   return FindSelf()->GetName();
737 }
738
739 DBus::ValueOrError< Accessible*, uint32_t , std::unordered_map< std::string, std::string > > BridgeAccessible::GetDefaultLabelInfo()
740 {
741   auto defaultLabel = FindSelf()->GetDefaultLabel();
742   return {defaultLabel, static_cast< uint32_t >( defaultLabel->GetRole() ) , defaultLabel->GetAttributes()};
743 }
744
745 DBus::ValueOrError<std::vector< BridgeAccessible::Relation >> BridgeAccessible::GetRelationSet()
746 {
747   auto relations = FindSelf()->GetRelationSet();
748   std::vector< BridgeAccessible::Relation > ret;
749
750   for (auto &it : relations)
751     ret.emplace_back(Relation{static_cast<uint32_t>(it.relationType), it.targets});
752
753   return ret;
754 }