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