[Tizen][ATSPI] Accessibility initial implementation
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / accessibility-impl.cpp
1 #include <dali/devel-api/adaptor-framework/accessibility.h>
2 #include <dali/integration-api/debug.h>
3 #include <dali/public-api/actors/actor.h>
4 #include <dali/public-api/actors/layer.h>
5 #include <dali/public-api/common/stage.h>
6 #include <dali/public-api/object/base-object.h>
7 #include <dali/public-api/object/object-registry.h>
8 #include <dali/public-api/object/type-info.h>
9 #include <dali/public-api/object/type-registry-helper.h>
10
11 using namespace Dali::Accessibility;
12
13 std::string EmptyAccessibleWithAddress::GetRoleName()
14 {
15   return "";
16 }
17
18 std::string Accessible::GetLocalizedRoleName()
19 {
20   return GetRoleName();
21 }
22
23 std::string Accessible::GetRoleName()
24 {
25   switch( GetRole() )
26   {
27     case Role::Invalid:
28     {
29       return "invalid";
30     }
31     case Role::AcceleratorLabel:
32     {
33       return "accelerator label";
34     }
35     case Role::Alert:
36     {
37       return "alert";
38     }
39     case Role::Animation:
40     {
41       return "animation";
42     }
43     case Role::Arrow:
44     {
45       return "arrow";
46     }
47     case Role::Calendar:
48     {
49       return "calendar";
50     }
51     case Role::Canvas:
52     {
53       return "canvas";
54     }
55     case Role::CheckBox:
56     {
57       return "check box";
58     }
59     case Role::CheckMenuItem:
60     {
61       return "check menu item";
62     }
63     case Role::ColorChooser:
64     {
65       return "color chooser";
66     }
67     case Role::ColumnHeader:
68     {
69       return "column header";
70     }
71     case Role::ComboBox:
72     {
73       return "combo box";
74     }
75     case Role::DateEditor:
76     {
77       return "date editor";
78     }
79     case Role::DesktopIcon:
80     {
81       return "desktop icon";
82     }
83     case Role::DesktopFrame:
84     {
85       return "desktop frame";
86     }
87     case Role::Dial:
88     {
89       return "dial";
90     }
91     case Role::Dialog:
92     {
93       return "dialog";
94     }
95     case Role::DirectoryPane:
96     {
97       return "directory pane";
98     }
99     case Role::DrawingArea:
100     {
101       return "drawing area";
102     }
103     case Role::FileChooser:
104     {
105       return "file chooser";
106     }
107     case Role::Filler:
108     {
109       return "filler";
110     }
111     case Role::FocusTraversable:
112     {
113       return "focus traversable";
114     }
115     case Role::FontChooser:
116     {
117       return "font chooser";
118     }
119     case Role::Frame:
120     {
121       return "frame";
122     }
123     case Role::GlassPane:
124     {
125       return "glass pane";
126     }
127     case Role::HtmlContainer:
128     {
129       return "html container";
130     }
131     case Role::Icon:
132     {
133       return "icon";
134     }
135     case Role::Image:
136     {
137       return "image";
138     }
139     case Role::InternalFrame:
140     {
141       return "internal frame";
142     }
143     case Role::Label:
144     {
145       return "label";
146     }
147     case Role::LayeredPane:
148     {
149       return "layered pane";
150     }
151     case Role::List:
152     {
153       return "list";
154     }
155     case Role::ListItem:
156     {
157       return "list item";
158     }
159     case Role::Menu:
160     {
161       return "menu";
162     }
163     case Role::MenuBar:
164     {
165       return "menu bar";
166     }
167     case Role::MenuItem:
168     {
169       return "menu item";
170     }
171     case Role::OptionPane:
172     {
173       return "option pane";
174     }
175     case Role::PageTab:
176     {
177       return "page tab";
178     }
179     case Role::PageTabList:
180     {
181       return "page tab list";
182     }
183     case Role::Panel:
184     {
185       return "panel";
186     }
187     case Role::PasswordText:
188     {
189       return "password text";
190     }
191     case Role::PopupMenu:
192     {
193       return "popup menu";
194     }
195     case Role::ProgressBar:
196     {
197       return "progress bar";
198     }
199     case Role::PushButton:
200     {
201       return "push button";
202     }
203     case Role::RadioButton:
204     {
205       return "radio button";
206     }
207     case Role::RadioMenuItem:
208     {
209       return "radio menu item";
210     }
211     case Role::RootPane:
212     {
213       return "root pane";
214     }
215     case Role::RowHeader:
216     {
217       return "row header";
218     }
219     case Role::ScrollBar:
220     {
221       return "scroll bar";
222     }
223     case Role::ScrollPane:
224     {
225       return "scroll pane";
226     }
227     case Role::Separator:
228     {
229       return "separator";
230     }
231     case Role::Slider:
232     {
233       return "slider";
234     }
235     case Role::SpinButton:
236     {
237       return "spin button";
238     }
239     case Role::SplitPane:
240     {
241       return "split pane";
242     }
243     case Role::StatusBar:
244     {
245       return "status bar";
246     }
247     case Role::Table:
248     {
249       return "table";
250     }
251     case Role::TableCell:
252     {
253       return "table cell";
254     }
255     case Role::TableColumnHeader:
256     {
257       return "table column header";
258     }
259     case Role::TableRowHeader:
260     {
261       return "table row header";
262     }
263     case Role::TearoffMenuItem:
264     {
265       return "tearoff menu item";
266     }
267     case Role::Terminal:
268     {
269       return "terminal";
270     }
271     case Role::Text:
272     {
273       return "text";
274     }
275     case Role::ToggleButton:
276     {
277       return "toggle button";
278     }
279     case Role::ToolBar:
280     {
281       return "tool bar";
282     }
283     case Role::ToolTip:
284     {
285       return "tool tip";
286     }
287     case Role::Tree:
288     {
289       return "tree";
290     }
291     case Role::TreeTable:
292     {
293       return "tree table";
294     }
295     case Role::Unknown:
296     {
297       return "unknown";
298     }
299     case Role::Viewport:
300     {
301       return "viewport";
302     }
303     case Role::Window:
304     {
305       return "window";
306     }
307     case Role::Extended:
308     {
309       return "extended";
310     }
311     case Role::Header:
312     {
313       return "header";
314     }
315     case Role::Footer:
316     {
317       return "footer";
318     }
319     case Role::Paragraph:
320     {
321       return "paragraph";
322     }
323     case Role::Ruler:
324     {
325       return "ruler";
326     }
327     case Role::Application:
328     {
329       return "application";
330     }
331     case Role::Autocomplete:
332     {
333       return "autocomplete";
334     }
335     case Role::Editbar:
336     {
337       return "edit bar";
338     }
339     case Role::Embedded:
340     {
341       return "embedded";
342     }
343     case Role::Entry:
344     {
345       return "entry";
346     }
347     case Role::Chart:
348     {
349       return "chart";
350     }
351     case Role::Caption:
352     {
353       return "caution";
354     }
355     case Role::DocumentFrame:
356     {
357       return "document frame";
358     }
359     case Role::Heading:
360     {
361       return "heading";
362     }
363     case Role::Page:
364     {
365       return "page";
366     }
367     case Role::Section:
368     {
369       return "section";
370     }
371     case Role::RedundantObject:
372     {
373       return "redundant object";
374     }
375     case Role::Form:
376     {
377       return "form";
378     }
379     case Role::Link:
380     {
381       return "link";
382     }
383     case Role::InputMethodWindow:
384     {
385       return "input method window";
386     }
387     case Role::TableRow:
388     {
389       return "table row";
390     }
391     case Role::TreeItem:
392     {
393       return "tree item";
394     }
395     case Role::DocumentSpreadsheet:
396     {
397       return "document spreadsheet";
398     }
399     case Role::DocumentPresentation:
400     {
401       return "document presentation";
402     }
403     case Role::DocumentText:
404     {
405       return "document text";
406     }
407     case Role::DocumentWeb:
408     {
409       return "document web";
410     }
411     case Role::DocumentEmail:
412     {
413       return "document email";
414     }
415     case Role::Comment:
416     {
417       return "comment";
418     }
419     case Role::ListBox:
420     {
421       return "list box";
422     }
423     case Role::Grouping:
424     {
425       return "grouping";
426     }
427     case Role::ImageMap:
428     {
429       return "image map";
430     }
431     case Role::Notification:
432     {
433       return "notification";
434     }
435     case Role::InfoBar:
436     {
437       return "info bar";
438     }
439     case Role::LevelBar:
440     {
441       return "level bar";
442     }
443     case Role::TitleBar:
444     {
445       return "title bar";
446     }
447     case Role::BlockQuote:
448     {
449       return "block quote";
450     }
451     case Role::Audio:
452     {
453       return "audio";
454     }
455     case Role::Video:
456     {
457       return "video";
458     }
459     case Role::Definition:
460     {
461       return "definition";
462     }
463     case Role::Article:
464     {
465       return "article";
466     }
467     case Role::Landmark:
468     {
469       return "landmark";
470     }
471     case Role::Log:
472     {
473       return "log";
474     }
475     case Role::Marquee:
476     {
477       return "marquee";
478     }
479     case Role::Math:
480     {
481       return "math";
482     }
483     case Role::Rating:
484     {
485       return "rating";
486     }
487     case Role::Timer:
488     {
489       return "timer";
490     }
491     case Role::Static:
492     {
493       return "static";
494     }
495     case Role::MathFraction:
496     {
497       return "math fraction";
498     }
499     case Role::MathRoot:
500     {
501       return "math root";
502     }
503     case Role::Subscript:
504     {
505       return "subscript";
506     }
507     case Role::Superscript:
508     {
509       return "superscript";
510     }
511     case Role::_Count:
512     {
513       break;
514     }
515   }
516   return "";
517 }
518
519 void Bridge::SetIsOnRootLevel( Accessible* o )
520 {
521   o->isOnRootLevel = true;
522 }
523
524 class NonControlAccessible : public virtual Accessible, public virtual Collection
525 {
526 public:
527   Dali::Actor actor;
528   bool root = false;
529
530   NonControlAccessible( Dali::Actor actor ) : actor( actor )
531   {
532     Dali::Stage stage = Dali::Stage::GetCurrent();
533     root = stage.GetRootLayer() == actor;
534   }
535
536   std::string GetName() override
537   {
538     return actor.GetName();
539   }
540   std::string GetDescription() override
541   {
542     return "";
543   }
544   Accessible* GetParent() override
545   {
546     if( GetIsOnRootLevel() )
547     {
548       auto b = GetBridgeData();
549       return b->bridge->GetApplication();
550     }
551     return Get( actor.GetParent() );
552   }
553   size_t GetChildCount() override
554   {
555     return static_cast< size_t >( actor.GetChildCount() );
556   }
557   Accessible* GetChildAtIndex( size_t index ) override
558   {
559     auto s = static_cast< size_t >( actor.GetChildCount() );
560     if( index >= s )
561       throw AccessibleError{"invalid index " + std::to_string( index ) + " for object with " + std::to_string( s ) + " children"};
562     return Get( actor.GetChildAt( static_cast< unsigned int >( index ) ) );
563   }
564   size_t GetIndexInParent() override
565   {
566     auto p = actor.GetParent();
567     if( !p )
568       return 0;
569     auto s = static_cast< size_t >( p.GetChildCount() );
570     for( auto i = 0u; i < s; ++i )
571     {
572       if( p.GetChildAt( i ) == actor )
573         return i;
574     }
575     throw AccessibleError{"actor is not a child of it's parent"};
576   }
577   Role GetRole() override
578   {
579     return root ? Role::Window : Role::RedundantObject;
580   }
581   States GetStates() override
582   {
583     States s;
584     if( root )
585     {
586       s[State::Highlightable] = true;
587       s[State::Enabled] = true;
588       s[State::Sensitive] = true;
589       s[State::Showing] = true;
590       s[State::Active] = true;
591     }
592     else
593     {
594       auto t = GetParent()->GetStates();
595       s[State::Showing] = t[State::Showing];
596       s[State::Visible] = t[State::Visible];
597     }
598     return s;
599   }
600   Attributes GetAttributes() override
601   {
602     Dali::TypeInfo type;
603     actor.GetTypeInfo( type );
604     return {
605         {"t", type.GetName()},
606     };
607   }
608 };
609
610 using NonControlAccessiblesType = std::unordered_map< const Dali::RefObject*, std::unique_ptr< NonControlAccessible > >;
611 static NonControlAccessiblesType nonControlAccessibles;
612
613 static std::function< Accessible*( Dali::Actor ) > convertingFunctor = []( Dali::Actor ) -> Accessible* {
614   return nullptr;
615 };
616
617 void Accessible::RegisterControlAccessibilityGetter( std::function< Accessible*( Dali::Actor ) > functor )
618 {
619   convertingFunctor = functor;
620 }
621
622 Accessible* Accessible::Get( Dali::Actor actor )
623 {
624   if( !actor )
625   {
626     return nullptr;
627   }
628   auto p = convertingFunctor( actor );
629   if( !p )
630   {
631     if( nonControlAccessibles.empty() )
632     {
633       auto registry = Dali::Stage::GetCurrent().GetObjectRegistry();
634       registry.ObjectDestroyedSignal().Connect( []( const Dali::RefObject* obj ) {
635         nonControlAccessibles.erase( obj );
636       } );
637     }
638     auto it = nonControlAccessibles.emplace( &actor.GetBaseObject(), nullptr );
639     if( it.second )
640     {
641       it.first->second.reset( new NonControlAccessible( actor ) );
642     }
643     p = it.first->second.get();
644   }
645   return p;
646 }