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