Revert "[Tizen](ATSPI) Fix Native TC fails"
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / accessibility-impl.cpp
1 /*
2  * Copyright 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 // CLASS HEADER
18
19 // EXTERNAL INCLUDES
20 #include <dali/integration-api/debug.h>
21 #include <dali/public-api/actors/actor.h>
22 #include <dali/public-api/actors/layer.h>
23 #include <dali/public-api/common/stage.h>
24 #include <dali/public-api/object/base-object.h>
25 #include <dali/public-api/object/object-registry.h>
26 #include <dali/public-api/object/type-info.h>
27 #include <dali/public-api/object/type-registry-helper.h>
28 #include <dali/devel-api/actors/actor-devel.h>
29
30 // INTERNAL INCLUDES
31 #include <dali/public-api/dali-adaptor-common.h>
32 #include <dali/devel-api/adaptor-framework/accessibility.h>
33
34 using namespace Dali::Accessibility;
35 using namespace Dali;
36
37 const std::string& Dali::Accessibility::Address::GetBus() const
38 {
39   return bus.empty() && Bridge::GetCurrentBridge() ? Bridge::GetCurrentBridge()->GetBusName() : bus;
40 }
41
42 std::string EmptyAccessibleWithAddress::GetRoleName()
43 {
44   return "";
45 }
46
47 std::string Accessible::GetLocalizedRoleName()
48 {
49   return GetRoleName();
50 }
51
52 std::string Accessible::GetRoleName()
53 {
54   switch( GetRole() )
55   {
56     case Role::INVALID:
57     {
58       return "invalid";
59     }
60     case Role::ACCELERATOR_LABEL:
61     {
62       return "accelerator label";
63     }
64     case Role::ALERT:
65     {
66       return "alert";
67     }
68     case Role::ANIMATION:
69     {
70       return "animation";
71     }
72     case Role::ARROW:
73     {
74       return "arrow";
75     }
76     case Role::CALENDAR:
77     {
78       return "calendar";
79     }
80     case Role::CANVAS:
81     {
82       return "canvas";
83     }
84     case Role::CHECK_BOX:
85     {
86       return "check box";
87     }
88     case Role::CHECK_MENU_ITEM:
89     {
90       return "check menu item";
91     }
92     case Role::COLOR_CHOOSER:
93     {
94       return "color chooser";
95     }
96     case Role::COLUMN_HEADER:
97     {
98       return "column header";
99     }
100     case Role::COMBO_BOX:
101     {
102       return "combo box";
103     }
104     case Role::DATE_EDITOR:
105     {
106       return "date editor";
107     }
108     case Role::DESKTOP_ICON:
109     {
110       return "desktop icon";
111     }
112     case Role::DESKTOP_FRAME:
113     {
114       return "desktop frame";
115     }
116     case Role::DIAL:
117     {
118       return "dial";
119     }
120     case Role::DIALOG:
121     {
122       return "dialog";
123     }
124     case Role::DIRECTORY_PANE:
125     {
126       return "directory pane";
127     }
128     case Role::DRAWING_AREA:
129     {
130       return "drawing area";
131     }
132     case Role::FILE_CHOOSER:
133     {
134       return "file chooser";
135     }
136     case Role::FILLER:
137     {
138       return "filler";
139     }
140     case Role::FOCUS_TRAVERSABLE:
141     {
142       return "focus traversable";
143     }
144     case Role::FONT_CHOOSER:
145     {
146       return "font chooser";
147     }
148     case Role::FRAME:
149     {
150       return "frame";
151     }
152     case Role::GLASS_PANE:
153     {
154       return "glass pane";
155     }
156     case Role::HTML_CONTAINER:
157     {
158       return "html container";
159     }
160     case Role::ICON:
161     {
162       return "icon";
163     }
164     case Role::IMAGE:
165     {
166       return "image";
167     }
168     case Role::INTERNAL_FRAME:
169     {
170       return "internal frame";
171     }
172     case Role::LABEL:
173     {
174       return "label";
175     }
176     case Role::LAYERED_PANE:
177     {
178       return "layered pane";
179     }
180     case Role::LIST:
181     {
182       return "list";
183     }
184     case Role::LIST_ITEM:
185     {
186       return "list item";
187     }
188     case Role::MENU:
189     {
190       return "menu";
191     }
192     case Role::MENU_BAR:
193     {
194       return "menu bar";
195     }
196     case Role::MENU_ITEM:
197     {
198       return "menu item";
199     }
200     case Role::OPTION_PANE:
201     {
202       return "option pane";
203     }
204     case Role::PAGE_TAB:
205     {
206       return "page tab";
207     }
208     case Role::PAGE_TAB_LIST:
209     {
210       return "page tab list";
211     }
212     case Role::PANEL:
213     {
214       return "panel";
215     }
216     case Role::PASSWORD_TEXT:
217     {
218       return "password text";
219     }
220     case Role::POPUP_MENU:
221     {
222       return "popup menu";
223     }
224     case Role::PROGRESS_BAR:
225     {
226       return "progress bar";
227     }
228     case Role::PUSH_BUTTON:
229     {
230       return "push button";
231     }
232     case Role::RADIO_BUTTON:
233     {
234       return "radio button";
235     }
236     case Role::RADIO_MENU_ITEM:
237     {
238       return "radio menu item";
239     }
240     case Role::ROOT_PANE:
241     {
242       return "root pane";
243     }
244     case Role::ROW_HEADER:
245     {
246       return "row header";
247     }
248     case Role::SCROLL_BAR:
249     {
250       return "scroll bar";
251     }
252     case Role::SCROLL_PANE:
253     {
254       return "scroll pane";
255     }
256     case Role::SEPARATOR:
257     {
258       return "separator";
259     }
260     case Role::SLIDER:
261     {
262       return "slider";
263     }
264     case Role::SPIN_BUTTON:
265     {
266       return "spin button";
267     }
268     case Role::SPLIT_PANE:
269     {
270       return "split pane";
271     }
272     case Role::STATUS_BAR:
273     {
274       return "status bar";
275     }
276     case Role::TABLE:
277     {
278       return "table";
279     }
280     case Role::TABLE_CELL:
281     {
282       return "table cell";
283     }
284     case Role::TABLE_COLUMN_HEADER:
285     {
286       return "table column header";
287     }
288     case Role::TABLE_ROW_HEADER:
289     {
290       return "table row header";
291     }
292     case Role::TEAROFF_MENU_ITEM:
293     {
294       return "tearoff menu item";
295     }
296     case Role::TERMINAL:
297     {
298       return "terminal";
299     }
300     case Role::TEXT:
301     {
302       return "text";
303     }
304     case Role::TOGGLE_BUTTON:
305     {
306       return "toggle button";
307     }
308     case Role::TOOL_BAR:
309     {
310       return "tool bar";
311     }
312     case Role::TOOL_TIP:
313     {
314       return "tool tip";
315     }
316     case Role::TREE:
317     {
318       return "tree";
319     }
320     case Role::TREE_TABLE:
321     {
322       return "tree table";
323     }
324     case Role::UNKNOWN:
325     {
326       return "unknown";
327     }
328     case Role::VIEWPORT:
329     {
330       return "viewport";
331     }
332     case Role::WINDOW:
333     {
334       return "window";
335     }
336     case Role::EXTENDED:
337     {
338       return "extended";
339     }
340     case Role::HEADER:
341     {
342       return "header";
343     }
344     case Role::FOOTER:
345     {
346       return "footer";
347     }
348     case Role::PARAGRAPH:
349     {
350       return "paragraph";
351     }
352     case Role::RULER:
353     {
354       return "ruler";
355     }
356     case Role::APPLICATION:
357     {
358       return "application";
359     }
360     case Role::AUTOCOMPLETE:
361     {
362       return "autocomplete";
363     }
364     case Role::EDITBAR:
365     {
366       return "edit bar";
367     }
368     case Role::EMBEDDED:
369     {
370       return "embedded";
371     }
372     case Role::ENTRY:
373     {
374       return "entry";
375     }
376     case Role::CHART:
377     {
378       return "chart";
379     }
380     case Role::CAPTION:
381     {
382       return "caution";
383     }
384     case Role::DOCUMENT_FRAME:
385     {
386       return "document frame";
387     }
388     case Role::HEADING:
389     {
390       return "heading";
391     }
392     case Role::PAGE:
393     {
394       return "page";
395     }
396     case Role::SECTION:
397     {
398       return "section";
399     }
400     case Role::REDUNDANT_OBJECT:
401     {
402       return "redundant object";
403     }
404     case Role::FORM:
405     {
406       return "form";
407     }
408     case Role::LINK:
409     {
410       return "link";
411     }
412     case Role::INPUT_METHOD_WINDOW:
413     {
414       return "input method window";
415     }
416     case Role::TABLE_ROW:
417     {
418       return "table row";
419     }
420     case Role::TREE_ITEM:
421     {
422       return "tree item";
423     }
424     case Role::DOCUMENT_SPREADSHEET:
425     {
426       return "document spreadsheet";
427     }
428     case Role::DOCUMENT_PRESENTATION:
429     {
430       return "document presentation";
431     }
432     case Role::DOCUMENT_TEXT:
433     {
434       return "document text";
435     }
436     case Role::DOCUMENT_WEB:
437     {
438       return "document web";
439     }
440     case Role::DOCUMENT_EMAIL:
441     {
442       return "document email";
443     }
444     case Role::COMMENT:
445     {
446       return "comment";
447     }
448     case Role::LIST_BOX:
449     {
450       return "list box";
451     }
452     case Role::GROUPING:
453     {
454       return "grouping";
455     }
456     case Role::IMAGE_MAP:
457     {
458       return "image map";
459     }
460     case Role::NOTIFICATION:
461     {
462       return "notification";
463     }
464     case Role::INFO_BAR:
465     {
466       return "info bar";
467     }
468     case Role::LEVEL_BAR:
469     {
470       return "level bar";
471     }
472     case Role::TITLE_BAR:
473     {
474       return "title bar";
475     }
476     case Role::BLOCK_QUOTE:
477     {
478       return "block quote";
479     }
480     case Role::AUDIO:
481     {
482       return "audio";
483     }
484     case Role::VIDEO:
485     {
486       return "video";
487     }
488     case Role::DEFINITION:
489     {
490       return "definition";
491     }
492     case Role::ARTICLE:
493     {
494       return "article";
495     }
496     case Role::LANDMARK:
497     {
498       return "landmark";
499     }
500     case Role::LOG:
501     {
502       return "log";
503     }
504     case Role::MARQUEE:
505     {
506       return "marquee";
507     }
508     case Role::MATH:
509     {
510       return "math";
511     }
512     case Role::RATING:
513     {
514       return "rating";
515     }
516     case Role::TIMER:
517     {
518       return "timer";
519     }
520     case Role::STATIC:
521     {
522       return "static";
523     }
524     case Role::MATH_FRACTION:
525     {
526       return "math fraction";
527     }
528     case Role::MATH_ROOT:
529     {
530       return "math root";
531     }
532     case Role::SUBSCRIPT:
533     {
534       return "subscript";
535     }
536     case Role::SUPERSCRIPT:
537     {
538       return "superscript";
539     }
540     case Role::_COUNT:
541     {
542       break;
543     }
544   }
545   return "";
546 }
547
548 Dali::Actor Accessible::GetCurrentlyHighlightedActor()
549 {
550   return IsUp() ? Bridge::GetCurrentBridge()->data->currentlyHighlightedActor : Dali::Actor{};
551 }
552
553 void Accessible::SetCurrentlyHighlightedActor(Dali::Actor actor)
554 {
555   if (IsUp()) {
556     Bridge::GetCurrentBridge()->data->currentlyHighlightedActor = actor;
557   }
558 }
559
560 Dali::Actor Accessible::GetHighlightActor()
561 {
562   return IsUp() ? Bridge::GetCurrentBridge()->data->highlightActor : Dali::Actor{};
563 }
564
565 void Accessible::SetHighlightActor(Dali::Actor actor)
566 {
567   if (IsUp()) {
568     Bridge::GetCurrentBridge()->data->highlightActor = actor;
569   }
570 }
571
572 void Bridge::ForceDown()
573 {
574   auto highlighted = Accessible::GetCurrentlyHighlightedActor();
575   if( highlighted )
576   {
577     auto p = dynamic_cast< Component* >( Accessible::Get( highlighted ) );
578     if( p )
579       p->ClearHighlight();
580   }
581   data = {};
582 }
583
584 void Bridge::SetIsOnRootLevel( Accessible* o )
585 {
586   o->isOnRootLevel = true;
587 }
588
589 class NonControlAccessible : public virtual Accessible, public virtual Collection, public virtual Component
590 {
591 public:
592   Dali::Actor actor;
593   bool root = false;
594
595   NonControlAccessible( Dali::Actor actor, bool root ) : actor( actor ), root( root )
596   {
597   }
598
599   Dali::Rect<> GetExtents( Dali::Accessibility::CoordType ctype ) override
600   {
601     Vector2 screenPosition = actor.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION ).Get< Vector2 >();
602     Vector3 size = actor.GetCurrentSize() * actor.GetCurrentWorldScale();
603     bool positionUsesAnchorPoint =
604         actor.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
605             .Get< bool >();
606     Vector3 anchorPointOffSet =
607         size * ( positionUsesAnchorPoint ? actor.GetCurrentAnchorPoint()
608                                         : AnchorPoint::TOP_LEFT );
609     Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
610                                 screenPosition.y - anchorPointOffSet.y );
611
612     return { position.x, position.y, size.x, size.y };
613   }
614   Dali::Accessibility::ComponentLayer GetLayer() override
615   {
616     return Dali::Accessibility::ComponentLayer::WINDOW;
617   }
618   int16_t GetMdiZOrder()
619   {
620     return 0;
621   }
622   double GetAlpha()
623   {
624     return 0;
625   }
626   bool GrabFocus() override
627   {
628     return false;
629   }
630   bool GrabHighlight() override
631   {
632     return false;
633   }
634   bool ClearHighlight() override
635   {
636     return false;
637   }
638   int GetHighlightIndex() override
639   {
640     return 0;
641   }
642   bool IsScrollable() override
643   {
644     return false;
645   }
646   std::string GetName() override
647   {
648     return actor.GetName();
649   }
650   std::string GetDescription() override
651   {
652     return "";
653   }
654   Accessible* GetParent() override
655   {
656     if( GetIsOnRootLevel() )
657     {
658       auto b = GetBridgeData();
659       return b->bridge->GetApplication();
660     }
661     return Get( actor.GetParent() );
662   }
663   size_t GetChildCount() override
664   {
665     return static_cast< size_t >( actor.GetChildCount() );
666   }
667   Accessible* GetChildAtIndex( size_t index ) override
668   {
669     auto s = static_cast< size_t >( actor.GetChildCount() );
670     if( index >= s )
671       throw std::domain_error{"invalid index " + std::to_string( index ) + " for object with " + std::to_string( s ) + " children"};
672     return Get( actor.GetChildAt( static_cast< unsigned int >( index ) ) );
673   }
674   size_t GetIndexInParent() override
675   {
676     auto p = actor.GetParent();
677     if( !p )
678       return 0;
679     auto s = static_cast< size_t >( p.GetChildCount() );
680     for( auto i = 0u; i < s; ++i )
681     {
682       if( p.GetChildAt( i ) == actor )
683         return i;
684     }
685     throw std::domain_error{"actor is not a child of it's parent"};
686   }
687   Role GetRole() override
688   {
689     return root ? Role::WINDOW : Role::REDUNDANT_OBJECT;
690   }
691   States GetStates() override
692   {
693     States s;
694     if( root )
695     {
696       s[State::HIGHLIGHTABLE] = true;
697       s[State::ENABLED] = true;
698       s[State::SENSITIVE] = true;
699       s[State::SHOWING] = true;
700       s[State::VISIBLE] = true;
701       s[State::ACTIVE] = true;
702     }
703     else
704     {
705       auto t = GetParent()->GetStates();
706       s[State::SHOWING] = t[State::SHOWING];
707       s[State::VISIBLE] = t[State::VISIBLE];
708     }
709     return s;
710   }
711   Attributes GetAttributes() override
712   {
713     Dali::TypeInfo type;
714     actor.GetTypeInfo( type );
715     return {
716         {"t", type.GetName()},
717     };
718   }
719   bool DoGesture(const GestureInfo &gestureInfo) override
720   {
721       return false;
722   }
723   std::vector<Relation> GetRelationSet() override
724   {
725       return {};
726   }
727 };
728
729 using NonControlAccessiblesType = std::unordered_map< const Dali::RefObject*, std::unique_ptr< NonControlAccessible > >;
730 static NonControlAccessiblesType nonControlAccessibles;
731
732 static std::function< Accessible*( Dali::Actor ) > convertingFunctor = []( Dali::Actor ) -> Accessible* {
733   return nullptr;
734 };
735
736 void Accessible::RegisterControlAccessibilityGetter( std::function< Accessible*( Dali::Actor ) > functor )
737 {
738   convertingFunctor = functor;
739 }
740
741 Accessible* Accessible::Get( Dali::Actor actor, bool root )
742 {
743   if( !actor )
744   {
745     return nullptr;
746   }
747   auto p = convertingFunctor( actor );
748   if( !p )
749   {
750     if( nonControlAccessibles.empty() )
751     {
752       auto registry = Dali::Stage::GetCurrent().GetObjectRegistry();
753       registry.ObjectDestroyedSignal().Connect( []( const Dali::RefObject* obj ) {
754         nonControlAccessibles.erase( obj );
755       } );
756     }
757     auto it = nonControlAccessibles.emplace( &actor.GetBaseObject(), nullptr );
758     if( it.second )
759     {
760       it.first->second.reset( new NonControlAccessible( actor, root ) );
761     }
762     p = it.first->second.get();
763   }
764   return p;
765 }