e667a6c8f7dad88e0c1c12c30c1b5e493503fca2
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / accessibility-manager / accessibility-manager-impl.cpp
1 /*
2  * Copyright (c) 2020 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 "accessibility-manager-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/actors/layer.h>
24 #include <dali/devel-api/adaptor-framework/accessibility-adaptor.h>
25 #include <dali/devel-api/adaptor-framework/sound-player.h>
26 #include <dali/public-api/animation/constraints.h>
27 #include <dali/devel-api/events/hit-test-algorithm.h>
28 #include <dali/devel-api/events/pan-gesture-devel.h>
29 #include <dali/integration-api/debug.h>
30
31 // INTERNAL INCLUDES
32 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
33 #include <dali-toolkit/public-api/controls/control.h>
34 #include <dali-toolkit/public-api/controls/control-impl.h>
35 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
36
37 namespace Dali
38 {
39
40 namespace Toolkit
41 {
42
43 namespace Internal
44 {
45
46 namespace // unnamed namespace
47 {
48
49 // Signals
50
51 const char* const SIGNAL_FOCUS_CHANGED =           "focusChanged";
52 const char* const SIGNAL_FOCUS_OVERSHOT =          "focusOvershot";
53 const char* const SIGNAL_FOCUSED_ACTOR_ACTIVATED = "focusedActorActivated";
54
55 #if defined(DEBUG_ENABLED)
56 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FOCUS_MANAGER");
57 #endif
58
59 const char* const ACTOR_FOCUSABLE("focusable");
60 const char* const IS_FOCUS_GROUP("isFocusGroup");
61
62 const char* FOCUS_BORDER_IMAGE_FILE_NAME = "B16-8_TTS_focus.9.png";
63
64 const char* FOCUS_SOUND_FILE_NAME = "Focus.ogg";
65 const char* FOCUS_CHAIN_END_SOUND_FILE_NAME = "End_of_List.ogg";
66
67 /**
68  * The function to be used in the hit-test algorithm to check whether the actor is hittable.
69  */
70 bool IsActorFocusableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
71 {
72   bool hittable = false;
73
74   switch (type)
75   {
76     case Dali::HitTestAlgorithm::CHECK_ACTOR:
77     {
78       // Check whether the actor is visible and not fully transparent.
79       if( actor.GetCurrentProperty< bool >( Actor::Property::VISIBLE )
80        && actor.GetCurrentProperty< Vector4 >( Actor::Property::WORLD_COLOR ).a > 0.01f) // not FULLY_TRANSPARENT
81       {
82         // Check whether the actor is focusable
83         Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
84         if(propertyActorFocusable != Property::INVALID_INDEX)
85         {
86           hittable = actor.GetProperty<bool>(propertyActorFocusable);
87         }
88       }
89       break;
90     }
91     case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
92     {
93       if( actor.GetCurrentProperty< bool >( Actor::Property::VISIBLE ) ) // Actor is visible, if not visible then none of its children are visible.
94       {
95         hittable = true;
96       }
97       break;
98     }
99     default:
100     {
101       break;
102     }
103   }
104
105   return hittable;
106 };
107
108 }
109
110 AccessibilityManager::AccessibilityManager()
111 : mCurrentFocusActor(FocusIDPair(0, 0)),
112   mCurrentGesturedActor(),
113   mFocusIndicatorActor(),
114   mPreviousPosition( 0.0f, 0.0f ),
115   mRecursiveFocusMoveCounter(0),
116   mFocusSoundFilePath(),
117   mFocusChainEndSoundFilePath(),
118   mIsWrapped(false),
119   mIsFocusWithinGroup(false),
120   mIsEndcapFeedbackEnabled(false),
121   mIsEndcapFeedbackPlayed(false),
122   mIsAccessibilityTtsEnabled(false),
123   mTtsCreated(false),
124   mIsFocusIndicatorEnabled(false),
125   mContinuousPlayMode(false),
126   mIsFocusSoundFilePathSet(false),
127   mIsFocusChainEndSoundFilePathSet(false)
128 {
129 }
130
131 AccessibilityManager::~AccessibilityManager()
132 {
133 }
134
135 void AccessibilityManager::Initialise()
136 {
137   AccessibilityAdaptor adaptor = AccessibilityAdaptor::Get();
138   adaptor.SetActionHandler(*this);
139   adaptor.SetGestureHandler(*this);
140
141   ChangeAccessibilityStatus();
142 }
143
144 AccessibilityManager::ActorAdditionalInfo AccessibilityManager::GetActorAdditionalInfo(const unsigned int actorID) const
145 {
146   ActorAdditionalInfo data;
147   IDAdditionalInfoConstIter iter = mIDAdditionalInfoContainer.find(actorID);
148   if(iter != mIDAdditionalInfoContainer.end())
149   {
150     data = (*iter).second;
151   }
152
153   return data;
154 }
155
156 void AccessibilityManager::SynchronizeActorAdditionalInfo(const unsigned int actorID, const unsigned int order)
157 {
158   ActorAdditionalInfo actorInfo = GetActorAdditionalInfo(actorID);
159   actorInfo.mFocusOrder = order;
160   mIDAdditionalInfoContainer.erase(actorID);
161   mIDAdditionalInfoContainer.insert(IDAdditionalInfoPair(actorID, actorInfo));
162 }
163
164 void AccessibilityManager::SetAccessibilityAttribute(Actor actor, Toolkit::AccessibilityManager::AccessibilityAttribute type, const std::string& text)
165 {
166   if(actor)
167   {
168     unsigned int actorID = actor.GetProperty< int >( Actor::Property::ID );
169
170     ActorAdditionalInfo info = GetActorAdditionalInfo(actorID);
171     info.mAccessibilityAttributes[type] = text;
172
173     mIDAdditionalInfoContainer.erase(actorID);
174     mIDAdditionalInfoContainer.insert(IDAdditionalInfoPair(actorID, info));
175   }
176 }
177
178 std::string AccessibilityManager::GetAccessibilityAttribute(Actor actor, Toolkit::AccessibilityManager::AccessibilityAttribute type) const
179 {
180   std::string text;
181
182   if(actor)
183   {
184     ActorAdditionalInfo data = GetActorAdditionalInfo(actor.GetProperty< int >( Actor::Property::ID ));
185     text = data.mAccessibilityAttributes[type];
186   }
187
188   return text;
189 }
190
191 void AccessibilityManager::SetFocusOrder(Actor actor, const unsigned int order)
192 {
193   // Do nothing if the focus order of the actor is not changed.
194   if(actor && GetFocusOrder(actor) != order)
195   {
196     // Firstly delete the actor from the focus chain if it's already there with a different focus order.
197     mFocusIDContainer.erase(GetFocusOrder(actor));
198
199     // Create/retrieve actor focusable property
200     Property::Index propertyActorFocusable = actor.RegisterProperty( ACTOR_FOCUSABLE, true, Property::READ_WRITE );
201
202     if(order == 0)
203     {
204       // The actor is not focusable without a defined focus order.
205       actor.SetProperty(propertyActorFocusable, false);
206
207       // If the actor is currently being focused, it should clear the focus
208       if(actor == GetCurrentFocusActor())
209       {
210         ClearFocus();
211       }
212     }
213     else // Insert the actor to the focus chain
214     {
215       // Check whether there is another actor in the focus chain with the same focus order already.
216       FocusIDIter focusIDIter = mFocusIDContainer.find(order);
217       if(focusIDIter != mFocusIDContainer.end())
218       {
219         // We need to increase the focus order of that actor and all the actors followed it
220         // in the focus chain.
221         FocusIDIter lastIter = mFocusIDContainer.end();
222         --lastIter;//We want forward iterator to the last element here
223         mFocusIDContainer.insert(FocusIDPair((*lastIter).first + 1, (*lastIter).second));
224
225         // Update the actor's focus order in its additional data
226         SynchronizeActorAdditionalInfo((*lastIter).second, (*lastIter).first + 1);
227
228         for(FocusIDIter iter = lastIter; iter != focusIDIter; iter--)
229         {
230           FocusIDIter previousIter = iter;
231           --previousIter;//We want forward iterator to the previous element here
232           unsigned int actorID = (*previousIter).second;
233           (*iter).second = actorID;
234
235           // Update the actor's focus order in its additional data
236           SynchronizeActorAdditionalInfo(actorID, (*iter).first);
237         }
238
239         mFocusIDContainer.erase(order);
240       }
241
242       // The actor is focusable
243       actor.SetProperty(propertyActorFocusable, true);
244
245       // Now we insert the actor into the focus chain with the specified focus order
246       mFocusIDContainer.insert(FocusIDPair(order, actor.GetProperty< int >( Actor::Property::ID )));
247     }
248
249     // Update the actor's focus order in its additional data
250     SynchronizeActorAdditionalInfo(actor.GetProperty< int >( Actor::Property::ID ), order);
251   }
252 }
253
254 unsigned int AccessibilityManager::GetFocusOrder(Actor actor) const
255 {
256   unsigned int focusOrder = 0;
257
258   if(actor)
259   {
260     ActorAdditionalInfo data = GetActorAdditionalInfo(actor.GetProperty< int >( Actor::Property::ID ));
261     focusOrder = data.mFocusOrder;
262   }
263
264   return focusOrder;
265 }
266
267 unsigned int AccessibilityManager::GenerateNewFocusOrder() const
268 {
269   unsigned int order = 1;
270   FocusIDContainer::const_reverse_iterator iter = mFocusIDContainer.rbegin();
271
272   if(iter != mFocusIDContainer.rend())
273   {
274     order = (*iter).first + 1;
275   }
276
277   return order;
278 }
279
280 Actor AccessibilityManager::GetActorByFocusOrder(const unsigned int order)
281 {
282   Actor actor = Actor();
283
284   FocusIDIter focusIDIter = mFocusIDContainer.find(order);
285   if(focusIDIter != mFocusIDContainer.end())
286   {
287     Actor rootActor = Stage::GetCurrent().GetRootLayer();
288     actor = rootActor.FindChildById(mFocusIDContainer[order]);
289   }
290
291   return actor;
292 }
293
294 bool AccessibilityManager::SetCurrentFocusActor(Actor actor)
295 {
296   if(actor)
297   {
298     return DoSetCurrentFocusActor(actor.GetProperty< int >( Actor::Property::ID ));
299   }
300
301   return false;
302 }
303
304 bool AccessibilityManager::DoSetCurrentFocusActor(const unsigned int actorID)
305 {
306   Actor rootActor = Stage::GetCurrent().GetRootLayer();
307
308   // If the group mode is enabled, check which focus group the current focused actor belongs to
309   Actor focusGroup;
310   if(mIsFocusWithinGroup)
311   {
312     focusGroup = GetFocusGroup(GetCurrentFocusActor());
313   }
314
315   if(!focusGroup)
316   {
317     focusGroup = rootActor;
318   }
319
320   Actor actor = focusGroup.FindChildById(actorID);
321
322   // Check whether the actor is in the stage
323   if(actor)
324   {
325     // Check whether the actor is focusable
326     bool actorFocusable = false;
327     Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
328     if(propertyActorFocusable != Property::INVALID_INDEX)
329     {
330       actorFocusable = actor.GetProperty<bool>(propertyActorFocusable);
331     }
332
333     // Go through the actor's hierarchy to check whether the actor is visible
334     bool actorVisible = actor.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
335     Actor parent = actor.GetParent();
336     while (actorVisible && parent && parent != rootActor)
337     {
338       actorVisible = parent.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
339       parent = parent.GetParent();
340     }
341
342     // Check whether the actor is fully transparent
343     bool actorOpaque = actor.GetCurrentProperty< Vector4 >( Actor::Property::WORLD_COLOR ).a > 0.01f;
344
345     // Set the focus only when the actor is focusable and visible and not fully transparent
346     if(actorVisible && actorFocusable && actorOpaque)
347     {
348       // Draw the focus indicator upon the focused actor
349       if( mIsFocusIndicatorEnabled )
350       {
351         actor.Add( GetFocusIndicatorActor() );
352       }
353
354       // Send notification for the change of focus actor
355       mFocusChangedSignal.Emit( GetCurrentFocusActor(), actor );
356
357       // Save the current focused actor
358       mCurrentFocusActor = FocusIDPair(GetFocusOrder(actor), actorID);
359
360       if(mIsAccessibilityTtsEnabled)
361       {
362         Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
363         if(soundPlayer)
364         {
365           if (!mIsFocusSoundFilePathSet)
366           {
367             const std::string soundDirPath = AssetManager::GetDaliSoundPath();
368             mFocusSoundFilePath = soundDirPath + FOCUS_SOUND_FILE_NAME;
369             mIsFocusSoundFilePathSet = true;
370           }
371           soundPlayer.PlaySound(mFocusSoundFilePath);
372         }
373
374         // Play the accessibility attributes with the TTS player.
375         Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
376
377         // Combine attribute texts to one text
378         std::string informationText;
379         for(int i = 0; i < Toolkit::AccessibilityManager::ACCESSIBILITY_ATTRIBUTE_NUM; i++)
380         {
381           if(!GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i].empty())
382           {
383             if( i > 0 )
384             {
385               informationText += ", "; // for space time between each information
386             }
387             informationText += GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i];
388           }
389         }
390         player.Play(informationText);
391       }
392
393       return true;
394     }
395   }
396
397   DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
398   return false;
399 }
400
401 Actor AccessibilityManager::GetCurrentFocusActor()
402 {
403   Actor rootActor = Stage::GetCurrent().GetRootLayer();
404   return rootActor.FindChildById(mCurrentFocusActor.second);
405 }
406
407 Actor AccessibilityManager::GetCurrentFocusGroup()
408 {
409   return GetFocusGroup(GetCurrentFocusActor());
410 }
411
412 unsigned int AccessibilityManager::GetCurrentFocusOrder()
413 {
414   return mCurrentFocusActor.first;
415 }
416
417 bool AccessibilityManager::MoveFocusForward()
418 {
419   bool ret = false;
420   mRecursiveFocusMoveCounter = 0;
421
422   FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
423   if(focusIDIter != mFocusIDContainer.end())
424   {
425     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
426     ret = DoMoveFocus(focusIDIter, true, mIsWrapped);
427   }
428   else
429   {
430     // TODO: if there is not focused actor, move first actor
431     if(!mFocusIDContainer.empty())
432     {
433       //if there is not focused actor, move 1st actor
434       focusIDIter = mFocusIDContainer.begin(); // TODO: I'm not sure it was sorted.
435       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
436       ret = DoSetCurrentFocusActor((*focusIDIter).second);
437     }
438   }
439
440   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
441
442   return ret;
443 }
444
445 bool AccessibilityManager::MoveFocusBackward()
446 {
447   bool ret = false;
448   mRecursiveFocusMoveCounter = 0;
449
450   FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
451   if(focusIDIter != mFocusIDContainer.end())
452   {
453     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
454     ret = DoMoveFocus(focusIDIter, false, mIsWrapped);
455   }
456   else
457   {
458     // TODO: if there is not focused actor, move last actor
459     if(!mFocusIDContainer.empty())
460     {
461       //if there is not focused actor, move last actor
462       focusIDIter = mFocusIDContainer.end();
463       --focusIDIter;//We want forward iterator to the last element here
464       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
465       ret = DoSetCurrentFocusActor((*focusIDIter).second);
466     }
467   }
468
469   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
470
471   return ret;
472 }
473
474 void AccessibilityManager::DoActivate(Actor actor)
475 {
476   if(actor)
477   {
478     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
479     if(control)
480     {
481       // Notify the control that it is activated
482       GetImplementation( control ).AccessibilityActivate();
483     }
484
485     // Send notification for the activation of focused actor
486     mFocusedActorActivatedSignal.Emit(actor);
487   }
488 }
489
490 void AccessibilityManager::ClearFocus()
491 {
492   Actor actor = GetCurrentFocusActor();
493   if( actor && mFocusIndicatorActor )
494   {
495     actor.Remove( mFocusIndicatorActor );
496   }
497
498   mCurrentFocusActor = FocusIDPair(0, 0);
499
500   // Send notification for the change of focus actor
501   mFocusChangedSignal.Emit(actor, Actor());
502
503   if(mIsAccessibilityTtsEnabled)
504   {
505     // Stop the TTS playing if any
506     Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
507     player.Stop();
508   }
509 }
510
511 void AccessibilityManager::Reset()
512 {
513   ClearFocus();
514   mFocusIDContainer.clear();
515   mIDAdditionalInfoContainer.clear();
516 }
517
518 void AccessibilityManager::SetFocusGroup(Actor actor, bool isFocusGroup)
519 {
520   if(actor)
521   {
522     // Create/Set focus group property.
523     actor.RegisterProperty( IS_FOCUS_GROUP, isFocusGroup, Property::READ_WRITE );
524   }
525 }
526
527 bool AccessibilityManager::IsFocusGroup(Actor actor) const
528 {
529   // Check whether the actor is a focus group
530   bool isFocusGroup = false;
531
532   if(actor)
533   {
534     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
535     if(propertyIsFocusGroup != Property::INVALID_INDEX)
536     {
537       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
538     }
539   }
540
541   return isFocusGroup;
542 }
543
544 Actor AccessibilityManager::GetFocusGroup(Actor actor)
545 {
546   // Go through the actor's hierarchy to check which focus group the actor belongs to
547   while (actor && !IsFocusGroup(actor))
548   {
549     actor = actor.GetParent();
550   }
551
552   return actor;
553 }
554
555 Vector2 AccessibilityManager::GetReadPosition() const
556 {
557   AccessibilityAdaptor adaptor = AccessibilityAdaptor::Get();
558   return adaptor.GetReadPosition();
559 }
560
561 void AccessibilityManager::EnableAccessibility(bool enabled)
562 {
563   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Set Enabled Forcibly : %d \n", __FUNCTION__, __LINE__, enabled );
564   AccessibilityAdaptor adaptor = AccessibilityAdaptor::Get();
565   adaptor.EnableAccessibility(enabled);
566 }
567
568 bool AccessibilityManager::IsEnabled() const
569 {
570   AccessibilityAdaptor adaptor = AccessibilityAdaptor::Get();
571   return adaptor.IsEnabled();
572 }
573
574 void AccessibilityManager::SetGroupMode(bool enabled)
575 {
576   mIsFocusWithinGroup = enabled;
577 }
578
579 bool AccessibilityManager::GetGroupMode() const
580 {
581   return mIsFocusWithinGroup;
582 }
583
584 void AccessibilityManager::SetWrapMode(bool wrapped)
585 {
586   mIsWrapped = wrapped;
587 }
588
589 bool AccessibilityManager::GetWrapMode() const
590 {
591   return mIsWrapped;
592 }
593
594 void AccessibilityManager::SetFocusIndicatorActor(Actor indicator)
595 {
596   if( mFocusIndicatorActor != indicator )
597   {
598     Actor currentFocusActor = GetCurrentFocusActor();
599     if( currentFocusActor )
600     {
601       // The new focus indicator should be added to the current focused actor immediately
602       if( mFocusIndicatorActor )
603       {
604         currentFocusActor.Remove( mFocusIndicatorActor );
605       }
606
607       if( indicator )
608       {
609         currentFocusActor.Add( indicator );
610       }
611     }
612
613     mFocusIndicatorActor = indicator;
614   }
615 }
616
617 Actor AccessibilityManager::GetFocusIndicatorActor()
618 {
619   if( ! mFocusIndicatorActor )
620   {
621     // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors
622     const std::string imageDirPath = AssetManager::GetDaliImagePath();
623     const std::string focusBorderImagePath = imageDirPath + FOCUS_BORDER_IMAGE_FILE_NAME;
624
625     mFocusIndicatorActor = Toolkit::ImageView::New(focusBorderImagePath);
626     mFocusIndicatorActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
627     mFocusIndicatorActor.SetProperty( Actor::Property::POSITION_Z,  1.0f );
628
629     // Apply size constraint to the focus indicator
630     mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
631   }
632
633   return mFocusIndicatorActor;
634 }
635
636 bool AccessibilityManager::DoMoveFocus(FocusIDIter focusIDIter, bool forward, bool wrapped)
637 {
638   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] %d focusable actors\n", __FUNCTION__, __LINE__, mFocusIDContainer.size());
639   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
640
641   if( (forward && ++focusIDIter == mFocusIDContainer.end())
642     || (!forward && focusIDIter-- == mFocusIDContainer.begin()) )
643   {
644     if(mIsEndcapFeedbackEnabled)
645     {
646       if(mIsEndcapFeedbackPlayed == false)
647       {
648         // play sound & skip moving once
649         Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
650         if(soundPlayer)
651         {
652           if (!mIsFocusChainEndSoundFilePathSet)
653           {
654             const std::string soundDirPath = AssetManager::GetDaliSoundPath();
655             mFocusChainEndSoundFilePath = soundDirPath + FOCUS_CHAIN_END_SOUND_FILE_NAME;
656             mIsFocusChainEndSoundFilePathSet = true;
657           }
658           soundPlayer.PlaySound(mFocusChainEndSoundFilePath);
659         }
660
661         mIsEndcapFeedbackPlayed = true;
662         return true;
663       }
664       mIsEndcapFeedbackPlayed = false;
665     }
666
667     if(wrapped)
668     {
669       if(forward)
670       {
671         focusIDIter = mFocusIDContainer.begin();
672       }
673       else
674       {
675         focusIDIter = mFocusIDContainer.end();
676         --focusIDIter;//We want forward iterator to the last element here
677       }
678     }
679     else
680     {
681       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Overshot\n", __FUNCTION__, __LINE__);
682       // Send notification for handling overshooted situation
683       mFocusOvershotSignal.Emit(GetCurrentFocusActor(), forward ? Toolkit::AccessibilityManager::OVERSHOT_NEXT : Toolkit::AccessibilityManager::OVERSHOT_PREVIOUS);
684
685       return false; // Try to move the focus out of the scope
686     }
687   }
688
689   // Invalid focus.
690   if( focusIDIter == mFocusIDContainer.end() )
691   {
692     return false;
693   }
694
695   // Note: This function performs the focus change.
696   if( !DoSetCurrentFocusActor( (*focusIDIter).second ) )
697   {
698     mRecursiveFocusMoveCounter++;
699     if(mRecursiveFocusMoveCounter > mFocusIDContainer.size())
700     {
701       // We've attempted to focus all the actors in the whole focus chain and no actor
702       // can be focused successfully.
703       DALI_LOG_WARNING("[%s] There is no more focusable actor in %d focus chains\n", __FUNCTION__, mRecursiveFocusMoveCounter);
704
705       return false;
706     }
707     else
708     {
709       return DoMoveFocus(focusIDIter, forward, wrapped);
710     }
711   }
712
713   return true;
714 }
715
716 void AccessibilityManager::SetFocusable(Actor actor, bool focusable)
717 {
718   if(actor)
719   {
720     // Create/Set actor focusable property.
721     actor.RegisterProperty( ACTOR_FOCUSABLE, focusable, Property::READ_WRITE );
722   }
723 }
724
725 bool AccessibilityManager::ChangeAccessibilityStatus()
726 {
727   AccessibilityAdaptor adaptor = AccessibilityAdaptor::Get();
728   mIsAccessibilityTtsEnabled = adaptor.IsEnabled();
729   Dali::Toolkit::AccessibilityManager handle( this );
730
731   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] TtsEnabled : %d \n", __FUNCTION__, __LINE__, mIsAccessibilityTtsEnabled );
732
733   if(mIsAccessibilityTtsEnabled)
734   {
735     // Show indicator when tts turned on if there is focused actor.
736     Actor actor = GetCurrentFocusActor();
737     if(actor)
738     {
739       actor.Add( GetFocusIndicatorActor() );
740     }
741     mIsFocusIndicatorEnabled = true;
742
743     // Connect a signal to the TTS player to implement continuous reading mode.
744     Dali::TtsPlayer player = Dali::TtsPlayer::Get( Dali::TtsPlayer::SCREEN_READER );
745     player.StateChangedSignal().Connect( this, &AccessibilityManager::TtsStateChanged );
746     mTtsCreated = true;
747   }
748   else
749   {
750     // Hide indicator when tts turned off
751     Actor actor = GetCurrentFocusActor();
752     if( actor && mFocusIndicatorActor )
753     {
754       actor.Remove( mFocusIndicatorActor );
755     }
756     mIsFocusIndicatorEnabled = false;
757
758     if( mTtsCreated )
759     {
760       // Disconnect the TTS state change signal.
761       Dali::TtsPlayer player = Dali::TtsPlayer::Get( Dali::TtsPlayer::SCREEN_READER );
762       player.StateChangedSignal().Disconnect( this, &AccessibilityManager::TtsStateChanged );
763       mTtsCreated = true;
764     }
765   }
766
767   mStatusChangedSignal.Emit( handle );
768
769   return true;
770 }
771
772 bool AccessibilityManager::AccessibilityActionNext(bool allowEndFeedback)
773 {
774   Dali::Toolkit::AccessibilityManager handle( this );
775   if( !mActionNextSignal.Empty() )
776   {
777     mActionNextSignal.Emit( handle );
778   }
779
780   if(mIsAccessibilityTtsEnabled)
781   {
782     mIsEndcapFeedbackEnabled = allowEndFeedback;
783     return MoveFocusForward();
784   }
785   else
786   {
787     return false;
788   }
789 }
790
791 bool AccessibilityManager::AccessibilityActionPrevious(bool allowEndFeedback)
792 {
793   Dali::Toolkit::AccessibilityManager handle( this );
794   if( !mActionPreviousSignal.Empty() )
795   {
796     mActionPreviousSignal.Emit( handle );
797   }
798
799   if(mIsAccessibilityTtsEnabled)
800   {
801     mIsEndcapFeedbackEnabled = allowEndFeedback;
802     return MoveFocusBackward();
803   }
804   else
805   {
806     return false;
807   }
808 }
809
810 bool AccessibilityManager::AccessibilityActionActivate()
811 {
812   Dali::Toolkit::AccessibilityManager handle( this );
813   if( !mActionActivateSignal.Empty() )
814   {
815     mActionActivateSignal.Emit( handle );
816   }
817
818   bool ret = false;
819
820   Actor actor = GetCurrentFocusActor();
821   if(actor)
822   {
823     DoActivate(actor);
824     ret = true;
825   }
826
827   return ret;
828 }
829
830 bool AccessibilityManager::AccessibilityActionRead(bool allowReadAgain)
831 {
832   Dali::Toolkit::AccessibilityManager handle( this );
833
834   if( allowReadAgain )
835   {
836     if ( !mActionReadSignal.Empty() )
837     {
838       mActionReadSignal.Emit( handle );
839     }
840   }
841   else
842   {
843     if ( !mActionOverSignal.Empty() )
844     {
845       mActionOverSignal.Emit( handle );
846     }
847   }
848
849   bool ret = false;
850
851   if(mIsAccessibilityTtsEnabled)
852   {
853     // Find the focusable actor at the read position
854     AccessibilityAdaptor adaptor = AccessibilityAdaptor::Get();
855     Dali::HitTestAlgorithm::Results results;
856     Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), adaptor.GetReadPosition(), results, IsActorFocusableFunction );
857
858     FocusIDIter focusIDIter = mFocusIDContainer.find(GetFocusOrder(results.actor));
859     if(focusIDIter != mFocusIDContainer.end())
860     {
861       if( allowReadAgain || (results.actor != GetCurrentFocusActor()) )
862       {
863         // Move the focus to the actor
864         ret = SetCurrentFocusActor(results.actor);
865         DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SetCurrentFocusActor returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
866       }
867     }
868   }
869
870   return ret;
871 }
872
873 bool AccessibilityManager::AccessibilityActionReadNext(bool allowEndFeedback)
874 {
875   Dali::Toolkit::AccessibilityManager handle( this );
876   if( !mActionReadNextSignal.Empty() )
877   {
878     mActionReadNextSignal.Emit( handle );
879   }
880
881   if(mIsAccessibilityTtsEnabled)
882   {
883     return MoveFocusForward();
884   }
885   else
886   {
887     return false;
888   }
889 }
890
891 bool AccessibilityManager::AccessibilityActionReadPrevious(bool allowEndFeedback)
892 {
893   Dali::Toolkit::AccessibilityManager handle( this );
894   if( !mActionReadPreviousSignal.Empty() )
895   {
896     mActionReadPreviousSignal.Emit( handle );
897   }
898
899   if(mIsAccessibilityTtsEnabled)
900   {
901     return MoveFocusBackward();
902   }
903   else
904   {
905     return false;
906   }
907 }
908
909 bool AccessibilityManager::AccessibilityActionUp()
910 {
911   Dali::Toolkit::AccessibilityManager handle( this );
912   if( !mActionUpSignal.Empty() )
913   {
914     mActionUpSignal.Emit( handle );
915   }
916
917   bool ret = false;
918
919   if(mIsAccessibilityTtsEnabled)
920   {
921     Actor actor = GetCurrentFocusActor();
922     if(actor)
923     {
924       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
925       if(control)
926       {
927         // Notify the control that it is activated
928         ret = GetImplementation( control ).OnAccessibilityValueChange(true);
929       }
930     }
931   }
932
933   return ret;
934 }
935
936 bool AccessibilityManager::AccessibilityActionDown()
937 {
938   Dali::Toolkit::AccessibilityManager handle( this );
939   if( !mActionDownSignal.Empty() )
940   {
941     mActionDownSignal.Emit( handle );
942   }
943
944   bool ret = false;
945
946   if(mIsAccessibilityTtsEnabled)
947   {
948     Actor actor = GetCurrentFocusActor();
949     if(actor)
950     {
951       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
952       if(control)
953       {
954         // Notify the control that it is activated
955         ret = GetImplementation( control ).OnAccessibilityValueChange(false);
956       }
957     }
958   }
959
960   return ret;
961 }
962
963 bool AccessibilityManager::ClearAccessibilityFocus()
964 {
965   Dali::Toolkit::AccessibilityManager handle( this );
966   if( !mActionClearFocusSignal.Empty() )
967   {
968     mActionClearFocusSignal.Emit( handle );
969   }
970
971   if(mIsAccessibilityTtsEnabled)
972   {
973     ClearFocus();
974     return true;
975   }
976   else
977   {
978     return false;
979   }
980 }
981
982 bool AccessibilityManager::AccessibilityActionScroll( Dali::TouchEvent& touch )
983 {
984   Dali::Toolkit::AccessibilityManager handle( this );
985   if( !mActionScrollSignal.Empty() )
986   {
987     mActionScrollSignal.Emit( handle, touch );
988   }
989
990   return true;
991 }
992
993 bool AccessibilityManager::AccessibilityActionBack()
994 {
995   Dali::Toolkit::AccessibilityManager handle( this );
996   if( !mActionBackSignal.Empty() )
997   {
998     mActionBackSignal.Emit( handle );
999   }
1000
1001   // TODO: Back to previous view
1002
1003   return mIsAccessibilityTtsEnabled;
1004 }
1005
1006 bool AccessibilityManager::AccessibilityActionScrollUp()
1007 {
1008   Dali::Toolkit::AccessibilityManager handle( this );
1009   if( !mActionScrollUpSignal.Empty() )
1010   {
1011     mActionScrollUpSignal.Emit( handle );
1012   }
1013
1014   bool ret = false;
1015
1016   if(mIsAccessibilityTtsEnabled)
1017   {
1018     Actor actor = GetCurrentFocusActor();
1019     if(actor)
1020     {
1021       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
1022       if(control)
1023       {
1024         // TODO: Notify the control to scroll up. Should control handle this?
1025 //        ret = GetImplementation( control ).OnAccessibilityScroll(Direction::UP);
1026       }
1027     }
1028   }
1029
1030   return ret;
1031 }
1032
1033 bool AccessibilityManager::AccessibilityActionScrollDown()
1034 {
1035   Dali::Toolkit::AccessibilityManager handle( this );
1036   if( !mActionScrollDownSignal.Empty() )
1037   {
1038     mActionScrollDownSignal.Emit( handle );
1039   }
1040
1041   bool ret = false;
1042
1043   if(mIsAccessibilityTtsEnabled)
1044   {
1045     Actor actor = GetCurrentFocusActor();
1046     if(actor)
1047     {
1048       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
1049       if(control)
1050       {
1051         // TODO: Notify the control to scroll down. Should control handle this?
1052 //        ret = GetImplementation( control ).OnAccessibilityScrollDown(Direction::DOWN);
1053       }
1054     }
1055   }
1056
1057   return ret;
1058 }
1059
1060 bool AccessibilityManager::AccessibilityActionPageLeft()
1061 {
1062   Dali::Toolkit::AccessibilityManager handle( this );
1063   if( !mActionPageLeftSignal.Empty() )
1064   {
1065     mActionPageLeftSignal.Emit( handle );
1066   }
1067
1068   bool ret = false;
1069
1070   if(mIsAccessibilityTtsEnabled)
1071   {
1072     Actor actor = GetCurrentFocusActor();
1073     if(actor)
1074     {
1075       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
1076       if(control)
1077       {
1078         // TODO: Notify the control to scroll left to the previous page. Should control handle this?
1079 //        ret = GetImplementation( control ).OnAccessibilityScrollToPage(Direction::LEFT);
1080       }
1081     }
1082   }
1083
1084   return ret;
1085 }
1086
1087 bool AccessibilityManager::AccessibilityActionPageRight()
1088 {
1089   Dali::Toolkit::AccessibilityManager handle( this );
1090   if( !mActionPageRightSignal.Empty() )
1091   {
1092     mActionPageRightSignal.Emit( handle );
1093   }
1094
1095   bool ret = false;
1096
1097   if(mIsAccessibilityTtsEnabled)
1098   {
1099     Actor actor = GetCurrentFocusActor();
1100     if(actor)
1101     {
1102       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
1103       if(control)
1104       {
1105         // TODO: Notify the control to scroll right to the next page. Should control handle this?
1106 //        ret = GetImplementation( control ).OnAccessibilityScrollToPage(Direction::RIGHT);
1107       }
1108     }
1109   }
1110
1111   return ret;
1112 }
1113
1114 bool AccessibilityManager::AccessibilityActionPageUp()
1115 {
1116   Dali::Toolkit::AccessibilityManager handle( this );
1117   if( !mActionPageUpSignal.Empty() )
1118   {
1119     mActionPageUpSignal.Emit( handle );
1120   }
1121
1122   bool ret = false;
1123
1124   if(mIsAccessibilityTtsEnabled)
1125   {
1126     Actor actor = GetCurrentFocusActor();
1127     if(actor)
1128     {
1129       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
1130       if(control)
1131       {
1132         // TODO: Notify the control to scroll up to the previous page. Should control handle this?
1133 //        ret = GetImplementation( control ).OnAccessibilityScrollToPage(Direction::UP);
1134       }
1135     }
1136   }
1137
1138   return ret;
1139 }
1140
1141 bool AccessibilityManager::AccessibilityActionPageDown()
1142 {
1143   Dali::Toolkit::AccessibilityManager handle( this );
1144   if( !mActionPageDownSignal.Empty() )
1145   {
1146     mActionPageDownSignal.Emit( handle );
1147   }
1148
1149   bool ret = false;
1150
1151   if(mIsAccessibilityTtsEnabled)
1152   {
1153     Actor actor = GetCurrentFocusActor();
1154     if(actor)
1155     {
1156       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
1157       if(control)
1158       {
1159         // TODO: Notify the control to scroll down to the next page. Should control handle this?
1160 //        ret = GetImplementation( control ).OnAccessibilityScrollToPage(Direction::DOWN);
1161       }
1162     }
1163   }
1164
1165   return ret;
1166 }
1167
1168 bool AccessibilityManager::AccessibilityActionMoveToFirst()
1169 {
1170   Dali::Toolkit::AccessibilityManager handle( this );
1171   if( !mActionMoveToFirstSignal.Empty() )
1172   {
1173     mActionMoveToFirstSignal.Emit( handle );
1174   }
1175
1176   // TODO: Move to the first item on screen
1177
1178   return mIsAccessibilityTtsEnabled;
1179 }
1180
1181 bool AccessibilityManager::AccessibilityActionMoveToLast()
1182 {
1183   Dali::Toolkit::AccessibilityManager handle( this );
1184   if( !mActionMoveToLastSignal.Empty() )
1185   {
1186     mActionMoveToLastSignal.Emit( handle );
1187   }
1188
1189   // TODO: Move to the last item on screen
1190
1191   return mIsAccessibilityTtsEnabled;
1192 }
1193
1194 bool AccessibilityManager::AccessibilityActionReadFromTop()
1195 {
1196   Dali::Toolkit::AccessibilityManager handle( this );
1197   if( !mActionReadFromTopSignal.Empty() )
1198   {
1199     mActionReadFromTopSignal.Emit( handle );
1200   }
1201
1202   // TODO: Move to the top item on screen and read from the item continuously
1203
1204   return mIsAccessibilityTtsEnabled;
1205 }
1206
1207 bool AccessibilityManager::AccessibilityActionReadFromNext()
1208 {
1209   Dali::Toolkit::AccessibilityManager handle( this );
1210
1211   if( !mActionReadFromNextSignal.Empty() )
1212   {
1213     mActionReadFromNextSignal.Emit( handle );
1214   }
1215
1216   if( mIsAccessibilityTtsEnabled )
1217   {
1218     // Mark that we are in continuous play mode, so TTS signals can move focus.
1219     mContinuousPlayMode = true;
1220
1221     // Attempt to move to the next item and read from the item continuously.
1222     MoveFocusForward();
1223   }
1224
1225   return mIsAccessibilityTtsEnabled;
1226 }
1227
1228 void AccessibilityManager::TtsStateChanged( const Dali::TtsPlayer::State previousState, const Dali::TtsPlayer::State currentState )
1229 {
1230   if( mContinuousPlayMode )
1231   {
1232     // If we were playing and now we have stopped, attempt to play the next item.
1233     if( ( previousState == Dali::TtsPlayer::PLAYING ) && ( currentState == Dali::TtsPlayer::READY ) )
1234     {
1235       // Attempt to move the focus forward and play.
1236       // If we can't cancel continuous play mode.
1237       if( !MoveFocusForward() )
1238       {
1239         // We are done, exit continuous play mode.
1240         mContinuousPlayMode = false;
1241       }
1242     }
1243     else
1244     {
1245       // Unexpected play state change, exit continuous play mode.
1246       mContinuousPlayMode = false;
1247     }
1248   }
1249 }
1250
1251 bool AccessibilityManager::AccessibilityActionZoom()
1252 {
1253   Dali::Toolkit::AccessibilityManager handle( this );
1254   if( !mActionZoomSignal.Empty() )
1255   {
1256     mActionZoomSignal.Emit( handle );
1257   }
1258
1259   bool ret = false;
1260
1261   if(mIsAccessibilityTtsEnabled)
1262   {
1263     Actor actor = GetCurrentFocusActor();
1264     if(actor)
1265     {
1266       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
1267       if(control)
1268       {
1269         // Notify the control to zoom
1270         ret = GetImplementation( control ).OnAccessibilityZoom();
1271       }
1272     }
1273   }
1274
1275   return ret;
1276 }
1277
1278 bool AccessibilityManager::AccessibilityActionReadPauseResume()
1279 {
1280   Dali::Toolkit::AccessibilityManager handle( this );
1281   if( !mActionReadPauseResumeSignal.Empty() )
1282   {
1283     mActionReadPauseResumeSignal.Emit( handle );
1284   }
1285
1286   bool ret = false;
1287
1288   if(mIsAccessibilityTtsEnabled)
1289   {
1290     // Pause or resume the TTS player
1291     Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
1292     Dali::TtsPlayer::State state = player.GetState();
1293     if(state == Dali::TtsPlayer::PLAYING)
1294     {
1295       player.Pause();
1296       ret = true;
1297     }
1298     else if(state == Dali::TtsPlayer::PAUSED)
1299     {
1300       player.Resume();
1301       ret = true;
1302     }
1303   }
1304
1305   return ret;
1306 }
1307
1308 bool AccessibilityManager::AccessibilityActionStartStop()
1309 {
1310   Dali::Toolkit::AccessibilityManager handle( this );
1311   if( !mActionStartStopSignal.Empty() )
1312   {
1313     mActionStartStopSignal.Emit( handle );
1314   }
1315
1316   // TODO: Start/stop the current action
1317
1318   return mIsAccessibilityTtsEnabled;
1319 }
1320
1321 bool AccessibilityManager::HandlePanGesture(const AccessibilityGestureEvent& panEvent)
1322 {
1323   bool handled = false;
1324
1325   if( panEvent.state == AccessibilityGestureEvent::STARTED )
1326   {
1327     // Find the focusable actor at the event position
1328     Dali::HitTestAlgorithm::Results results;
1329     AccessibilityAdaptor adaptor = AccessibilityAdaptor::Get();
1330
1331     Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), panEvent.currentPosition, results, IsActorFocusableFunction );
1332     mCurrentGesturedActor = results.actor;
1333
1334     if(!mCurrentGesturedActor)
1335     {
1336       DALI_LOG_ERROR("Gesture detected, but no hit actor\n");
1337     }
1338   }
1339
1340   // GestureState::FINISHED (Up) events are delivered with previous (Motion) event position
1341   // Use the real previous position; otherwise we may incorrectly get a ZERO velocity
1342   if ( AccessibilityGestureEvent::FINISHED != panEvent.state )
1343   {
1344     // Store the previous position for next GestureState::FINISHED iteration.
1345     mPreviousPosition = panEvent.previousPosition;
1346   }
1347
1348   Actor rootActor = Stage::GetCurrent().GetRootLayer();
1349
1350   Dali::PanGesture pan = DevelPanGesture::New( static_cast<Dali::GestureState>(panEvent.state) );
1351   DevelPanGesture::SetTime( pan, panEvent.time );
1352   DevelPanGesture::SetNumberOfTouches( pan, panEvent.numberOfTouches  );
1353   DevelPanGesture::SetScreenPosition( pan, panEvent.currentPosition );
1354   DevelPanGesture::SetScreenDisplacement( pan, mPreviousPosition - panEvent.currentPosition );
1355   DevelPanGesture::SetScreenVelocity( pan, Vector2( pan.GetScreenDisplacement().x / panEvent.timeDelta, pan.GetScreenDisplacement().y / panEvent.timeDelta ) );
1356
1357   // Only handle the pan gesture when the current focused actor is scrollable or within a scrollable actor
1358   while(mCurrentGesturedActor && mCurrentGesturedActor != rootActor && !handled)
1359   {
1360     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(mCurrentGesturedActor);
1361     if(control)
1362     {
1363       Vector2 localCurrent;
1364       control.ScreenToLocal( localCurrent.x, localCurrent.y, panEvent.currentPosition.x, panEvent.currentPosition.y );
1365       DevelPanGesture::SetPosition( pan, localCurrent );
1366
1367       Vector2 localPrevious;
1368       control.ScreenToLocal( localPrevious.x, localPrevious.y, mPreviousPosition.x, mPreviousPosition.y );
1369
1370       DevelPanGesture::SetDisplacement( pan, localCurrent - localPrevious );
1371       DevelPanGesture::SetVelocity( pan, Vector2( pan.GetDisplacement().x / panEvent.timeDelta, pan.GetDisplacement().y / panEvent.timeDelta ));
1372
1373       handled = GetImplementation( control ).OnAccessibilityPan(pan);
1374     }
1375
1376     // If the gesture is not handled by the control, check its parent
1377     if(!handled)
1378     {
1379       mCurrentGesturedActor = mCurrentGesturedActor.GetParent();
1380
1381       if(!mCurrentGesturedActor)
1382       {
1383         DALI_LOG_ERROR("no more gestured actor\n");
1384       }
1385     }
1386     else
1387     {
1388       // If handled, then update the pan gesture properties
1389       PanGestureDetector::SetPanGestureProperties( pan );
1390     }
1391   }
1392
1393   return handled;
1394 }
1395
1396 Toolkit::AccessibilityManager::FocusChangedSignalType& AccessibilityManager::FocusChangedSignal()
1397 {
1398   return mFocusChangedSignal;
1399 }
1400
1401 Toolkit::AccessibilityManager::FocusOvershotSignalType& AccessibilityManager::FocusOvershotSignal()
1402 {
1403   return mFocusOvershotSignal;
1404 }
1405
1406 Toolkit::AccessibilityManager::FocusedActorActivatedSignalType& AccessibilityManager::FocusedActorActivatedSignal()
1407 {
1408   return mFocusedActorActivatedSignal;
1409 }
1410
1411 } // namespace Internal
1412
1413 } // namespace Toolkit
1414
1415 } // namespace Dali