Merge "Add Tab key focus movement." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyboard-focus-manager-impl.cpp
1 /*
2  * Copyright (c) 2021 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 <dali/devel-api/actors/actor-devel.h>
23 #include <dali/devel-api/adaptor-framework/lifecycle-controller.h>
24 #include <dali/devel-api/common/singleton-service.h>
25 #include <dali/integration-api/adaptor-framework/adaptor.h>
26 #include <dali/integration-api/adaptor-framework/scene-holder.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/actors/layer.h>
29 #include <dali/public-api/animation/constraints.h>
30 #include <dali/public-api/events/key-event.h>
31 #include <dali/public-api/events/touch-event.h>
32 #include <dali/public-api/object/property-map.h>
33 #include <dali/public-api/object/type-registry-helper.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <cstring> // for strcmp
36
37 // INTERNAL INCLUDES
38 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
39 #include <dali-toolkit/devel-api/controls/control-devel.h>
40 #include <dali-toolkit/devel-api/focus-manager/focus-finder.h>
41 #include <dali-toolkit/devel-api/styling/style-manager-devel.h>
42 #include <dali-toolkit/public-api/controls/control-impl.h>
43 #include <dali-toolkit/public-api/controls/control.h>
44 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
45 #include <dali-toolkit/public-api/styling/style-manager.h>
46 #include <dali/devel-api/adaptor-framework/accessibility.h>
47
48 namespace Dali
49 {
50 namespace Toolkit
51 {
52 namespace Internal
53 {
54 namespace // Unnamed namespace
55 {
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEYBOARD_FOCUS_MANAGER");
58 #endif
59
60 const char* const IS_FOCUS_GROUP_PROPERTY_NAME = "isKeyboardFocusGroup"; // This property will be replaced by a flag in Control.
61
62 const char* const FOCUS_BORDER_IMAGE_FILE_NAME = "keyboard_focus.9.png";
63
64 BaseHandle Create()
65 {
66   BaseHandle handle = KeyboardFocusManager::Get();
67
68   if(!handle)
69   {
70     SingletonService singletonService(SingletonService::Get());
71     if(singletonService)
72     {
73       Toolkit::KeyboardFocusManager manager = Toolkit::KeyboardFocusManager(new Internal::KeyboardFocusManager());
74       singletonService.Register(typeid(manager), manager);
75       handle = manager;
76     }
77   }
78
79   return handle;
80 }
81
82 DALI_TYPE_REGISTRATION_BEGIN_CREATE(Toolkit::KeyboardFocusManager, Dali::BaseHandle, Create, true)
83
84 DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardPreFocusChange", SIGNAL_PRE_FOCUS_CHANGE)
85 DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardFocusChanged", SIGNAL_FOCUS_CHANGED)
86 DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardFocusGroupChanged", SIGNAL_FOCUS_GROUP_CHANGED)
87 DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardFocusedActorEnterKey", SIGNAL_FOCUSED_ACTOR_ENTER_KEY)
88
89 DALI_TYPE_REGISTRATION_END()
90
91 const unsigned int MAX_HISTORY_AMOUNT = 30; ///< Max length of focus history stack
92
93 } // unnamed namespace
94
95 Toolkit::KeyboardFocusManager KeyboardFocusManager::Get()
96 {
97   Toolkit::KeyboardFocusManager manager;
98
99   SingletonService singletonService(SingletonService::Get());
100   if(singletonService)
101   {
102     // Check whether the keyboard focus manager is already created
103     Dali::BaseHandle handle = singletonService.GetSingleton(typeid(Toolkit::KeyboardFocusManager));
104     if(handle)
105     {
106       // If so, downcast the handle of singleton to keyboard focus manager
107       manager = Toolkit::KeyboardFocusManager(dynamic_cast<KeyboardFocusManager*>(handle.GetObjectPtr()));
108     }
109   }
110
111   return manager;
112 }
113
114 KeyboardFocusManager::KeyboardFocusManager()
115 : mPreFocusChangeSignal(),
116   mFocusChangedSignal(),
117   mFocusGroupChangedSignal(),
118   mFocusedActorEnterKeySignal(),
119   mCurrentFocusActor(),
120   mFocusIndicatorActor(),
121   mFocusHistory(),
122   mSlotDelegate(this),
123   mCustomAlgorithmInterface(NULL),
124   mCurrentFocusedWindow(),
125   mIsFocusIndicatorShown(UNKNOWN),
126   mEnableFocusIndicator(ENABLE),
127   mAlwaysShowIndicator(ALWAYS_SHOW),
128   mFocusGroupLoopEnabled(false),
129   mIsWaitingKeyboardFocusChangeCommit(false),
130   mClearFocusOnTouch(true)
131 {
132   // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown.
133
134   LifecycleController::Get().InitSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnAdaptorInit);
135 }
136
137 void KeyboardFocusManager::OnAdaptorInit()
138 {
139   if(Adaptor::IsAvailable())
140   {
141     // Retrieve all the existing scene holders
142     Dali::SceneHolderList sceneHolders = Adaptor::Get().GetSceneHolders();
143     for(auto iter = sceneHolders.begin(); iter != sceneHolders.end(); ++iter)
144     {
145       (*iter).KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
146       (*iter).TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouch);
147       Dali::Window window = DevelWindow::DownCast(*iter);
148       if(window)
149       {
150         window.FocusChangeSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWindowFocusChanged);
151       }
152     }
153
154     // Get notified when any new scene holder is created afterwards
155     Adaptor::Get().WindowCreatedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnSceneHolderCreated);
156   }
157 }
158
159 void KeyboardFocusManager::OnSceneHolderCreated(Dali::Integration::SceneHolder& sceneHolder)
160 {
161   sceneHolder.KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
162   sceneHolder.TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouch);
163   Dali::Window window = DevelWindow::DownCast(sceneHolder);
164   if(window)
165   {
166     window.FocusChangeSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWindowFocusChanged);
167   }
168 }
169
170 KeyboardFocusManager::~KeyboardFocusManager()
171 {
172 }
173
174 void KeyboardFocusManager::GetConfigurationFromStyleManger()
175 {
176   Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
177   if(styleManager)
178   {
179     Property::Map config   = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
180     mAlwaysShowIndicator   = config["alwaysShowFocus"].Get<bool>() ? ALWAYS_SHOW : NONE;
181     mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE;
182     mClearFocusOnTouch     = (mIsFocusIndicatorShown == SHOW) ? false : true;
183   }
184 }
185
186 bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor)
187 {
188   DALI_ASSERT_DEBUG(!mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?");
189
190   if(mIsFocusIndicatorShown == UNKNOWN)
191   {
192     GetConfigurationFromStyleManger();
193   }
194
195   return DoSetCurrentFocusActor(actor);
196 }
197
198 bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
199 {
200   bool success = false;
201   if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
202   {
203     Integration::SceneHolder currentWindow = Integration::SceneHolder::Get(actor);
204
205     if(currentWindow.GetRootLayer() != mCurrentFocusedWindow.GetHandle())
206     {
207       Layer rootLayer       = currentWindow.GetRootLayer();
208       mCurrentFocusedWindow = rootLayer;
209     }
210   }
211
212   Actor currentFocusedActor = GetCurrentFocusActor();
213
214   // If developer set focus on same actor, doing nothing
215   if(actor == currentFocusedActor)
216   {
217     if(!actor)
218     {
219       return false;
220     }
221     return true;
222   }
223
224   // Check whether the actor is in the stage and is keyboard focusable.
225   if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
226   {
227     if((mIsFocusIndicatorShown == SHOW) && (mEnableFocusIndicator == ENABLE))
228     {
229       actor.Add(GetFocusIndicatorActor());
230     }
231
232     // Send notification for the change of focus actor
233     if(!mFocusChangedSignal.Empty())
234     {
235       mFocusChangedSignal.Emit(currentFocusedActor, actor);
236     }
237
238     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor);
239     if(currentlyFocusedControl)
240     {
241       // Do we need it to remember if it was previously DISABLED?
242       currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL);
243       currentlyFocusedControl.ClearKeyInputFocus();
244     }
245
246     DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
247
248     // Save the current focused actor
249     mCurrentFocusActor = actor;
250
251     bool focusedWindowFound = false;
252     for(unsigned int i = 0; i < mCurrentFocusActors.size(); i++)
253     {
254       if(mCurrentFocusActors[i].first == mCurrentFocusedWindow)
255       {
256         mCurrentFocusActors[i].second = actor;
257         focusedWindowFound            = true;
258         break;
259       }
260     }
261     if(!focusedWindowFound)
262     {
263       // A new window gains the focus, so store the focused actor in that window.
264       mCurrentFocusActors.push_back(std::pair<WeakHandle<Layer>, WeakHandle<Actor> >(mCurrentFocusedWindow, actor));
265     }
266
267     Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor);
268     if(newlyFocusedControl)
269     {
270       newlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::FOCUSED);
271       newlyFocusedControl.SetKeyInputFocus();
272     }
273
274     // Push Current Focused Actor to FocusHistory
275     mFocusHistory.push_back(actor);
276
277     // Delete first element before add new element when Stack is full.
278     if(mFocusHistory.size() > MAX_HISTORY_AMOUNT)
279     {
280       FocusStackIterator beginPos = mFocusHistory.begin();
281       mFocusHistory.erase(beginPos);
282     }
283
284     DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
285     success = true;
286   }
287   else
288   {
289     DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
290   }
291
292   return success;
293 }
294
295 Actor KeyboardFocusManager::GetCurrentFocusActor()
296 {
297   Actor actor = mCurrentFocusActor.GetHandle();
298
299   if(actor && !actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
300   {
301     // If the actor has been removed from the stage, then it should not be focused
302     actor.Reset();
303     mCurrentFocusActor.Reset();
304   }
305   return actor;
306 }
307
308 Actor KeyboardFocusManager::GetFocusActorFromCurrentWindow()
309 {
310   Actor        actor;
311   unsigned int index;
312   for(index = 0; index < mCurrentFocusActors.size(); index++)
313   {
314     if(mCurrentFocusActors[index].first == mCurrentFocusedWindow)
315     {
316       actor = mCurrentFocusActors[index].second.GetHandle();
317       break;
318     }
319   }
320
321   if(actor && !actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
322   {
323     // If the actor has been removed from the window, then the window doesn't have any focused actor
324     actor.Reset();
325     mCurrentFocusActors.erase(mCurrentFocusActors.begin() + index);
326   }
327
328   return actor;
329 }
330
331 Actor KeyboardFocusManager::GetCurrentFocusGroup()
332 {
333   return GetFocusGroup(GetCurrentFocusActor());
334 }
335
336 void KeyboardFocusManager::MoveFocusBackward()
337 {
338   // Find Pre Focused Actor when the list size is more than 1
339   if(mFocusHistory.size() > 1)
340   {
341     // Delete current focused actor in history
342     mFocusHistory.pop_back();
343
344     // If pre-focused actors are not on stage or deleted, remove them in stack
345     while(mFocusHistory.size() > 0)
346     {
347       // Get pre focused actor
348       Actor target = mFocusHistory[mFocusHistory.size() - 1].GetHandle();
349
350       // Impl of Actor is not null
351       if(target && target.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
352       {
353         // Delete pre focused actor in history because it will pushed again by SetCurrentFocusActor()
354         mFocusHistory.pop_back();
355         SetCurrentFocusActor(target);
356         break;
357       }
358       else
359       {
360         // Target is empty handle or off stage. Erase from queue
361         mFocusHistory.pop_back();
362       }
363     }
364
365     // if there is no actor which can get focus, then push current focus actor in stack again
366     if(mFocusHistory.size() == 0)
367     {
368       Actor currentFocusedActor = GetCurrentFocusActor();
369       mFocusHistory.push_back(currentFocusedActor);
370     }
371   }
372 }
373
374 bool KeyboardFocusManager::IsLayoutControl(Actor actor) const
375 {
376   Toolkit::Control control = Toolkit::Control::DownCast(actor);
377   return control && GetImplementation(control).IsKeyboardNavigationSupported();
378 }
379
380 Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const
381 {
382   // Get the actor's parent layout control that supports two dimensional keyboard navigation
383   Actor rootActor;
384   Actor parent;
385   if(actor)
386   {
387     Integration::SceneHolder window = Integration::SceneHolder::Get(actor);
388     if(window)
389     {
390       rootActor = window.GetRootLayer();
391     }
392
393     parent = actor.GetParent();
394   }
395
396   while(parent && !IsLayoutControl(parent) && parent != rootActor)
397   {
398     parent = parent.GetParent();
399   }
400
401   return Toolkit::Control::DownCast(parent);
402 }
403
404 bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction)
405 {
406   Actor currentFocusActor = GetCurrentFocusActor();
407
408   bool succeed = false;
409
410   // Go through the actor's hierarchy until we find a layout control that knows how to move the focus
411   Toolkit::Control parentLayoutControl = GetParentLayoutControl(currentFocusActor);
412   while(parentLayoutControl && !succeed)
413   {
414     succeed             = DoMoveFocusWithinLayoutControl(parentLayoutControl, currentFocusActor, direction);
415     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
416   }
417
418   if(!succeed)
419   {
420     Actor nextFocusableActor;
421
422     Toolkit::Control currentFocusControl = Toolkit::Control::DownCast(currentFocusActor);
423
424     // If the current focused actor is a control, then find the next focusable actor via the focusable properties.
425     if(currentFocusControl)
426     {
427       int             actorId = -1;
428       Property::Index index   = Property::INVALID_INDEX;
429       Property::Value value;
430
431       // Find property index based upon focus direction
432       switch(direction)
433       {
434         case Toolkit::Control::KeyboardFocus::LEFT:
435         {
436           index = Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID;
437           break;
438         }
439         case Toolkit::Control::KeyboardFocus::RIGHT:
440         {
441           index = Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID;
442           break;
443         }
444         case Toolkit::Control::KeyboardFocus::UP:
445         {
446           index = Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID;
447           break;
448         }
449         case Toolkit::Control::KeyboardFocus::DOWN:
450         {
451           index = Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID;
452           break;
453         }
454         default:
455           break;
456       }
457
458       // If the focusable property is set then determine next focusable actor
459       if(index != Property::INVALID_INDEX)
460       {
461         value   = currentFocusActor.GetProperty(index);
462         actorId = value.Get<int>();
463
464         // If actor's id is valid then find actor form actor's id. The actor should be on the stage.
465         if(actorId != -1)
466         {
467           if(currentFocusActor.GetParent())
468           {
469             nextFocusableActor = currentFocusActor.GetParent().FindChildById(actorId);
470           }
471
472           if(!nextFocusableActor)
473           {
474             Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor);
475             if(window)
476             {
477               nextFocusableActor = window.GetRootLayer().FindChildById(actorId);
478             }
479           }
480         }
481       }
482     }
483
484     if(!nextFocusableActor)
485     {
486       // If the implementation of CustomAlgorithmInterface is provided then the PreFocusChangeSignal is no longer emitted.
487       if(mCustomAlgorithmInterface)
488       {
489         mIsWaitingKeyboardFocusChangeCommit = true;
490         nextFocusableActor                  = mCustomAlgorithmInterface->GetNextFocusableActor(currentFocusActor, Actor(), direction);
491         mIsWaitingKeyboardFocusChangeCommit = false;
492       }
493       else if(!mPreFocusChangeSignal.Empty())
494       {
495         // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to
496         mIsWaitingKeyboardFocusChangeCommit = true;
497         nextFocusableActor                  = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction);
498         mIsWaitingKeyboardFocusChangeCommit = false;
499       }
500       else
501       {
502         // We should find it among the actors nearby.
503         nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(currentFocusActor, direction);
504       }
505     }
506
507     if(nextFocusableActor && nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
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.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
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.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
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.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
743   mFocusIndicatorActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
744   mFocusIndicatorActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
745
746   return mFocusIndicatorActor;
747 }
748
749 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
750 {
751   std::string keyName = event.GetKeyName();
752
753   if(mIsFocusIndicatorShown == UNKNOWN)
754   {
755     GetConfigurationFromStyleManger();
756   }
757
758   bool isFocusStartableKey = false;
759
760   if(event.GetState() == KeyEvent::DOWN)
761   {
762     if(keyName == "Left")
763     {
764       if(!mIsFocusIndicatorShown)
765       {
766         if(mIsFocusIndicatorShown == HIDE)
767         {
768           // Show focus indicator
769           mIsFocusIndicatorShown = SHOW;
770         }
771         else
772         {
773           // Move the focus towards left
774           MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
775         }
776
777         isFocusStartableKey = true;
778       }
779       else
780       {
781         // Move the focus towards left
782         MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
783       }
784
785       isFocusStartableKey = true;
786     }
787     else if(keyName == "Right")
788     {
789       if(!mIsFocusIndicatorShown)
790       {
791         if(mIsFocusIndicatorShown == HIDE)
792         {
793           // Show focus indicator
794           mIsFocusIndicatorShown = SHOW;
795         }
796         else
797         {
798           // Move the focus towards right
799           MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
800         }
801       }
802       else
803       {
804         // Move the focus towards right
805         MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
806       }
807
808       isFocusStartableKey = true;
809     }
810     else if(keyName == "Up")
811     {
812       if(mIsFocusIndicatorShown == HIDE)
813       {
814         // Show focus indicator
815         mIsFocusIndicatorShown = SHOW;
816       }
817       else
818       {
819         // Move the focus towards up
820         MoveFocus(Toolkit::Control::KeyboardFocus::UP);
821       }
822
823       isFocusStartableKey = true;
824     }
825     else if(keyName == "Down")
826     {
827       if(mIsFocusIndicatorShown == HIDE)
828       {
829         // Show focus indicator
830         mIsFocusIndicatorShown = SHOW;
831       }
832       else
833       {
834         // Move the focus towards down
835         MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
836       }
837
838       isFocusStartableKey = true;
839     }
840     else if(keyName == "Prior")
841     {
842       if(mIsFocusIndicatorShown == HIDE)
843       {
844         // Show focus indicator
845         mIsFocusIndicatorShown = SHOW;
846       }
847       else
848       {
849         // Move the focus towards the previous page
850         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
851       }
852
853       isFocusStartableKey = true;
854     }
855     else if(keyName == "Next")
856     {
857       if(mIsFocusIndicatorShown == HIDE)
858       {
859         // Show focus indicator
860         mIsFocusIndicatorShown = SHOW;
861       }
862       else
863       {
864         // Move the focus towards the next page
865         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
866       }
867
868       isFocusStartableKey = true;
869     }
870     else if(keyName == "Tab")
871     {
872       if(mIsFocusIndicatorShown == HIDE)
873       {
874         // Show focus indicator
875         mIsFocusIndicatorShown = SHOW;
876       }
877       else
878       {
879         // "Tab" key changes the focus group in the forward direction and
880         // "Shift-Tab" key changes it in the backward direction.
881         if(!DoMoveFocusToNextFocusGroup(!event.IsShiftModifier()))
882         {
883           // If the focus group is not changed, Move the focus towards right, "Shift-Tap" key moves the focus towards left.
884           if(!MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::LEFT : Toolkit::Control::KeyboardFocus::RIGHT))
885           {
886             // If the focus is not moved, Move the focus towards down, "Shift-Tap" key moves the focus towards up.
887             MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::UP : Toolkit::Control::KeyboardFocus::DOWN);
888           }
889         }
890       }
891
892       isFocusStartableKey = true;
893     }
894     else if(keyName == "space")
895     {
896       if(mIsFocusIndicatorShown == HIDE)
897       {
898         // Show focus indicator
899         mIsFocusIndicatorShown = SHOW;
900       }
901
902       isFocusStartableKey = true;
903     }
904     else if(keyName == "")
905     {
906       // Check the fake key event for evas-plugin case
907       if(mIsFocusIndicatorShown == HIDE)
908       {
909         // Show focus indicator
910         mIsFocusIndicatorShown = SHOW;
911       }
912
913       isFocusStartableKey = true;
914     }
915     else if(keyName == "Backspace")
916     {
917       // Emit signal to go back to the previous view???
918     }
919     else if(keyName == "Escape")
920     {
921     }
922   }
923   else if(event.GetState() == KeyEvent::UP)
924   {
925     if(keyName == "Return")
926     {
927       if(mIsFocusIndicatorShown == HIDE)
928       {
929         // Show focus indicator
930         mIsFocusIndicatorShown = SHOW;
931       }
932       else
933       {
934         // The focused actor has enter pressed on it
935         Actor actor = GetCurrentFocusActor();
936         if(actor)
937         {
938           DoKeyboardEnter(actor);
939         }
940       }
941
942       isFocusStartableKey = true;
943     }
944   }
945
946   if(isFocusStartableKey && mIsFocusIndicatorShown == SHOW)
947   {
948     Actor actor = GetCurrentFocusActor();
949     if(actor)
950     {
951       if(mEnableFocusIndicator == ENABLE)
952       {
953         // Make sure the focused actor is highlighted
954         actor.Add(GetFocusIndicatorActor());
955       }
956     }
957     else
958     {
959       // No actor is focused but keyboard focus is activated by the key press
960       // Let's try to move the initial focus
961       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
962     }
963   }
964 }
965
966 void KeyboardFocusManager::OnTouch(const TouchEvent& touch)
967 {
968   // if mIsFocusIndicatorShown is UNKNOWN, it means Configuration is not loaded.
969   // Try to load configuration.
970   if(mIsFocusIndicatorShown == UNKNOWN)
971   {
972     GetConfigurationFromStyleManger();
973   }
974
975   // Clear the focus when user touch the screen.
976   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
977   if(((touch.GetPointCount() < 1) || (touch.GetState(0) == PointState::DOWN)))
978   {
979     // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
980     if(mClearFocusOnTouch)
981     {
982       ClearFocus();
983     }
984
985     // If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor
986     Actor hitActor = touch.GetHitActor(0);
987     if(hitActor && hitActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && hitActor.GetProperty<bool>(DevelActor::Property::TOUCH_FOCUSABLE))
988     {
989       SetCurrentFocusActor(hitActor);
990     }
991   }
992 }
993
994 void KeyboardFocusManager::OnWindowFocusChanged(Window window, bool focusIn)
995 {
996   if(focusIn && mCurrentFocusedWindow.GetHandle() != window.GetRootLayer())
997   {
998     // Change Current Focused Window
999     Layer rootLayer       = window.GetRootLayer();
1000     mCurrentFocusedWindow = rootLayer;
1001
1002     // Get Current Focused Actor from window
1003     Actor currentFocusedActor = GetFocusActorFromCurrentWindow();
1004     SetCurrentFocusActor(currentFocusedActor);
1005
1006     if(currentFocusedActor && (mEnableFocusIndicator == ENABLE))
1007     {
1008       // Make sure the focused actor is highlighted
1009       currentFocusedActor.Add(GetFocusIndicatorActor());
1010       mIsFocusIndicatorShown = SHOW;
1011     }
1012   }
1013 }
1014
1015 Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal()
1016 {
1017   return mPreFocusChangeSignal;
1018 }
1019
1020 Toolkit::KeyboardFocusManager::FocusChangedSignalType& KeyboardFocusManager::FocusChangedSignal()
1021 {
1022   return mFocusChangedSignal;
1023 }
1024
1025 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager::FocusGroupChangedSignal()
1026 {
1027   return mFocusGroupChangedSignal;
1028 }
1029
1030 Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal()
1031 {
1032   return mFocusedActorEnterKeySignal;
1033 }
1034
1035 bool KeyboardFocusManager::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1036 {
1037   Dali::BaseHandle handle(object);
1038
1039   bool                  connected(true);
1040   KeyboardFocusManager* manager = static_cast<KeyboardFocusManager*>(object); // TypeRegistry guarantees that this is the correct type.
1041
1042   if(0 == strcmp(signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE))
1043   {
1044     manager->PreFocusChangeSignal().Connect(tracker, functor);
1045   }
1046   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_CHANGED))
1047   {
1048     manager->FocusChangedSignal().Connect(tracker, functor);
1049   }
1050   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED))
1051   {
1052     manager->FocusGroupChangedSignal().Connect(tracker, functor);
1053   }
1054   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY))
1055   {
1056     manager->FocusedActorEnterKeySignal().Connect(tracker, functor);
1057   }
1058   else
1059   {
1060     // signalName does not match any signal
1061     connected = false;
1062   }
1063
1064   return connected;
1065 }
1066
1067 void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interface)
1068 {
1069   mCustomAlgorithmInterface = &interface;
1070 }
1071
1072 void KeyboardFocusManager::EnableFocusIndicator(bool enable)
1073 {
1074   if(!enable && mFocusIndicatorActor)
1075   {
1076     mFocusIndicatorActor.Unparent();
1077   }
1078
1079   mEnableFocusIndicator = enable ? ENABLE : DISABLE;
1080 }
1081
1082 bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
1083 {
1084   return (mEnableFocusIndicator == ENABLE);
1085 }
1086
1087 } // namespace Internal
1088
1089 } // namespace Toolkit
1090
1091 } // namespace Dali