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