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