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