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