989997bd537a489caa9316580c454fb57db25606
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyboard-focus-manager-impl.cpp
1 /*
2  * Copyright (c) 2016 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 // 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/singleton-service.h>
26 #include <dali/public-api/animation/constraints.h>
27 #include <dali/public-api/common/stage.h>
28 #include <dali/public-api/events/key-event.h>
29 #include <dali/public-api/events/touch-data.h>
30 #include <dali/public-api/object/type-registry.h>
31 #include <dali/public-api/object/type-registry-helper.h>
32 #include <dali/public-api/images/resource-image.h>
33 #include <dali/integration-api/debug.h>
34
35 // INTERNAL INCLUDES
36 #include <dali-toolkit/public-api/controls/control.h>
37 #include <dali-toolkit/public-api/controls/control-impl.h>
38 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
39 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
40 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
41 #include <dali-toolkit/devel-api/controls/control-devel.h>
42
43 namespace Dali
44 {
45
46 namespace Toolkit
47 {
48
49 namespace Internal
50 {
51
52 namespace // Unnamed namespace
53 {
54
55 #if defined(DEBUG_ENABLED)
56 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEYBOARD_FOCUS_MANAGER");
57 #endif
58
59 const char* const IS_FOCUS_GROUP_PROPERTY_NAME = "isKeyboardFocusGroup"; // This property will be replaced by a flag in Control.
60
61 const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.9.png";
62
63 BaseHandle Create()
64 {
65   BaseHandle handle = KeyboardFocusManager::Get();
66
67   if ( !handle )
68   {
69     SingletonService singletonService( SingletonService::Get() );
70     if ( singletonService )
71     {
72       Toolkit::KeyboardFocusManager manager = Toolkit::KeyboardFocusManager( new Internal::KeyboardFocusManager() );
73       singletonService.Register( typeid( manager ), manager );
74       handle = manager;
75     }
76   }
77
78   return handle;
79 }
80
81 DALI_TYPE_REGISTRATION_BEGIN_CREATE( Toolkit::KeyboardFocusManager, Dali::BaseHandle, Create, true )
82
83 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardPreFocusChange",           SIGNAL_PRE_FOCUS_CHANGE )
84 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusChanged",             SIGNAL_FOCUS_CHANGED )
85 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusGroupChanged",        SIGNAL_FOCUS_GROUP_CHANGED )
86 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusedActorEnterKey",     SIGNAL_FOCUSED_ACTOR_ENTER_KEY )
87
88 DALI_TYPE_REGISTRATION_END()
89
90 const unsigned int MAX_HISTORY_AMOUNT = 30; ///< Max length of focus history stack
91
92 } // unnamed namespace
93
94 Toolkit::KeyboardFocusManager KeyboardFocusManager::Get()
95 {
96   Toolkit::KeyboardFocusManager manager;
97
98   SingletonService singletonService( SingletonService::Get() );
99   if ( singletonService )
100   {
101     // Check whether the keyboard focus manager is already created
102     Dali::BaseHandle handle = singletonService.GetSingleton( typeid( Toolkit::KeyboardFocusManager ) );
103     if(handle)
104     {
105       // If so, downcast the handle of singleton to keyboard focus manager
106       manager = Toolkit::KeyboardFocusManager( dynamic_cast< KeyboardFocusManager* >( handle.GetObjectPtr() ) );
107     }
108   }
109
110   return manager;
111 }
112
113 KeyboardFocusManager::KeyboardFocusManager()
114 : mPreFocusChangeSignal(),
115   mFocusChangedSignal(),
116   mFocusGroupChangedSignal(),
117   mFocusedActorEnterKeySignal(),
118   mCurrentFocusActor( 0 ),
119   mFocusIndicatorActor(),
120   mFocusGroupLoopEnabled( false ),
121   mIsKeyboardFocusEnabled( false ),
122   mIsFocusIndicatorEnabled( false ),
123   mIsWaitingKeyboardFocusChangeCommit( false ),
124   mFocusHistory(),
125   mSlotDelegate( this )
126 {
127   OnPhysicalKeyboardStatusChanged(PhysicalKeyboard::Get());
128
129   Toolkit::KeyInputFocusManager::Get().UnhandledKeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
130   Stage::GetCurrent().TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch );
131   PhysicalKeyboard::Get().StatusChangedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnPhysicalKeyboardStatusChanged);
132 }
133
134 KeyboardFocusManager::~KeyboardFocusManager()
135 {
136 }
137
138 bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor )
139 {
140   DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" );
141
142   if( actor )
143   {
144     return DoSetCurrentFocusActor( actor.GetId() );
145   }
146
147   return false;
148 }
149
150 bool KeyboardFocusManager::DoSetCurrentFocusActor( const unsigned int actorID )
151 {
152   Actor rootActor = Stage::GetCurrent().GetRootLayer();
153   Actor actor = rootActor.FindChildById( actorID );
154   bool success = false;
155
156   // Check whether the actor is in the stage and is keyboard focusable.
157   if( actor && actor.IsKeyboardFocusable() )
158   {
159     mIsFocusIndicatorEnabled = true;
160     // Draw the focus indicator upon the focused actor when PhysicalKeyboard is attached
161     if( mIsKeyboardFocusEnabled )
162     {
163       actor.Add( GetFocusIndicatorActor() );
164     }
165     // Send notification for the change of focus actor
166     Actor currentFocusedActor = GetCurrentFocusActor();
167
168     if( !mFocusChangedSignal.Empty() )
169     {
170       mFocusChangedSignal.Emit(currentFocusedActor, actor);
171     }
172
173     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor);
174     if( currentlyFocusedControl )
175     {
176       // Do we need it to remember if it was previously DISABLED?
177       currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL );
178     }
179
180     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
181
182     // Save the current focused actor
183     mCurrentFocusActor = actorID;
184
185     Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor);
186     if( newlyFocusedControl )
187     {
188       newlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::FOCUSED );
189     }
190
191     // Push Current Focused Actor to FocusHistory
192     mFocusHistory.PushBack( &actor.GetBaseObject() );
193
194     // Delete first element before add new element when Stack is full.
195     if( mFocusHistory.Count() > MAX_HISTORY_AMOUNT )
196     {
197        FocusStackIterator beginPos = mFocusHistory.Begin();
198        mFocusHistory.Erase( beginPos );
199     }
200
201     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
202     success = true;
203   }
204   else
205   {
206     DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
207   }
208
209   return success;
210 }
211
212 Actor KeyboardFocusManager::GetCurrentFocusActor()
213 {
214   Actor rootActor = Stage::GetCurrent().GetRootLayer();
215   return rootActor.FindChildById(mCurrentFocusActor);
216 }
217
218 Actor KeyboardFocusManager::GetCurrentFocusGroup()
219 {
220   return GetFocusGroup(GetCurrentFocusActor());
221 }
222
223 void KeyboardFocusManager::MoveFocusBackward()
224 {
225   // Find Pre Focused Actor when the list size is more than 1
226   if( mFocusHistory.Count() > 1 )
227   {
228     // Delete current focused actor in history
229     FocusStackIterator endPos = mFocusHistory.End();
230     endPos = mFocusHistory.Erase( --endPos );
231
232     // If pre-focused actors are not on stage, remove them in stack
233     while( !Dali::Actor::DownCast(BaseHandle(mFocusHistory[ mFocusHistory.Count() - 1 ])).OnStage() )
234     {
235       endPos = mFocusHistory.Erase( --endPos );
236     }
237
238     // Get pre focused actor
239     BaseObject* object = mFocusHistory[ mFocusHistory.Count() - 1 ];
240     BaseHandle handle( object );
241     Actor preFocusedActor = Dali::Actor::DownCast( handle );
242
243     // Delete pre focused actor in history because it will pushed again by SetCurrentFocusActor()
244     mFocusHistory.Erase( --endPos );
245
246     SetCurrentFocusActor( preFocusedActor );
247  }
248 }
249
250 bool KeyboardFocusManager::IsLayoutControl(Actor actor) const
251 {
252   Toolkit::Control control = Toolkit::Control::DownCast(actor);
253   return control && GetImplementation( control ).IsKeyboardNavigationSupported();
254 }
255
256 Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const
257 {
258   // Get the actor's parent layout control that supports two dimensional keyboard navigation
259   Actor rootActor = Stage::GetCurrent().GetRootLayer();
260   Actor parent;
261   if(actor)
262   {
263     parent = actor.GetParent();
264   }
265
266   while( parent && !IsLayoutControl(parent) && parent != rootActor )
267   {
268     parent = parent.GetParent();
269   }
270
271   return Toolkit::Control::DownCast(parent);
272 }
273
274 bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction)
275 {
276   Actor currentFocusActor = GetCurrentFocusActor();
277
278   bool succeed = false;
279
280   // Go through the actor's hierarchy until we find a layout control that knows how to move the focus
281   Toolkit::Control parentLayoutControl = GetParentLayoutControl(currentFocusActor);
282   while(parentLayoutControl && !succeed)
283   {
284     succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, currentFocusActor, direction);
285     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
286   }
287
288   if(!succeed && !mPreFocusChangeSignal.Empty())
289   {
290     // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to
291     mIsWaitingKeyboardFocusChangeCommit = true;
292     Actor nextFocusableActor = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction);
293     mIsWaitingKeyboardFocusChangeCommit = false;
294
295     if ( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() )
296     {
297       // Whether the next focusable actor is a layout control
298       if(IsLayoutControl(nextFocusableActor))
299       {
300         // If so, move the focus inside it.
301         Toolkit::Control layoutControl = Toolkit::Control::DownCast(nextFocusableActor);
302         succeed = DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
303       }
304       else
305       {
306         // Otherwise, just set focus to the next focusable actor
307         succeed = SetCurrentFocusActor(nextFocusableActor);
308       }
309     }
310   }
311
312   return succeed;
313 }
314
315 bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control control, Actor actor, Toolkit::Control::KeyboardFocus::Direction direction)
316 {
317   // Ask the control for the next actor to focus
318   Actor nextFocusableActor = GetImplementation( control ).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
319   if(nextFocusableActor)
320   {
321     if(!nextFocusableActor.IsKeyboardFocusable())
322     {
323       // If the actor is not focusable, ask the same layout control for the next actor to focus
324       return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
325     }
326     else
327     {
328       Actor currentFocusActor = GetCurrentFocusActor();
329       Actor committedFocusActor = nextFocusableActor;
330
331       // We will try to move the focus to the actor. Emit a signal to notify the proposed actor to focus
332       // Signal handler can check the proposed actor and return a different actor if it wishes.
333       if( !mPreFocusChangeSignal.Empty() )
334       {
335         mIsWaitingKeyboardFocusChangeCommit = true;
336         committedFocusActor = mPreFocusChangeSignal.Emit(currentFocusActor, nextFocusableActor, direction);
337         mIsWaitingKeyboardFocusChangeCommit = false;
338       }
339
340       if (committedFocusActor && committedFocusActor.IsKeyboardFocusable())
341       {
342         // Whether the commited focusable actor is a layout control
343         if(IsLayoutControl(committedFocusActor))
344         {
345           // If so, move the focus inside it.
346           Toolkit::Control layoutControl = Toolkit::Control::DownCast(committedFocusActor);
347           return DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
348         }
349         else
350         {
351           // Otherwise, just set focus to the next focusable actor
352           if(committedFocusActor == nextFocusableActor)
353           {
354             // If the application hasn't changed our proposed actor, we informs the layout control we will
355             // move the focus to what the control returns. The control might wish to perform some actions
356             // before the focus is actually moved.
357             GetImplementation( control ).OnKeyboardFocusChangeCommitted( committedFocusActor );
358           }
359
360           return SetCurrentFocusActor(committedFocusActor);
361         }
362       }
363       else
364       {
365         return false;
366       }
367     }
368   }
369   else
370   {
371     // No more actor can be focused in the given direction within the same layout control.
372     return false;
373   }
374 }
375
376 bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward)
377 {
378   bool succeed = false;
379
380   // Get the parent layout control of the current focus group
381   Toolkit::Control parentLayoutControl = GetParentLayoutControl(GetCurrentFocusGroup());
382
383   while(parentLayoutControl && !succeed)
384   {
385     // If the current focus group has a parent layout control, we can probably automatically
386     // move the focus to the next focus group in the forward or backward direction.
387     Toolkit::Control::KeyboardFocus::Direction direction = forward ? Toolkit::Control::KeyboardFocus::RIGHT : Toolkit::Control::KeyboardFocus::LEFT;
388     succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction);
389     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
390   }
391
392   if(!mFocusGroupChangedSignal.Empty())
393   {
394     // Emit a focus group changed signal. The applicaton can move the focus to a new focus group
395     mFocusGroupChangedSignal.Emit(GetCurrentFocusActor(), forward);
396   }
397
398   return succeed;
399 }
400
401 void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
402 {
403   if( actor )
404   {
405     Toolkit::Control control = Toolkit::Control::DownCast( actor );
406     if( control )
407     {
408       // Notify the control that enter has been pressed on it.
409       GetImplementation( control ).KeyboardEnter();
410     }
411
412     // Send a notification for the actor.
413     if( !mFocusedActorEnterKeySignal.Empty() )
414     {
415       mFocusedActorEnterKeySignal.Emit( actor );
416     }
417   }
418 }
419
420 void KeyboardFocusManager::ClearFocus()
421 {
422   Actor actor = GetCurrentFocusActor();
423   if( actor )
424   {
425     if( mFocusIndicatorActor )
426     {
427       actor.Remove( mFocusIndicatorActor );
428     }
429
430     // Send notification for the change of focus actor
431     if( !mFocusChangedSignal.Empty() )
432     {
433       mFocusChangedSignal.Emit( actor, Actor() );
434     }
435
436     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast( actor );
437     if( currentlyFocusedControl )
438     {
439       currentlyFocusedControl.SetProperty( DevelControl::Property::STATE, DevelControl::NORMAL );
440     }
441   }
442
443   mCurrentFocusActor = 0;
444   mIsFocusIndicatorEnabled = false;
445 }
446
447 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
448 {
449   mFocusGroupLoopEnabled = enabled;
450 }
451
452 bool KeyboardFocusManager::GetFocusGroupLoop() const
453 {
454   return mFocusGroupLoopEnabled;
455 }
456
457 void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup)
458 {
459   if(actor)
460   {
461     // Create/Set focus group property.
462     actor.RegisterProperty( IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE );
463   }
464 }
465
466 bool KeyboardFocusManager::IsFocusGroup(Actor actor) const
467 {
468   // Check whether the actor is a focus group
469   bool isFocusGroup = false;
470
471   if(actor)
472   {
473     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
474     if(propertyIsFocusGroup != Property::INVALID_INDEX)
475     {
476       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
477     }
478   }
479
480   return isFocusGroup;
481 }
482
483 Actor KeyboardFocusManager::GetFocusGroup(Actor actor)
484 {
485   // Go through the actor's hierarchy to check which focus group the actor belongs to
486   while (actor && !IsFocusGroup(actor))
487   {
488     actor = actor.GetParent();
489   }
490
491   return actor;
492 }
493
494 void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator)
495 {
496   if(mFocusIndicatorActor != indicator)
497   {
498     Actor currentFocusActor = GetCurrentFocusActor();
499     if(currentFocusActor)
500     {
501       // The new focus indicator should be added to the current focused actor immediately
502       if(mFocusIndicatorActor)
503       {
504         currentFocusActor.Remove(mFocusIndicatorActor);
505       }
506
507       if(indicator)
508       {
509         currentFocusActor.Add(indicator);
510       }
511     }
512
513     mFocusIndicatorActor = indicator;
514   }
515 }
516
517 Actor KeyboardFocusManager::GetFocusIndicatorActor()
518 {
519   if( ! mFocusIndicatorActor )
520   {
521     // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors
522     mFocusIndicatorActor = Toolkit::ImageView::New( FOCUS_BORDER_IMAGE_PATH );
523     mFocusIndicatorActor.SetParentOrigin( ParentOrigin::CENTER );
524
525     // Apply size constraint to the focus indicator
526     mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
527   }
528
529   return mFocusIndicatorActor;
530 }
531
532 void KeyboardFocusManager::OnPhysicalKeyboardStatusChanged(PhysicalKeyboard keyboard)
533 {
534   mIsKeyboardFocusEnabled = keyboard.IsAttached();
535
536   if(mIsKeyboardFocusEnabled)
537   {
538     // Show indicator when keyboard focus turned on if there is focused actor.
539     Actor actor = GetCurrentFocusActor();
540     if(actor)
541     {
542       actor.Add( GetFocusIndicatorActor() );
543     }
544     mIsFocusIndicatorEnabled = true;
545   }
546   else
547   {
548     // Hide indicator when keyboard focus turned off
549     Actor actor = GetCurrentFocusActor();
550     if( actor && mFocusIndicatorActor )
551     {
552       actor.Remove( mFocusIndicatorActor );
553     }
554     mIsFocusIndicatorEnabled = false;
555   }
556 }
557
558 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
559 {
560   if(!mIsKeyboardFocusEnabled)
561   {
562     return;
563   }
564
565   AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
566   bool isAccessibilityEnabled = accessibilityAdaptor.IsEnabled();
567
568   Toolkit::AccessibilityManager accessibilityManager = Toolkit::AccessibilityManager::Get();
569
570   std::string keyName = event.keyPressedName;
571
572   bool isFocusStartableKey = false;
573
574   if(event.state == KeyEvent::Down)
575   {
576     if (keyName == "Left")
577     {
578       if(!isAccessibilityEnabled)
579       {
580         if(!mIsFocusIndicatorEnabled)
581         {
582           // Show focus indicator
583           mIsFocusIndicatorEnabled = true;
584         }
585         else
586         {
587           // Move the focus towards left
588           MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
589         }
590
591         isFocusStartableKey = true;
592       }
593       else
594       {
595         // Move the accessibility focus backward
596         accessibilityManager.MoveFocusBackward();
597       }
598     }
599     else if (keyName == "Right")
600     {
601       if(!isAccessibilityEnabled)
602       {
603         if(!mIsFocusIndicatorEnabled)
604         {
605           // Show focus indicator
606           mIsFocusIndicatorEnabled = true;
607         }
608         else
609         {
610           // Move the focus towards right
611           MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
612         }
613       }
614       else
615       {
616         // Move the accessibility focus forward
617         accessibilityManager.MoveFocusForward();
618       }
619
620       isFocusStartableKey = true;
621     }
622     else if (keyName == "Up" && !isAccessibilityEnabled)
623     {
624       if(!mIsFocusIndicatorEnabled)
625       {
626         // Show focus indicator
627         mIsFocusIndicatorEnabled = true;
628       }
629       else
630       {
631         // Move the focus towards up
632         MoveFocus(Toolkit::Control::KeyboardFocus::UP);
633       }
634
635       isFocusStartableKey = true;
636     }
637     else if (keyName == "Down" && !isAccessibilityEnabled)
638     {
639       if(!mIsFocusIndicatorEnabled)
640       {
641         // Show focus indicator
642         mIsFocusIndicatorEnabled = true;
643       }
644       else
645       {
646         // Move the focus towards down
647         MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
648       }
649
650       isFocusStartableKey = true;
651     }
652     else if (keyName == "Prior" && !isAccessibilityEnabled)
653     {
654       if(!mIsFocusIndicatorEnabled)
655       {
656         // Show focus indicator
657         mIsFocusIndicatorEnabled = true;
658       }
659       else
660       {
661         // Move the focus towards the previous page
662         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
663       }
664
665       isFocusStartableKey = true;
666     }
667     else if (keyName == "Next" && !isAccessibilityEnabled)
668     {
669       if(!mIsFocusIndicatorEnabled)
670       {
671         // Show focus indicator
672         mIsFocusIndicatorEnabled = true;
673       }
674       else
675       {
676         // Move the focus towards the next page
677         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
678       }
679
680       isFocusStartableKey = true;
681     }
682     else if (keyName == "Tab" && !isAccessibilityEnabled)
683     {
684       if(!mIsFocusIndicatorEnabled)
685       {
686         // Show focus indicator
687         mIsFocusIndicatorEnabled = true;
688       }
689       else
690       {
691         // "Tab" key changes the focus group in the forward direction and
692         // "Shift-Tab" key changes it in the backward direction.
693         DoMoveFocusToNextFocusGroup(!event.IsShiftModifier());
694       }
695
696       isFocusStartableKey = true;
697     }
698     else if (keyName == "space" && !isAccessibilityEnabled)
699     {
700       if(!mIsFocusIndicatorEnabled)
701       {
702         // Show focus indicator
703         mIsFocusIndicatorEnabled = true;
704       }
705
706       isFocusStartableKey = true;
707     }
708     else if (keyName == "" && !isAccessibilityEnabled)
709     {
710       // Check the fake key event for evas-plugin case
711       if(!mIsFocusIndicatorEnabled)
712       {
713         // Show focus indicator
714         mIsFocusIndicatorEnabled = true;
715       }
716
717       isFocusStartableKey = true;
718     }
719     else if (keyName == "Backspace" && !isAccessibilityEnabled)
720     {
721       // Emit signal to go back to the previous view???
722     }
723     else if (keyName == "Escape" && !isAccessibilityEnabled)
724     {
725     }
726   }
727   else if(event.state == KeyEvent::Up)
728   {
729     if (keyName == "Return")
730     {
731       if(!mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
732       {
733         // Show focus indicator
734         mIsFocusIndicatorEnabled = true;
735       }
736       else
737       {
738         // The focused actor has enter pressed on it
739         Actor actor;
740         if( !isAccessibilityEnabled )
741         {
742           actor = GetCurrentFocusActor();
743         }
744         else
745         {
746           actor = accessibilityManager.GetCurrentFocusActor();
747         }
748
749         if( actor )
750         {
751           DoKeyboardEnter( actor );
752         }
753       }
754
755       isFocusStartableKey = true;
756     }
757   }
758
759   if(isFocusStartableKey && mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
760   {
761     Actor actor = GetCurrentFocusActor();
762     if( actor )
763     {
764       // Make sure the focused actor is highlighted
765       actor.Add( GetFocusIndicatorActor() );
766     }
767     else
768     {
769       // No actor is focused but keyboard focus is activated by the key press
770       // Let's try to move the initial focus
771       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
772     }
773   }
774 }
775
776 void KeyboardFocusManager::OnTouch(const TouchData& touch)
777 {
778   // Clear the focus when user touch the screen.
779   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
780   if( ( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN ) )
781   {
782     ClearFocus();
783   }
784 }
785
786 Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal()
787 {
788   return mPreFocusChangeSignal;
789 }
790
791 Toolkit::KeyboardFocusManager::FocusChangedSignalType& KeyboardFocusManager::FocusChangedSignal()
792 {
793   return mFocusChangedSignal;
794 }
795
796 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager::FocusGroupChangedSignal()
797 {
798   return mFocusGroupChangedSignal;
799 }
800
801 Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal()
802 {
803   return mFocusedActorEnterKeySignal;
804 }
805
806 bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
807 {
808   Dali::BaseHandle handle( object );
809
810   bool connected( true );
811   KeyboardFocusManager* manager = static_cast< KeyboardFocusManager* >( object ); // TypeRegistry guarantees that this is the correct type.
812
813   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE ) )
814   {
815     manager->PreFocusChangeSignal().Connect( tracker, functor );
816   }
817   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) )
818   {
819     manager->FocusChangedSignal().Connect( tracker, functor );
820   }
821   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED ) )
822   {
823     manager->FocusGroupChangedSignal().Connect( tracker, functor );
824   }
825   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) )
826   {
827     manager->FocusedActorEnterKeySignal().Connect( tracker, functor );
828   }
829   else
830   {
831     // signalName does not match any signal
832     connected = false;
833   }
834
835   return connected;
836 }
837
838 } // namespace Internal
839
840 } // namespace Toolkit
841
842 } // namespace Dali