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