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