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