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