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