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