Merge branch 'master' into tizen
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / focus-manager / keyboard-focus-manager-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 #include "keyboard-focus-manager-impl.h"
19
20 // INTERNAL INCLUDES
21 #include <dali-toolkit/public-api/controls/control.h>
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/public-api/focus-manager/focus-manager.h>
24 #include <dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h>
25 #include <dali/integration-api/debug.h>
26
27 namespace Dali
28 {
29
30 namespace Toolkit
31 {
32
33 namespace Internal
34 {
35
36 namespace // unnamed namespace
37 {
38
39 #if defined(DEBUG_ENABLED)
40 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEYBOARD_FOCUS_MANAGER");
41 #endif
42
43 const std::string IS_FOCUS_GROUP_PROPERTY_NAME("is-keyboard-focus-group"); // This property will be replaced by a flag in Control.
44
45 const char* FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.png";
46 const Vector4 FOCUS_BORDER_IMAGE_BORDER = Vector4(7.0f, 7.0f, 7.0f, 7.0f);
47
48 BaseHandle Create()
49 {
50   BaseHandle handle = KeyboardFocusManager::Get();
51
52   if ( !handle && Adaptor::IsAvailable() )
53   {
54     Toolkit::KeyboardFocusManager manager = Toolkit::KeyboardFocusManager( new Internal::KeyboardFocusManager() );
55     Adaptor::Get().RegisterSingleton( typeid( manager ), manager );
56     handle = manager;
57   }
58
59   return handle;
60 }
61 TypeRegistration KEYBOARD_FOCUS_MANAGER_TYPE( typeid(Dali::Toolkit::KeyboardFocusManager), typeid(Dali::BaseHandle), Create, true /* Create instance at startup */ );
62
63 } // unnamed namespace
64
65 Toolkit::KeyboardFocusManager KeyboardFocusManager::Get()
66 {
67   Toolkit::KeyboardFocusManager manager;
68
69   if ( Adaptor::IsAvailable() )
70   {
71     // Check whether the keyboard focus manager is already created
72     Dali::BaseHandle handle = Dali::Adaptor::Get().GetSingleton( typeid( Toolkit::KeyboardFocusManager ) );
73     if(handle)
74     {
75       // If so, downcast the handle of singleton to keyboard focus manager
76       manager = Toolkit::KeyboardFocusManager( dynamic_cast< KeyboardFocusManager* >( handle.GetObjectPtr() ) );
77     }
78   }
79
80   return manager;
81 }
82
83 KeyboardFocusManager::KeyboardFocusManager()
84 : mCurrentFocusActor(0),
85   mFocusIndicatorActor(Actor()),
86   mFocusGroupLoopEnabled(false),
87   mIsKeyboardFocusEnabled(false),
88   mIsFocusIndicatorEnabled(false),
89   mIsWaitingKeyboardFocusChangeCommit(false),
90   mSlotDelegate(this)
91 {
92   CreateDefaultFocusIndicatorActor();
93
94   OnPhysicalKeyboardStatusChanged(PhysicalKeyboard::Get());
95
96   Toolkit::KeyInputFocusManager::Get().UnhandledKeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
97   Stage::GetCurrent().TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouched);
98   PhysicalKeyboard::Get().StatusChangedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnPhysicalKeyboardStatusChanged);
99 }
100
101 KeyboardFocusManager::~KeyboardFocusManager()
102 {
103 }
104
105 bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor)
106 {
107   DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" );
108
109   if(actor)
110   {
111     return DoSetCurrentFocusActor(actor.GetId());
112   }
113
114   return false;
115 }
116
117 bool KeyboardFocusManager::DoSetCurrentFocusActor(const unsigned int actorID)
118 {
119   Actor rootActor = Stage::GetCurrent().GetRootLayer();
120   Actor actor = rootActor.FindChildById(actorID);
121
122   // Check whether the actor is in the stage
123   if(actor)
124   {
125     // Set the focus only when the actor is keyboard focusable
126     if(actor.IsKeyboardFocusable())
127     {
128       // Draw the focus indicator upon the focused actor
129       if(mIsFocusIndicatorEnabled && mFocusIndicatorActor)
130       {
131         actor.Add(mFocusIndicatorActor);
132       }
133
134       // Send notification for the change of focus actor
135       if( !mFocusChangedSignalV2.Empty() )
136       {
137         mFocusChangedSignalV2.Emit(GetCurrentFocusActor(), actor);
138       }
139
140       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
141
142       // Save the current focused actor
143       mCurrentFocusActor = actorID;
144
145       // Move the accessibility focus to the same actor
146 //      Toolkit::FocusManager focusManager = Toolkit::FocusManager::Get();
147 //      focusManager.SetCurrentFocusActor(actor);
148
149       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
150       return true;
151     }
152   }
153
154   DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
155   return false;
156 }
157
158 Actor KeyboardFocusManager::GetCurrentFocusActor()
159 {
160   Actor rootActor = Stage::GetCurrent().GetRootLayer();
161   return rootActor.FindChildById(mCurrentFocusActor);
162 }
163
164 Actor KeyboardFocusManager::GetCurrentFocusGroup()
165 {
166   return GetFocusGroup(GetCurrentFocusActor());
167 }
168
169 bool KeyboardFocusManager::IsLayoutControl(Actor actor) const
170 {
171   Toolkit::Control control = Toolkit::Control::DownCast(actor);
172   return control && control.GetImplementation().IsKeyboardNavigationSupported();
173 }
174
175 Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const
176 {
177   // Get the actor's parent layout control that supports two dimensional keyboard navigation
178   Actor rootActor = Stage::GetCurrent().GetRootLayer();
179   Actor parent;
180   if(actor)
181   {
182     parent = actor.GetParent();
183   }
184
185   while( parent && !IsLayoutControl(parent) && parent != rootActor )
186   {
187     parent = parent.GetParent();
188   }
189
190   return Toolkit::Control::DownCast(parent);
191 }
192
193 bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocusNavigationDirection direction)
194 {
195   Actor currentFocusActor = GetCurrentFocusActor();
196
197   bool succeed = false;
198
199   // Go through the actor's hierarchy until we find a layout control that knows how to move the focus
200   Toolkit::Control parentLayoutControl = GetParentLayoutControl(currentFocusActor);
201   while(parentLayoutControl && !succeed)
202   {
203     succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, currentFocusActor, direction);
204     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
205   }
206
207   if(!succeed && !mPreFocusChangeSignalV2.Empty())
208   {
209     // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to
210     mIsWaitingKeyboardFocusChangeCommit = true;
211     Actor nextFocusableActor = mPreFocusChangeSignalV2.Emit(currentFocusActor, Actor(), direction);
212     mIsWaitingKeyboardFocusChangeCommit = false;
213
214     if ( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() )
215     {
216       // Whether the next focusable actor is a layout control
217       if(IsLayoutControl(nextFocusableActor))
218       {
219         // If so, move the focus inside it.
220         Toolkit::Control layoutControl = Toolkit::Control::DownCast(nextFocusableActor);
221         succeed = DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
222       }
223       else
224       {
225         // Otherwise, just set focus to the next focusable actor
226         succeed = SetCurrentFocusActor(nextFocusableActor);
227       }
228     }
229   }
230
231   return succeed;
232 }
233
234 bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control control, Actor actor, Toolkit::Control::KeyboardFocusNavigationDirection direction)
235 {
236   // Ask the control for the next actor to focus
237   Actor nextFocusableActor = control.GetImplementation().GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
238   if(nextFocusableActor)
239   {
240     if(!nextFocusableActor.IsKeyboardFocusable())
241     {
242       // If the actor is not focusable, ask the same layout control for the next actor to focus
243       return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
244     }
245     else
246     {
247       Actor currentFocusActor = GetCurrentFocusActor();
248       Actor committedFocusActor = nextFocusableActor;
249
250       // We will try to move the focus to the actor. Emit a signal to notify the proposed actor to focus
251       // Signal handler can check the proposed actor and return a different actor if it wishes.
252       if( !mPreFocusChangeSignalV2.Empty() )
253       {
254         mIsWaitingKeyboardFocusChangeCommit = true;
255         committedFocusActor = mPreFocusChangeSignalV2.Emit(currentFocusActor, nextFocusableActor, direction);
256         mIsWaitingKeyboardFocusChangeCommit = false;
257       }
258
259       if (committedFocusActor && committedFocusActor.IsKeyboardFocusable())
260       {
261         // Whether the commited focusable actor is a layout control
262         if(IsLayoutControl(committedFocusActor))
263         {
264           // If so, move the focus inside it.
265           Toolkit::Control layoutControl = Toolkit::Control::DownCast(committedFocusActor);
266           return DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
267         }
268         else
269         {
270           // Otherwise, just set focus to the next focusable actor
271           if(committedFocusActor == nextFocusableActor)
272           {
273             // If the application hasn't changed our proposed actor, we informs the layout control we will
274             // move the focus to what the control returns. The control might wish to perform some actions
275             // before the focus is actually moved.
276             control.GetImplementation().OnKeyboardFocusChangeCommitted(committedFocusActor);
277           }
278
279           return SetCurrentFocusActor(committedFocusActor);
280         }
281       }
282       else
283       {
284         return false;
285       }
286     }
287   }
288   else
289   {
290     // No more actor can be focused in the given direction within the same layout control.
291     return false;
292   }
293 }
294
295 bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward)
296 {
297   bool succeed = false;
298
299   // Get the parent layout control of the current focus group
300   Toolkit::Control parentLayoutControl = GetParentLayoutControl(GetCurrentFocusGroup());
301
302   while(parentLayoutControl && !succeed)
303   {
304     // If the current focus group has a parent layout control, we can probably automatically
305     // move the focus to the next focus group in the forward or backward direction.
306     Toolkit::Control::KeyboardFocusNavigationDirection direction = forward ? Toolkit::Control::Right : Toolkit::Control::Left;
307     succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction);
308     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
309   }
310
311   if(!mFocusGroupChangedSignalV2.Empty())
312   {
313     // Emit a focus group changed signal. The applicaton can move the focus to a new focus group
314     mFocusGroupChangedSignalV2.Emit(GetCurrentFocusActor(), forward);
315   }
316
317   return succeed;
318 }
319
320 void KeyboardFocusManager::DoActivate(Actor actor)
321 {
322   if(actor)
323   {
324     Toolkit::Control control = Toolkit::Control::DownCast(actor);
325     if(control)
326     {
327       // Notify the control that it is activated
328       control.GetImplementation().OnActivated();
329     }
330
331     // Send notification for the activation of focused actor
332     if( !mFocusedActorActivatedSignalV2.Empty() )
333     {
334       mFocusedActorActivatedSignalV2.Emit(actor);
335     }
336   }
337 }
338
339 void KeyboardFocusManager::ClearFocus()
340 {
341   Actor actor = GetCurrentFocusActor();
342   if(actor)
343   {
344     if(mFocusIndicatorActor)
345     {
346       actor.Remove(mFocusIndicatorActor);
347     }
348
349     // Send notification for the change of focus actor
350     if( !mFocusChangedSignalV2.Empty() )
351     {
352       mFocusChangedSignalV2.Emit(actor, Actor());
353     }
354   }
355
356   mCurrentFocusActor = 0;
357   mIsFocusIndicatorEnabled = false;
358 }
359
360 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
361 {
362   mFocusGroupLoopEnabled = enabled;
363 }
364
365 bool KeyboardFocusManager::GetFocusGroupLoop() const
366 {
367   return mFocusGroupLoopEnabled;
368 }
369
370 void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup)
371 {
372   if(actor)
373   {
374     // Create focus group property if not already created.
375     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
376     if(propertyIsFocusGroup == Property::INVALID_INDEX)
377     {
378       propertyIsFocusGroup = actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup);
379     }
380     else
381     {
382       actor.SetProperty(propertyIsFocusGroup, isFocusGroup);
383     }
384   }
385 }
386
387 bool KeyboardFocusManager::IsFocusGroup(Actor actor) const
388 {
389   // Check whether the actor is a focus group
390   bool isFocusGroup = false;
391
392   if(actor)
393   {
394     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
395     if(propertyIsFocusGroup != Property::INVALID_INDEX)
396     {
397       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
398     }
399   }
400
401   return isFocusGroup;
402 }
403
404 Actor KeyboardFocusManager::GetFocusGroup(Actor actor)
405 {
406   // Go through the actor's hierarchy to check which focus group the actor belongs to
407   while (actor && !IsFocusGroup(actor))
408   {
409     actor = actor.GetParent();
410   }
411
412   return actor;
413 }
414
415 void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator)
416 {
417   if(mFocusIndicatorActor != indicator)
418   {
419     Actor currentFocusActor = GetCurrentFocusActor();
420     if(currentFocusActor)
421     {
422       // The new focus indicator should be added to the current focused actor immediately
423       if(mFocusIndicatorActor)
424       {
425         currentFocusActor.Remove(mFocusIndicatorActor);
426       }
427
428       if(indicator)
429       {
430         currentFocusActor.Add(indicator);
431       }
432     }
433
434     mFocusIndicatorActor = indicator;
435   }
436 }
437
438 Actor KeyboardFocusManager::GetFocusIndicatorActor()
439 {
440   return mFocusIndicatorActor;
441 }
442
443 void KeyboardFocusManager::CreateDefaultFocusIndicatorActor()
444 {
445   // Create a focus indicator actor shared by all the keyboard focusable actors
446   Image borderImage = Image::New(FOCUS_BORDER_IMAGE_PATH);
447
448   ImageActor focusIndicator = ImageActor::New(borderImage);
449   focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
450   focusIndicator.SetStyle( ImageActor::STYLE_NINE_PATCH );
451   focusIndicator.SetNinePatchBorder(FOCUS_BORDER_IMAGE_BORDER);
452   focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f));
453
454   // Apply size constraint to the focus indicator
455   Constraint constraint = Constraint::New<Vector3>(Actor::SIZE,
456                                                    ParentSource(Actor::SIZE),
457                                                    EqualToConstraint());
458   focusIndicator.ApplyConstraint(constraint);
459
460   SetFocusIndicatorActor(focusIndicator);
461 }
462
463 void KeyboardFocusManager::OnPhysicalKeyboardStatusChanged(PhysicalKeyboard keyboard)
464 {
465   mIsKeyboardFocusEnabled = keyboard.IsAttached();
466
467   if(mIsKeyboardFocusEnabled)
468   {
469     // Show indicator when keyboard focus turned on if there is focused actor.
470     Actor actor = GetCurrentFocusActor();
471     if(actor)
472     {
473       if(mFocusIndicatorActor)
474       {
475         actor.Add(mFocusIndicatorActor);
476       }
477     }
478     mIsFocusIndicatorEnabled = true;
479   }
480   else
481   {
482     // Hide indicator when keyboard focus turned off
483     Actor actor = GetCurrentFocusActor();
484     if(actor)
485     {
486       actor.Remove(mFocusIndicatorActor);
487     }
488     mIsFocusIndicatorEnabled = false;
489   }
490 }
491
492 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
493 {
494   if(!mIsKeyboardFocusEnabled)
495   {
496     return;
497   }
498
499   AccessibilityManager accessibilityManager = AccessibilityManager::Get();
500   bool isAccessibilityEnabled = accessibilityManager.IsEnabled();
501
502   Toolkit::FocusManager accessibilityFocusManager = Toolkit::FocusManager::Get();
503
504   std::string keyName = event.keyPressedName;
505
506   bool isFocusStartableKey = false;
507
508   if(event.state == KeyEvent::Down)
509   {
510     if (keyName == "Left")
511     {
512       if(!isAccessibilityEnabled)
513       {
514         if(!mIsFocusIndicatorEnabled)
515         {
516           // Show focus indicator
517           mIsFocusIndicatorEnabled = true;
518         }
519         else
520         {
521           // Move the focus towards left
522           MoveFocus(Toolkit::Control::Left);
523         }
524
525         isFocusStartableKey = true;
526       }
527       else
528       {
529         // Move the accessibility focus backward
530         accessibilityFocusManager.MoveFocusBackward();
531       }
532     }
533     else if (keyName == "Right")
534     {
535       if(!isAccessibilityEnabled)
536       {
537         if(!mIsFocusIndicatorEnabled)
538         {
539           // Show focus indicator
540           mIsFocusIndicatorEnabled = true;
541         }
542         else
543         {
544           // Move the focus towards right
545           MoveFocus(Toolkit::Control::Right);
546         }
547
548         isFocusStartableKey = true;
549       }
550       else
551       {
552         // Move the accessibility focus forward
553         accessibilityFocusManager.MoveFocusForward();
554       }
555
556       isFocusStartableKey = true;
557     }
558     else if (keyName == "Up" && !isAccessibilityEnabled)
559     {
560       if(!mIsFocusIndicatorEnabled)
561       {
562         // Show focus indicator
563         mIsFocusIndicatorEnabled = true;
564       }
565       else
566       {
567         // Move the focus towards up
568         MoveFocus(Toolkit::Control::Up);
569       }
570
571       isFocusStartableKey = true;
572     }
573     else if (keyName == "Down" && !isAccessibilityEnabled)
574     {
575       if(!mIsFocusIndicatorEnabled)
576       {
577         // Show focus indicator
578         mIsFocusIndicatorEnabled = true;
579       }
580       else
581       {
582         // Move the focus towards down
583         MoveFocus(Toolkit::Control::Down);
584       }
585
586       isFocusStartableKey = true;
587     }
588     else if (keyName == "Tab" && !isAccessibilityEnabled)
589     {
590       if(!mIsFocusIndicatorEnabled)
591       {
592         // Show focus indicator
593         mIsFocusIndicatorEnabled = true;
594       }
595       else
596       {
597         // "Tab" key changes the focus group in the forward direction and
598         // "Shift-Tab" key changes it in the backward direction.
599         DoMoveFocusToNextFocusGroup(!event.IsShiftModifier());
600       }
601
602       isFocusStartableKey = true;
603     }
604     else if (keyName == "space" && !isAccessibilityEnabled)
605     {
606       if(!mIsFocusIndicatorEnabled)
607       {
608         // Show focus indicator
609         mIsFocusIndicatorEnabled = true;
610       }
611
612       isFocusStartableKey = true;
613     }
614     else if (keyName == "" && !isAccessibilityEnabled)
615     {
616       // Check the fake key event for evas-plugin case
617       if(!mIsFocusIndicatorEnabled)
618       {
619         // Show focus indicator
620         mIsFocusIndicatorEnabled = true;
621       }
622
623       isFocusStartableKey = true;
624     }
625     else if (keyName == "Backspace" && !isAccessibilityEnabled)
626     {
627       // Emit signal to go back to the previous view???
628     }
629   }
630   else if(event.state == KeyEvent::Up)
631   {
632     if (keyName == "Return")
633     {
634       if(!mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
635       {
636         // Show focus indicator
637         mIsFocusIndicatorEnabled = true;
638       }
639       else
640       {
641         // Activate the focused actor
642         Actor actor;
643         if(!isAccessibilityEnabled)
644         {
645           actor = GetCurrentFocusActor();
646         }
647         else
648         {
649           actor = accessibilityFocusManager.GetCurrentFocusActor();
650         }
651
652         if(actor)
653         {
654           DoActivate(actor);
655         }
656       }
657
658       isFocusStartableKey = true;
659     }
660   }
661
662   if(isFocusStartableKey && mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
663   {
664     Actor actor = GetCurrentFocusActor();
665     if( !actor )
666     {
667       // No actor is focused but keyboard focus is activated by the key press
668       // Let's try to move the initial focus
669       MoveFocus(Toolkit::Control::Right);
670     }
671     else if(mFocusIndicatorActor)
672     {
673       // Make sure the focused actor is highlighted
674       actor.Add(mFocusIndicatorActor);
675     }
676   }
677 }
678
679 void KeyboardFocusManager::OnTouched(const TouchEvent& touchEvent)
680 {
681   // Clear the focus when user touch the screen
682   ClearFocus();
683 }
684
685 Toolkit::KeyboardFocusManager::PreFocusChangeSignalV2& KeyboardFocusManager::PreFocusChangeSignal()
686 {
687   return mPreFocusChangeSignalV2;
688 }
689
690 Toolkit::KeyboardFocusManager::FocusChangedSignalV2& KeyboardFocusManager::FocusChangedSignal()
691 {
692   return mFocusChangedSignalV2;
693 }
694
695 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalV2& KeyboardFocusManager::FocusGroupChangedSignal()
696 {
697   return mFocusGroupChangedSignalV2;
698 }
699
700 Toolkit::KeyboardFocusManager::FocusedActorActivatedSignalV2& KeyboardFocusManager::FocusedActorActivatedSignal()
701 {
702   return mFocusedActorActivatedSignalV2;
703 }
704
705 bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
706 {
707   Dali::BaseHandle handle( object );
708
709   bool connected( true );
710   KeyboardFocusManager* manager = dynamic_cast<KeyboardFocusManager*>(object);
711
712   if( Dali::Toolkit::KeyboardFocusManager::SIGNAL_PRE_FOCUS_CHANGE == signalName )
713   {
714     manager->PreFocusChangeSignal().Connect( tracker, functor );
715   }
716   if( Dali::Toolkit::KeyboardFocusManager::SIGNAL_FOCUS_CHANGED == signalName )
717   {
718     manager->FocusChangedSignal().Connect( tracker, functor );
719   }
720   if( Dali::Toolkit::KeyboardFocusManager::SIGNAL_FOCUS_GROUP_CHANGED == signalName )
721   {
722     manager->FocusGroupChangedSignal().Connect( tracker, functor );
723   }
724   else if( Dali::Toolkit::KeyboardFocusManager::SIGNAL_FOCUSED_ACTOR_ACTIVATED== signalName )
725   {
726     manager->FocusedActorActivatedSignal().Connect( tracker, functor );
727   }
728   else
729   {
730     // signalName does not match any signal
731     connected = false;
732   }
733
734   return connected;
735 }
736
737 } // namespace Internal
738
739 } // namespace Toolkit
740
741 } // namespace Dali