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