Merge "CMake - Option added to define the default toolkit resource path." into devel...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyboard-focus-manager-impl.cpp
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "keyboard-focus-manager-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/actors/layer.h>
24 #include <dali/devel-api/adaptor-framework/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/common/stage.h>
29 #include <dali/public-api/events/key-event.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/object/type-registry.h>
32 #include <dali/public-api/object/type-registry-helper.h>
33 #include <dali/public-api/object/property-map.h>
34 #include <dali/public-api/images/resource-image.h>
35 #include <dali/integration-api/debug.h>
36 #include <dali/integration-api/adaptor-framework/adaptor.h>
37 #include <dali/integration-api/adaptor-framework/scene-holder.h>
38
39 // INTERNAL INCLUDES
40 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
41 #include <dali-toolkit/public-api/controls/control.h>
42 #include <dali-toolkit/public-api/controls/control-impl.h>
43 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
44 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
45 #include <dali-toolkit/devel-api/controls/control-devel.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 {
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 ).TouchSignal().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.TouchSignal().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.IsKeyboardFocusable() && actor.OnStage() )
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.IsKeyboardFocusable() && actor.OnStage() )
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.OnStage() )
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.OnStage() )
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.OnStage() )
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     }
506
507     if( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() )
508     {
509       // Whether the next focusable actor is a layout control
510       if( IsLayoutControl( nextFocusableActor ) )
511       {
512         // If so, move the focus inside it.
513         Toolkit::Control layoutControl = Toolkit::Control::DownCast( nextFocusableActor) ;
514         succeed = DoMoveFocusWithinLayoutControl( layoutControl, currentFocusActor, direction );
515       }
516       else
517       {
518         // Otherwise, just set focus to the next focusable actor
519         succeed = SetCurrentFocusActor( nextFocusableActor );
520       }
521     }
522   }
523
524   return succeed;
525 }
526
527 bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control control, Actor actor, Toolkit::Control::KeyboardFocus::Direction direction)
528 {
529   // Ask the control for the next actor to focus
530   Actor nextFocusableActor = GetImplementation( control ).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
531   if(nextFocusableActor)
532   {
533     if(!nextFocusableActor.IsKeyboardFocusable())
534     {
535       // If the actor is not focusable, ask the same layout control for the next actor to focus
536       return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
537     }
538     else
539     {
540       Actor currentFocusActor = GetCurrentFocusActor();
541       Actor committedFocusActor = nextFocusableActor;
542
543       // We will try to move the focus to the actor. Emit a signal to notify the proposed actor to focus
544       // Signal handler can check the proposed actor and return a different actor if it wishes.
545       if( !mPreFocusChangeSignal.Empty() )
546       {
547         mIsWaitingKeyboardFocusChangeCommit = true;
548         committedFocusActor = mPreFocusChangeSignal.Emit(currentFocusActor, nextFocusableActor, direction);
549         mIsWaitingKeyboardFocusChangeCommit = false;
550       }
551
552       if (committedFocusActor && committedFocusActor.IsKeyboardFocusable())
553       {
554         // Whether the commited focusable actor is a layout control
555         if(IsLayoutControl(committedFocusActor))
556         {
557           // If so, move the focus inside it.
558           Toolkit::Control layoutControl = Toolkit::Control::DownCast(committedFocusActor);
559           return DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
560         }
561         else
562         {
563           // Otherwise, just set focus to the next focusable actor
564           if(committedFocusActor == nextFocusableActor)
565           {
566             // If the application hasn't changed our proposed actor, we informs the layout control we will
567             // move the focus to what the control returns. The control might wish to perform some actions
568             // before the focus is actually moved.
569             GetImplementation( control ).OnKeyboardFocusChangeCommitted( committedFocusActor );
570           }
571
572           return SetCurrentFocusActor(committedFocusActor);
573         }
574       }
575       else
576       {
577         return false;
578       }
579     }
580   }
581   else
582   {
583     // No more actor can be focused in the given direction within the same layout control.
584     return false;
585   }
586 }
587
588 bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward)
589 {
590   bool succeed = false;
591
592   // Get the parent layout control of the current focus group
593   Toolkit::Control parentLayoutControl = GetParentLayoutControl(GetCurrentFocusGroup());
594
595   while(parentLayoutControl && !succeed)
596   {
597     // If the current focus group has a parent layout control, we can probably automatically
598     // move the focus to the next focus group in the forward or backward direction.
599     Toolkit::Control::KeyboardFocus::Direction direction = forward ? Toolkit::Control::KeyboardFocus::RIGHT : Toolkit::Control::KeyboardFocus::LEFT;
600     succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction);
601     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
602   }
603
604   if(!mFocusGroupChangedSignal.Empty())
605   {
606     // Emit a focus group changed signal. The applicaton can move the focus to a new focus group
607     mFocusGroupChangedSignal.Emit(GetCurrentFocusActor(), forward);
608   }
609
610   return succeed;
611 }
612
613 void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
614 {
615   if( actor )
616   {
617     Toolkit::Control control = Toolkit::Control::DownCast( actor );
618     if( control )
619     {
620       // Notify the control that enter has been pressed on it.
621       GetImplementation( control ).KeyboardEnter();
622     }
623
624     // Send a notification for the actor.
625     if( !mFocusedActorEnterKeySignal.Empty() )
626     {
627       mFocusedActorEnterKeySignal.Emit( actor );
628     }
629   }
630 }
631
632 void KeyboardFocusManager::ClearFocus()
633 {
634   Actor actor = GetCurrentFocusActor();
635   if( actor )
636   {
637     if( mFocusIndicatorActor )
638     {
639       actor.Remove( mFocusIndicatorActor );
640     }
641
642     // Send notification for the change of focus actor
643     if( !mFocusChangedSignal.Empty() )
644     {
645       mFocusChangedSignal.Emit( actor, Actor() );
646     }
647
648     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast( actor );
649     if( currentlyFocusedControl )
650     {
651       currentlyFocusedControl.SetProperty( DevelControl::Property::STATE, DevelControl::NORMAL );
652       currentlyFocusedControl.ClearKeyInputFocus();
653     }
654   }
655
656   mCurrentFocusActor.Reset();
657   mIsFocusIndicatorShown = ( mAlwaysShowIndicator == ALWAYS_SHOW ) ? SHOW : HIDE;
658 }
659
660 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
661 {
662   mFocusGroupLoopEnabled = enabled;
663 }
664
665 bool KeyboardFocusManager::GetFocusGroupLoop() const
666 {
667   return mFocusGroupLoopEnabled;
668 }
669
670 void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup)
671 {
672   if(actor)
673   {
674     // Create/Set focus group property.
675     actor.RegisterProperty( IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE );
676   }
677 }
678
679 bool KeyboardFocusManager::IsFocusGroup(Actor actor) const
680 {
681   // Check whether the actor is a focus group
682   bool isFocusGroup = false;
683
684   if(actor)
685   {
686     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
687     if(propertyIsFocusGroup != Property::INVALID_INDEX)
688     {
689       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
690     }
691   }
692
693   return isFocusGroup;
694 }
695
696 Actor KeyboardFocusManager::GetFocusGroup(Actor actor)
697 {
698   // Go through the actor's hierarchy to check which focus group the actor belongs to
699   while (actor && !IsFocusGroup(actor))
700   {
701     actor = actor.GetParent();
702   }
703
704   return actor;
705 }
706
707 void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator)
708 {
709   if(mFocusIndicatorActor != indicator)
710   {
711     Actor currentFocusActor = GetCurrentFocusActor();
712     if(currentFocusActor)
713     {
714       // The new focus indicator should be added to the current focused actor immediately
715       if(mFocusIndicatorActor)
716       {
717         currentFocusActor.Remove(mFocusIndicatorActor);
718       }
719
720       if(indicator)
721       {
722         currentFocusActor.Add(indicator);
723       }
724     }
725
726     mFocusIndicatorActor = indicator;
727   }
728 }
729
730 Actor KeyboardFocusManager::GetFocusIndicatorActor()
731 {
732   if( ! mFocusIndicatorActor )
733   {
734     // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors
735     const std::string imageDirPath = AssetManager::GetDaliImagePath();
736     mFocusIndicatorActor = Toolkit::ImageView::New( imageDirPath + FOCUS_BORDER_IMAGE_FILE_NAME );
737
738     // Apply size constraint to the focus indicator
739     mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
740   }
741
742   mFocusIndicatorActor.SetParentOrigin( ParentOrigin::CENTER );
743   mFocusIndicatorActor.SetAnchorPoint( AnchorPoint::CENTER );
744   mFocusIndicatorActor.SetPosition(0.0f, 0.0f);
745
746   return mFocusIndicatorActor;
747 }
748
749 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
750 {
751   AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
752   bool isAccessibilityEnabled = accessibilityAdaptor.IsEnabled();
753
754   Toolkit::AccessibilityManager accessibilityManager = Toolkit::AccessibilityManager::Get();
755
756   std::string keyName = event.keyPressedName;
757
758   if( mIsFocusIndicatorShown == UNKNOWN )
759   {
760     GetConfigurationFromStyleManger();
761   }
762
763   bool isFocusStartableKey = false;
764
765   if(event.state == KeyEvent::Down)
766   {
767     if (keyName == "Left")
768     {
769       if(!isAccessibilityEnabled)
770       {
771         if(mIsFocusIndicatorShown == HIDE)
772         {
773           // Show focus indicator
774           mIsFocusIndicatorShown = SHOW;
775         }
776         else
777         {
778           // Move the focus towards left
779           MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
780         }
781
782         isFocusStartableKey = true;
783       }
784       else
785       {
786         // Move the accessibility focus backward
787         accessibilityManager.MoveFocusBackward();
788       }
789     }
790     else if (keyName == "Right")
791     {
792       if(!isAccessibilityEnabled)
793       {
794         if( mIsFocusIndicatorShown == HIDE )
795         {
796           // Show focus indicator
797           mIsFocusIndicatorShown = SHOW;
798         }
799         else
800         {
801           // Move the focus towards right
802           MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
803         }
804       }
805       else
806       {
807         // Move the accessibility focus forward
808         accessibilityManager.MoveFocusForward();
809       }
810
811       isFocusStartableKey = true;
812     }
813     else if (keyName == "Up" && !isAccessibilityEnabled)
814     {
815       if( mIsFocusIndicatorShown == HIDE )
816       {
817         // Show focus indicator
818         mIsFocusIndicatorShown = SHOW;
819       }
820       else
821       {
822         // Move the focus towards up
823         MoveFocus(Toolkit::Control::KeyboardFocus::UP);
824       }
825
826       isFocusStartableKey = true;
827     }
828     else if (keyName == "Down" && !isAccessibilityEnabled)
829     {
830       if( mIsFocusIndicatorShown == HIDE )
831       {
832         // Show focus indicator
833         mIsFocusIndicatorShown = SHOW;
834       }
835       else
836       {
837         // Move the focus towards down
838         MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
839       }
840
841       isFocusStartableKey = true;
842     }
843     else if (keyName == "Prior" && !isAccessibilityEnabled)
844     {
845       if( mIsFocusIndicatorShown == HIDE )
846       {
847         // Show focus indicator
848         mIsFocusIndicatorShown = SHOW;
849       }
850       else
851       {
852         // Move the focus towards the previous page
853         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
854       }
855
856       isFocusStartableKey = true;
857     }
858     else if (keyName == "Next" && !isAccessibilityEnabled)
859     {
860       if( mIsFocusIndicatorShown == HIDE )
861       {
862         // Show focus indicator
863         mIsFocusIndicatorShown = SHOW;
864       }
865       else
866       {
867         // Move the focus towards the next page
868         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
869       }
870
871       isFocusStartableKey = true;
872     }
873     else if (keyName == "Tab" && !isAccessibilityEnabled)
874     {
875       if( mIsFocusIndicatorShown == HIDE )
876       {
877         // Show focus indicator
878         mIsFocusIndicatorShown = SHOW;
879       }
880       else
881       {
882         // "Tab" key changes the focus group in the forward direction and
883         // "Shift-Tab" key changes it in the backward direction.
884         DoMoveFocusToNextFocusGroup(!event.IsShiftModifier());
885       }
886
887       isFocusStartableKey = true;
888     }
889     else if (keyName == "space" && !isAccessibilityEnabled)
890     {
891       if( mIsFocusIndicatorShown == HIDE )
892       {
893         // Show focus indicator
894         mIsFocusIndicatorShown = SHOW;
895       }
896
897       isFocusStartableKey = true;
898     }
899     else if (keyName == "" && !isAccessibilityEnabled)
900     {
901       // Check the fake key event for evas-plugin case
902       if( mIsFocusIndicatorShown == HIDE )
903       {
904         // Show focus indicator
905         mIsFocusIndicatorShown = SHOW;
906       }
907
908       isFocusStartableKey = true;
909     }
910     else if (keyName == "Backspace" && !isAccessibilityEnabled)
911     {
912       // Emit signal to go back to the previous view???
913     }
914     else if (keyName == "Escape" && !isAccessibilityEnabled)
915     {
916     }
917   }
918   else if(event.state == KeyEvent::Up)
919   {
920     if (keyName == "Return")
921     {
922       if((mIsFocusIndicatorShown == HIDE) && !isAccessibilityEnabled)
923       {
924         // Show focus indicator
925         mIsFocusIndicatorShown = SHOW;
926       }
927       else
928       {
929         // The focused actor has enter pressed on it
930         Actor actor;
931         if( !isAccessibilityEnabled )
932         {
933           actor = GetCurrentFocusActor();
934         }
935         else
936         {
937           actor = accessibilityManager.GetCurrentFocusActor();
938         }
939
940         if( actor )
941         {
942           DoKeyboardEnter( actor );
943         }
944       }
945
946       isFocusStartableKey = true;
947     }
948   }
949
950   if(isFocusStartableKey && ( mIsFocusIndicatorShown == SHOW ) && !isAccessibilityEnabled)
951   {
952     Actor actor = GetCurrentFocusActor();
953     if( actor )
954     {
955       if( mEnableFocusIndicator == ENABLE )
956       {
957         // Make sure the focused actor is highlighted
958         actor.Add( GetFocusIndicatorActor() );
959       }
960     }
961     else
962     {
963       // No actor is focused but keyboard focus is activated by the key press
964       // Let's try to move the initial focus
965       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
966     }
967   }
968 }
969
970 void KeyboardFocusManager::OnTouch(const TouchData& touch)
971 {
972   // if mIsFocusIndicatorShown is UNKNOWN, it means Configuration is not loaded.
973   // Try to load configuration.
974   if( mIsFocusIndicatorShown == UNKNOWN )
975   {
976     GetConfigurationFromStyleManger();
977   }
978
979   // Clear the focus when user touch the screen.
980   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
981   // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
982   if( (( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN )) && mClearFocusOnTouch )
983   {
984     ClearFocus();
985   }
986 }
987
988 void KeyboardFocusManager::OnWindowFocusChanged(Window window, bool focusIn )
989 {
990   if( focusIn && mCurrentFocusedWindow.GetHandle() != window.GetRootLayer() )
991   {
992     // Change Current Focused Window
993     Layer rootLayer = window.GetRootLayer();
994     mCurrentFocusedWindow = rootLayer;
995
996     // Get Current Focused Actor from window
997     Actor currentFocusedActor = GetFocusActorFromCurrentWindow();
998     SetCurrentFocusActor( currentFocusedActor );
999
1000     if( currentFocusedActor && ( mEnableFocusIndicator == ENABLE ) )
1001     {
1002       // Make sure the focused actor is highlighted
1003       currentFocusedActor.Add( GetFocusIndicatorActor() );
1004       mIsFocusIndicatorShown = SHOW;
1005     }
1006   }
1007 }
1008
1009 Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal()
1010 {
1011   return mPreFocusChangeSignal;
1012 }
1013
1014 Toolkit::KeyboardFocusManager::FocusChangedSignalType& KeyboardFocusManager::FocusChangedSignal()
1015 {
1016   return mFocusChangedSignal;
1017 }
1018
1019 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager::FocusGroupChangedSignal()
1020 {
1021   return mFocusGroupChangedSignal;
1022 }
1023
1024 Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal()
1025 {
1026   return mFocusedActorEnterKeySignal;
1027 }
1028
1029 bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1030 {
1031   Dali::BaseHandle handle( object );
1032
1033   bool connected( true );
1034   KeyboardFocusManager* manager = static_cast< KeyboardFocusManager* >( object ); // TypeRegistry guarantees that this is the correct type.
1035
1036   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE ) )
1037   {
1038     manager->PreFocusChangeSignal().Connect( tracker, functor );
1039   }
1040   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) )
1041   {
1042     manager->FocusChangedSignal().Connect( tracker, functor );
1043   }
1044   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED ) )
1045   {
1046     manager->FocusGroupChangedSignal().Connect( tracker, functor );
1047   }
1048   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) )
1049   {
1050     manager->FocusedActorEnterKeySignal().Connect( tracker, functor );
1051   }
1052   else
1053   {
1054     // signalName does not match any signal
1055     connected = false;
1056   }
1057
1058   return connected;
1059 }
1060
1061 void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interface)
1062 {
1063   mCustomAlgorithmInterface = &interface;
1064 }
1065
1066 void KeyboardFocusManager::EnableFocusIndicator(bool enable)
1067 {
1068   if( !enable && mFocusIndicatorActor )
1069   {
1070     mFocusIndicatorActor.Unparent();
1071   }
1072
1073   mEnableFocusIndicator = enable? ENABLE : DISABLE;
1074
1075 }
1076
1077 bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
1078 {
1079   return ( mEnableFocusIndicator == ENABLE );
1080 }
1081
1082 } // namespace Internal
1083
1084 } // namespace Toolkit
1085
1086 } // namespace Dali