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