[AT-SPI] Provide correct reading material for Value
[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 (CALL(get_object_in_relation_by_type, obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0;
160   if ( !AcceptObjectCheckRelations( obj ) )
161     return false;
162   if( !states[State::HIGHLIGHTABLE] )
163     return false;
164
165   if( GetScrollableParent( obj ) != nullptr )
166   {
167     auto parent = dynamic_cast< Component* >( obj->GetParent() );
168
169     if( parent )
170     {
171       return !ObjectIsItem( obj ) || !ObjectIsCollapsed( parent );
172     }
173   }
174   else
175   {
176     if( OobjectIsZeroSize( obj ) )
177     {
178       return false;
179     }
180     if( !states[State::SHOWING] )
181     {
182       return false;
183     }
184   }
185   return true;
186 }
187
188 static bool AcceptObject( Accessible* obj )
189 {
190   auto c = dynamic_cast< Component* >( obj );
191   return AcceptObject( c );
192 }
193
194 static std::string objDump( Component* obj )
195 {
196   if ( !obj )
197     return "nullptr";
198   std::ostringstream o;
199   auto e = obj->GetExtents( CoordType::SCREEN );
200   o << "name: " << obj->GetName() << " extent: (" << e.x << ", "
201       << e.y << "), [" << e.width << ", " << e.height << "]";
202   return o.str();
203 }
204
205 Component * BridgeAccessible::GetObjectInRelation( Accessible * obj, RelationType ralationType )
206 {
207   if ( !obj )
208     return nullptr;
209   for ( auto &relation : obj->GetRelationSet() )
210   {
211     if ( relation.relationType == ralationType )
212     {
213       for ( auto &address : relation.targets )
214       {
215         auto component = dynamic_cast<Component*>( Find( address ) );
216         if ( component )
217           return component;
218       }
219     }
220   }
221   return nullptr;
222 }
223
224 static std::string makeIndent( unsigned int maxRecursionDepth )
225 {
226   return std::string( GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH - maxRecursionDepth, ' ' );
227 }
228
229 Component* BridgeAccessible::CalculateNavigableAccessibleAtPoint( Accessible* root, Point p, CoordType cType, unsigned int maxRecursionDepth )
230 {
231   if( !root || maxRecursionDepth == 0 )
232     return nullptr;
233   auto root_component = dynamic_cast< Component* >( root );
234   LOG() << "CalculateNavigableAccessibleAtPoint: checking: " << makeIndent(maxRecursionDepth) << objDump(root_component);
235
236   if( root_component && !root_component->Contains( p, cType ) )
237     return nullptr;
238
239   auto children = root->GetChildren();
240   for( auto childIt = children.rbegin(); childIt != children.rend(); childIt++ )
241   {
242     //check recursively all children first
243     auto result = CalculateNavigableAccessibleAtPoint( *childIt, p, cType, maxRecursionDepth - 1 );
244     if( result )
245       return result;
246   }
247   if( root_component )
248   {
249     //Found a candidate, all its children are already checked
250     auto controledBy = GetObjectInRelation( root_component, RelationType::CONTROLLED_BY );
251     if ( !controledBy )
252       controledBy = root_component;
253
254     if ( controledBy->IsProxy() || AcceptObject( controledBy ) )
255     {
256       LOG() << "CalculateNavigableAccessibleAtPoint: found:    " << makeIndent(maxRecursionDepth) << objDump( root_component );
257       return controledBy;
258     }
259   }
260   return nullptr;
261 }
262
263 BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
264 {
265   auto self = FindSelf();
266   auto attributes = self->GetAttributes();
267   auto name = self->GetName();
268   std::string labeledByName = "";
269   std::string textIfceName = "";
270   auto role = static_cast< uint32_t >( self->GetRole() );
271   auto states = self->GetStates();
272   auto localizedName = self->GetLocalizedRoleName();
273   auto childCount = static_cast< int32_t >( self->GetChildCount() );
274
275   double currentValue = 0.0;
276   double minimumIncrement = 0.0;
277   double maximumValue = 0.0;
278   double minimumValue = 0.0;
279
280   auto *value = dynamic_cast<Dali::Accessibility::Value *>(self);
281   if (value)
282   {
283     currentValue = value->GetCurrent();
284     minimumIncrement = value->GetMinimumIncrement();
285     maximumValue = value->GetMaximum();
286     minimumValue = value->GetMinimum();
287   }
288
289   auto description = self->GetDescription();
290   auto indexInParent = static_cast< int32_t >( self->GetIndexInParent() );
291   bool isSelectedInParent = false;
292   bool hasCheckBoxChild = false;
293   int32_t firstSelectedChildIndex = 0;
294   int32_t selectedChildCount = 0;
295
296   for( auto i = 0u; i < static_cast< size_t >( childCount ); ++i )
297   {
298     auto q = self->GetChildAtIndex( i );
299     auto s = q->GetStates();
300     if( s[State::SELECTABLE] )
301     {
302       ++selectedChildCount;
303       if( s[State::SELECTED] )
304       {
305         if( firstSelectedChildIndex < 0 )
306           firstSelectedChildIndex = static_cast< int32_t >( i );
307       }
308     }
309     if( q->GetRole() == Role::CHECK_BOX )
310       hasCheckBoxChild = true;
311   }
312
313   int32_t listChildrenCount = 0;
314   Accessible* parent = self->GetParent();
315   auto parentStateSet = parent ? parent->GetStates() : States{};
316   auto parentChildCount = parent ? static_cast< int32_t >( parent->GetChildCount() ) : 0;
317   auto parentRole = static_cast< uint32_t >( parent ? parent->GetRole() : Role{} );
318   Accessible* describedByObject = nullptr;
319
320   return {
321       attributes,
322       name,
323       labeledByName,
324       textIfceName,
325       role,
326       states,
327       localizedName,
328       childCount,
329       currentValue,
330       minimumIncrement,
331       maximumValue,
332       minimumValue,
333       description,
334       indexInParent,
335       isSelectedInParent,
336       hasCheckBoxChild,
337       listChildrenCount,
338       firstSelectedChildIndex,
339       parent,
340       parentStateSet,
341       parentChildCount,
342       parentRole,
343       selectedChildCount,
344       describedByObject};
345 }
346
347 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 )
348 {
349  return FindSelf()->DoGesture( Dali::Accessibility::GestureInfo {type, xBeg, xEnd, yBeg, yEnd, state, eventTime});
350 }
351
352 DBus::ValueOrError< Accessible*, uint8_t, Accessible* > BridgeAccessible::GetNavigableAtPoint( int32_t x, int32_t y, uint32_t coordType )
353 {
354   Accessible* deputy = nullptr;
355   auto accessible = FindSelf();
356   auto cType = static_cast< CoordType >( coordType );
357   LOG() << "GetNavigableAtPoint: " << x << ", " << y << " type: " << coordType;
358   auto component = CalculateNavigableAccessibleAtPoint( accessible, {x, y}, cType, GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH );
359   bool recurse = false;
360   if( component )
361   {
362     const auto states = component->GetStates();
363     if( states[State::MODAL] )
364     {
365       component = nullptr;
366     }
367   }
368   if( component )
369   {
370     recurse = component->IsProxy();
371   }
372   //TODO: add deputy
373   return {component, recurse, deputy};
374 }
375
376 static bool CheckChainEndWithAttribute( Accessible* obj, unsigned char forward )
377 {
378   if( !obj )
379     return false;
380   auto attrs = obj->GetAttributes();
381   for( auto& attr : attrs )
382   {
383     if( attr.first == "relation_chain_end" )
384     {
385       if( ( attr.second == "prev,end" && forward == 0 ) || ( attr.second == "next,end" && forward == 1 ) || attr.second == "prev,next,end" )
386       {
387         return true;
388       }
389     }
390   }
391   return false;
392 }
393
394 static Accessible* DeputyOfProxyInParentGet( Accessible* obj )
395 {
396   return nullptr;
397 }
398
399 Accessible* BridgeAccessible::GetCurrentlyHighlighted()
400 {
401   //TODO: add currently highlighted object
402   return nullptr;
403 }
404
405 std::vector< Accessible* > BridgeAccessible::ValidChildrenGet( const std::vector< Accessible* >& children, Accessible* start, Accessible* root )
406 {
407   return children;
408 }
409
410 static bool DeputyIs( Accessible* obj )
411 {
412   //TODO: add deputy
413   return false;
414 }
415
416 static Accessible* ProxyInParentGet( Accessible* obj )
417 {
418   if( !obj )
419     return nullptr;
420   auto children = obj->GetChildren();
421   for( auto& child : children )
422   {
423     if( child->IsProxy() )
424       return child;
425   }
426   return nullptr;
427 }
428
429 static bool ObjectRoleIsAcceptableWhenNavigatingNextPrev( Accessible* obj )
430 {
431   if( !obj )
432     return false;
433   auto role = obj->GetRole();
434   return role != Role::POPUP_MENU && role != Role::DIALOG;
435 }
436
437 template < class T >
438 struct CycleDetection
439 {
440   CycleDetection( const T value ) : key( value ), currentSearchSize( 1 ), counter( 1 ) {}
441   bool check( const T value )
442   {
443     if( key == value )
444       return true;
445     if( --counter == 0 )
446     {
447       currentSearchSize <<= 1;
448       if( currentSearchSize == 0 )
449         return true; // UNDEFINED BEHAVIOR
450       counter = currentSearchSize;
451       key = value;
452     }
453     return false;
454   }
455   T key;
456   unsigned int currentSearchSize;
457   unsigned int counter;
458 };
459
460 static Accessible* FindNonDefunctChild( const std::vector< Accessible* >& children, unsigned int currentIndex, unsigned char forward )
461 {
462   unsigned int childrenCount = children.size();
463   for( ; currentIndex < childrenCount; forward ? ++currentIndex : --currentIndex )
464   {
465     Accessible* n = children[currentIndex];
466     if( n && !n->GetStates()[State::DEFUNCT] )
467       return n;
468   }
469   return nullptr;
470 }
471
472 static Accessible* DirectionalDepthFirstSearchTryNonDefunctChild( Accessible* node, const std::vector< Accessible* >& children, unsigned char forward )
473 {
474   if( !node )
475     return nullptr;
476   auto childrenCount = children.size();
477   if( childrenCount > 0 )
478   {
479     const bool isShowing = GetScrollableParent( node ) == nullptr ? node->GetStates()[State::SHOWING] : true;
480     if( isShowing )
481     {
482       return FindNonDefunctChild( children, forward ? 0 : childrenCount - 1, forward );
483     }
484   }
485   return nullptr;
486 }
487
488 Accessible* BridgeAccessible::GetNextNonDefunctSibling( Accessible* obj, Accessible* start, Accessible* root, unsigned char forward )
489 {
490   if( !obj )
491     return nullptr;
492   auto parent = obj->GetParent();
493   if( !parent )
494     return nullptr;
495
496   auto children = ValidChildrenGet( parent->GetChildren(), start, root );
497
498   unsigned int children_count = children.size();
499   if( children_count == 0 )
500   {
501     return nullptr;
502   }
503   unsigned int current = 0;
504   for( ; current < children_count && children[current] != obj; ++current )
505     ;
506   if( current >= children_count )
507   {
508     return nullptr;
509   }
510   forward ? ++current : --current;
511   auto ret = FindNonDefunctChild( children, current, forward );
512   return ret;
513 }
514
515 Accessible* BridgeAccessible::DirectionalDepthFirstSearchTryNonDefunctSibling( bool& all_children_visited, Accessible* node, Accessible* start, Accessible* root, unsigned char forward )
516 {
517   while( true )
518   {
519     Accessible* sibling = GetNextNonDefunctSibling( node, start, root, forward );
520     if( sibling )
521     {
522       node = sibling;
523       all_children_visited = false;
524       break;
525     }
526     // walk up...
527     node = node->GetParent();
528     if( node == nullptr || node == root )
529       return nullptr;
530
531     // in backward traversing stop the walk up on parent
532     if( !forward )
533       break;
534   }
535   return node;
536 }
537
538 Accessible* BridgeAccessible::CalculateNeighbor( Accessible* root, Accessible* start, unsigned char forward, BridgeAccessible::GetNeighborSearchMode search_mode )
539 {
540   if( start && CheckChainEndWithAttribute( start, forward ) )
541     return start;
542   if( root && root->GetStates()[State::DEFUNCT] )
543     return NULL;
544   if( start && start->GetStates()[State::DEFUNCT] )
545   {
546     start = NULL;
547     forward = 1;
548   }
549
550   if( search_mode == BridgeAccessible::GetNeighborSearchMode::recurseToOutside )
551   {
552     // This only works if we navigate backward, and it is not possible to
553     // find in embedded process. In this case the deputy should be used */
554     return DeputyOfProxyInParentGet( start );
555   }
556
557   Accessible* node = start ? start : root;
558   if( !node )
559     return nullptr;
560
561   // initialization of all-children-visited flag for start node - we assume
562   // that when we begin at start node and we navigate backward, then all children
563   // are visited, so navigation will ignore start's children and go to
564   // previous sibling available.
565   // Regarding condtion (start != root):
566   // The last object can be found only if all_children_visited is false.
567   // The start is same with root, when looking for the last object.
568   bool all_children_visited = ( start != root ) && ( search_mode != BridgeAccessible::GetNeighborSearchMode::recurseFromRoot && !forward );
569   // true, if starting element should be ignored. this is only used in rare case of
570   // recursive search failing to find an object.
571   // consider tree, where element A on bus BUS_A has child B on bus BUS_B. when going "next" from
572   // element A algorithm has to descend into BUS_B and search element B and its children. this is done
573   // by returning to our caller object B with special flag set (meaning - continue the search from B on bus BUS_B).
574   // if next object will be found there (on BUS_B), then search ends. but if not, then our caller will find it out
575   // and will call us again with object A and flag search_mode set to NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING.
576   // this flag means, that object A was already checked previously and we should skip it and its children.
577   bool force_next = ( search_mode == BridgeAccessible::GetNeighborSearchMode::continueAfterFailedRecursion );
578
579   CycleDetection< Accessible* > cycleDetection( node );
580   while( node )
581   {
582     if( node->GetStates()[State::DEFUNCT] )
583       return nullptr;
584
585     // always accept proxy object from different world
586     if( !force_next && node->IsProxy() )
587       return node;
588
589     auto children = node->GetChildren();
590     children = ValidChildrenGet( children, start, root );
591
592     // do accept:
593     // 1. not start node
594     // 2. parent after all children in backward traversing
595     // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element.
596     //    Objects with those roles shouldnt be reachable, when navigating next / prev.
597     bool all_children_visited_or_moving_forward = ( children.size() == 0 || forward || all_children_visited );
598     if( !force_next && node != start && all_children_visited_or_moving_forward && AcceptObject( node ) )
599     {
600       if( start == NULL || ObjectRoleIsAcceptableWhenNavigatingNextPrev( node ) )
601         return node;
602     }
603
604     Accessible* next_related_in_direction = !force_next ? GetObjectInRelation( node, forward ? RelationType::FLOWS_TO : RelationType::FLOWS_FROM ) : nullptr;
605     // force_next means that the search_mode is NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING
606     // in this case the node is elm_layout which is parent of proxy object.
607     // There is an access object working for the proxy object, and the access
608     // object could have relation information. This relation information should
609     // be checked first before using the elm_layout as a node.
610     if( force_next && forward )
611     {
612       auto deputy = DeputyOfProxyInParentGet( node );
613       next_related_in_direction =
614           GetObjectInRelation( deputy, RelationType::FLOWS_TO );
615     }
616
617     if( next_related_in_direction && start && start->GetStates()[State::DEFUNCT] )
618     {
619       next_related_in_direction = NULL;
620     }
621
622     unsigned char want_cycle_detection = 0;
623     if( next_related_in_direction )
624     {
625       // Check next_related_in_direction is deputy object
626       Accessible* parent;
627       if( !forward )
628       {
629         // If the prev object is deputy, then go to inside of its proxy first
630         if( DeputyIs( next_related_in_direction ) )
631         {
632           parent = next_related_in_direction->GetParent();
633           next_related_in_direction = ProxyInParentGet( parent );
634         }
635       }
636       else
637       {
638         // If current object is deputy, and it has relation next object,
639         // then do not use the relation next object, and use proxy first
640         if( DeputyIs( node ) )
641         {
642           parent = node->GetParent();
643           next_related_in_direction = ProxyInParentGet( parent );
644         }
645       }
646       node = next_related_in_direction;
647       want_cycle_detection = 1;
648     }
649     else
650     {
651       auto child = !force_next && !all_children_visited ? DirectionalDepthFirstSearchTryNonDefunctChild( node, children, forward ) : nullptr;
652       if( child )
653       {
654         want_cycle_detection = 1;
655       }
656       else
657       {
658         if( !force_next && node == root )
659           return NULL;
660         all_children_visited = true;
661         child = DirectionalDepthFirstSearchTryNonDefunctSibling( all_children_visited, node, start, root, forward );
662       }
663       node = child;
664     }
665     force_next = 0;
666     if( want_cycle_detection && cycleDetection.check( node ) )
667     {
668       return NULL;
669     }
670   }
671   return NULL;
672 }
673
674 DBus::ValueOrError< Accessible*, uint8_t > BridgeAccessible::GetNeighbor( std::string rootPath, int32_t direction, int32_t search_mode )
675 {
676   auto start = FindSelf();
677   rootPath = StripPrefix( rootPath );
678   auto root = !rootPath.empty() ? Find( rootPath ) : nullptr;
679   auto accessible = CalculateNeighbor( root, start, direction == 1, static_cast< GetNeighborSearchMode >( search_mode ) );
680   unsigned char recurse = 0;
681   if( accessible )
682   {
683     recurse = accessible->IsProxy();
684   }
685   return {accessible, recurse};
686 }
687
688 Accessible* BridgeAccessible::GetParent()
689 {
690   // NOTE: currently bridge supports single application root element.
691   // only element set as application root might return nullptr from GetParent
692   // if you want more, then you need to change setApplicationRoot to
693   // add/remove ApplicationRoot and make roots a vector.
694   auto p = FindSelf()->GetParent();
695   assert( p );
696   return p;
697 }
698 DBus::ValueOrError< std::vector< Accessible* > > BridgeAccessible::GetChildren()
699 {
700   return FindSelf()->GetChildren();
701 }
702 std::string BridgeAccessible::GetDescription()
703 {
704   return FindSelf()->GetDescription();
705 }
706 DBus::ValueOrError< uint32_t > BridgeAccessible::GetRole()
707 {
708   return static_cast< unsigned int >( FindSelf()->GetRole() );
709 }
710 DBus::ValueOrError< std::string > BridgeAccessible::GetRoleName()
711 {
712   return FindSelf()->GetRoleName();
713 }
714 DBus::ValueOrError< std::string > BridgeAccessible::GetLocalizedRoleName()
715 {
716   return FindSelf()->GetLocalizedRoleName();
717 }
718 DBus::ValueOrError< int32_t > BridgeAccessible::GetIndexInParent()
719 {
720   return FindSelf()->GetIndexInParent();
721 }
722 DBus::ValueOrError< std::array< uint32_t, 2 > > BridgeAccessible::GetStates()
723 {
724   return FindSelf()->GetStates().GetRawData();
725 }
726 DBus::ValueOrError< std::unordered_map< std::string, std::string > > BridgeAccessible::GetAttributes()
727 {
728   return FindSelf()->GetAttributes();
729 }
730 DBus::ValueOrError< std::vector< std::string > > BridgeAccessible::GetInterfaces()
731 {
732   return FindSelf()->GetInterfaces();
733 }
734 int BridgeAccessible::GetChildCount()
735 {
736   return FindSelf()->GetChildCount();
737 }
738 DBus::ValueOrError< Accessible* > BridgeAccessible::GetChildAtIndex( int index )
739 {
740   if( index < 0 )
741     throw std::domain_error{"negative index (" + std::to_string( index ) + ")"};
742   return FindSelf()->GetChildAtIndex( static_cast< size_t >( index ) );
743 }
744
745 std::string BridgeAccessible::GetName()
746 {
747   return FindSelf()->GetName();
748 }
749
750 DBus::ValueOrError< Accessible*, uint32_t , std::unordered_map< std::string, std::string > > BridgeAccessible::GetDefaultLabelInfo()
751 {
752   auto defaultLabel = FindSelf()->GetDefaultLabel();
753   return {defaultLabel, static_cast< uint32_t >( defaultLabel->GetRole() ) , defaultLabel->GetAttributes()};
754 }
755
756 DBus::ValueOrError<std::vector< BridgeAccessible::Relation >> BridgeAccessible::GetRelationSet()
757 {
758   auto relations = FindSelf()->GetRelationSet();
759   std::vector< BridgeAccessible::Relation > ret;
760
761   for (auto &it : relations)
762     ret.emplace_back(Relation{static_cast<uint32_t>(it.relationType), it.targets});
763
764   return ret;
765 }