[dali_2.1.2] 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/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         nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(currentFocusActor, direction);
521       }
522     }
523
524     if(nextFocusableActor && nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
525     {
526       // Whether the next focusable actor is a layout control
527       if(IsLayoutControl(nextFocusableActor))
528       {
529         // If so, move the focus inside it.
530         Toolkit::Control layoutControl = Toolkit::Control::DownCast(nextFocusableActor);
531         succeed                        = DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
532       }
533       else
534       {
535         // Otherwise, just set focus to the next focusable actor
536         succeed = SetCurrentFocusActor(nextFocusableActor);
537       }
538     }
539   }
540
541   return succeed;
542 }
543
544 bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control control, Actor actor, Toolkit::Control::KeyboardFocus::Direction direction)
545 {
546   // Ask the control for the next actor to focus
547   Actor nextFocusableActor = GetImplementation(control).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
548   if(nextFocusableActor)
549   {
550     if(!nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
551     {
552       // If the actor is not focusable, ask the same layout control for the next actor to focus
553       return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
554     }
555     else
556     {
557       Actor currentFocusActor   = GetCurrentFocusActor();
558       Actor committedFocusActor = nextFocusableActor;
559
560       // We will try to move the focus to the actor. Emit a signal to notify the proposed actor to focus
561       // Signal handler can check the proposed actor and return a different actor if it wishes.
562       if(!mPreFocusChangeSignal.Empty())
563       {
564         mIsWaitingKeyboardFocusChangeCommit = true;
565         committedFocusActor                 = mPreFocusChangeSignal.Emit(currentFocusActor, nextFocusableActor, direction);
566         mIsWaitingKeyboardFocusChangeCommit = false;
567       }
568
569       if(committedFocusActor && committedFocusActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
570       {
571         // Whether the commited focusable actor is a layout control
572         if(IsLayoutControl(committedFocusActor))
573         {
574           // If so, move the focus inside it.
575           Toolkit::Control layoutControl = Toolkit::Control::DownCast(committedFocusActor);
576           return DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
577         }
578         else
579         {
580           // Otherwise, just set focus to the next focusable actor
581           if(committedFocusActor == nextFocusableActor)
582           {
583             // If the application hasn't changed our proposed actor, we informs the layout control we will
584             // move the focus to what the control returns. The control might wish to perform some actions
585             // before the focus is actually moved.
586             GetImplementation(control).OnKeyboardFocusChangeCommitted(committedFocusActor);
587           }
588
589           return SetCurrentFocusActor(committedFocusActor);
590         }
591       }
592       else
593       {
594         return false;
595       }
596     }
597   }
598   else
599   {
600     // No more actor can be focused in the given direction within the same layout control.
601     return false;
602   }
603 }
604
605 bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward)
606 {
607   bool succeed = false;
608
609   // Get the parent layout control of the current focus group
610   Toolkit::Control parentLayoutControl = GetParentLayoutControl(GetCurrentFocusGroup());
611
612   while(parentLayoutControl && !succeed)
613   {
614     // If the current focus group has a parent layout control, we can probably automatically
615     // move the focus to the next focus group in the forward or backward direction.
616     Toolkit::Control::KeyboardFocus::Direction direction = forward ? Toolkit::Control::KeyboardFocus::RIGHT : Toolkit::Control::KeyboardFocus::LEFT;
617     succeed                                              = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction);
618     parentLayoutControl                                  = GetParentLayoutControl(parentLayoutControl);
619   }
620
621   if(!mFocusGroupChangedSignal.Empty())
622   {
623     // Emit a focus group changed signal. The applicaton can move the focus to a new focus group
624     mFocusGroupChangedSignal.Emit(GetCurrentFocusActor(), forward);
625   }
626
627   return succeed;
628 }
629
630 void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
631 {
632   if(actor)
633   {
634     Toolkit::Control control = Toolkit::Control::DownCast(actor);
635     if(control)
636     {
637       // Notify the control that enter has been pressed on it.
638       GetImplementation(control).KeyboardEnter();
639     }
640
641     // Send a notification for the actor.
642     if(!mFocusedActorEnterKeySignal.Empty())
643     {
644       mFocusedActorEnterKeySignal.Emit(actor);
645     }
646   }
647 }
648
649 void KeyboardFocusManager::ClearFocus()
650 {
651   Actor actor = GetCurrentFocusActor();
652   if(actor)
653   {
654     if(mFocusIndicatorActor)
655     {
656       actor.Remove(mFocusIndicatorActor);
657     }
658
659     // Send notification for the change of focus actor
660     if(!mFocusChangedSignal.Empty())
661     {
662       mFocusChangedSignal.Emit(actor, Actor());
663     }
664
665     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(actor);
666     if(currentlyFocusedControl)
667     {
668       currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL);
669       currentlyFocusedControl.ClearKeyInputFocus();
670     }
671   }
672
673   mCurrentFocusActor.Reset();
674   mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE;
675 }
676
677 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
678 {
679   mFocusGroupLoopEnabled = enabled;
680 }
681
682 bool KeyboardFocusManager::GetFocusGroupLoop() const
683 {
684   return mFocusGroupLoopEnabled;
685 }
686
687 void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup)
688 {
689   if(actor)
690   {
691     // Create/Set focus group property.
692     actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE);
693   }
694 }
695
696 bool KeyboardFocusManager::IsFocusGroup(Actor actor) const
697 {
698   // Check whether the actor is a focus group
699   bool isFocusGroup = false;
700
701   if(actor)
702   {
703     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
704     if(propertyIsFocusGroup != Property::INVALID_INDEX)
705     {
706       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
707     }
708   }
709
710   return isFocusGroup;
711 }
712
713 Actor KeyboardFocusManager::GetFocusGroup(Actor actor)
714 {
715   // Go through the actor's hierarchy to check which focus group the actor belongs to
716   while(actor && !IsFocusGroup(actor))
717   {
718     actor = actor.GetParent();
719   }
720
721   return actor;
722 }
723
724 void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator)
725 {
726   if(mFocusIndicatorActor != indicator)
727   {
728     Actor currentFocusActor = GetCurrentFocusActor();
729     if(currentFocusActor)
730     {
731       // The new focus indicator should be added to the current focused actor immediately
732       if(mFocusIndicatorActor)
733       {
734         currentFocusActor.Remove(mFocusIndicatorActor);
735       }
736
737       if(indicator)
738       {
739         currentFocusActor.Add(indicator);
740       }
741     }
742
743     mFocusIndicatorActor = indicator;
744   }
745 }
746
747 Actor KeyboardFocusManager::GetFocusIndicatorActor()
748 {
749   if(!mFocusIndicatorActor)
750   {
751     // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors
752     const std::string imageDirPath = AssetManager::GetDaliImagePath();
753     mFocusIndicatorActor           = Toolkit::ImageView::New(imageDirPath + FOCUS_BORDER_IMAGE_FILE_NAME);
754
755     // Apply size constraint to the focus indicator
756     mFocusIndicatorActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
757   }
758
759   mFocusIndicatorActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
760   mFocusIndicatorActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
761   mFocusIndicatorActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
762
763   return mFocusIndicatorActor;
764 }
765
766 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
767 {
768   std::string keyName = event.GetKeyName();
769
770   if(mIsFocusIndicatorShown == UNKNOWN)
771   {
772     GetConfigurationFromStyleManger();
773   }
774
775   bool isFocusStartableKey = false;
776
777   if(event.GetState() == KeyEvent::DOWN)
778   {
779     if(keyName == "Left")
780     {
781       if(!mIsFocusIndicatorShown)
782       {
783         if(mIsFocusIndicatorShown == HIDE)
784         {
785           // Show focus indicator
786           mIsFocusIndicatorShown = SHOW;
787         }
788         else
789         {
790           // Move the focus towards left
791           MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
792         }
793
794         isFocusStartableKey = true;
795       }
796       else
797       {
798         // Move the focus towards left
799         MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
800       }
801
802       isFocusStartableKey = true;
803     }
804     else if(keyName == "Right")
805     {
806       if(!mIsFocusIndicatorShown)
807       {
808         if(mIsFocusIndicatorShown == HIDE)
809         {
810           // Show focus indicator
811           mIsFocusIndicatorShown = SHOW;
812         }
813         else
814         {
815           // Move the focus towards right
816           MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
817         }
818       }
819       else
820       {
821         // Move the focus towards right
822         MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
823       }
824
825       isFocusStartableKey = true;
826     }
827     else if(keyName == "Up")
828     {
829       if(mIsFocusIndicatorShown == HIDE)
830       {
831         // Show focus indicator
832         mIsFocusIndicatorShown = SHOW;
833       }
834       else
835       {
836         // Move the focus towards up
837         MoveFocus(Toolkit::Control::KeyboardFocus::UP);
838       }
839
840       isFocusStartableKey = true;
841     }
842     else if(keyName == "Down")
843     {
844       if(mIsFocusIndicatorShown == HIDE)
845       {
846         // Show focus indicator
847         mIsFocusIndicatorShown = SHOW;
848       }
849       else
850       {
851         // Move the focus towards down
852         MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
853       }
854
855       isFocusStartableKey = true;
856     }
857     else if(keyName == "Prior")
858     {
859       if(mIsFocusIndicatorShown == HIDE)
860       {
861         // Show focus indicator
862         mIsFocusIndicatorShown = SHOW;
863       }
864       else
865       {
866         // Move the focus towards the previous page
867         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
868       }
869
870       isFocusStartableKey = true;
871     }
872     else if(keyName == "Next")
873     {
874       if(mIsFocusIndicatorShown == HIDE)
875       {
876         // Show focus indicator
877         mIsFocusIndicatorShown = SHOW;
878       }
879       else
880       {
881         // Move the focus towards the next page
882         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
883       }
884
885       isFocusStartableKey = true;
886     }
887     else if(keyName == "Tab")
888     {
889       if(mIsFocusIndicatorShown == HIDE)
890       {
891         // Show focus indicator
892         mIsFocusIndicatorShown = SHOW;
893       }
894       else
895       {
896         // "Tab" key changes the focus group in the forward direction and
897         // "Shift-Tab" key changes it in the backward direction.
898         if(!DoMoveFocusToNextFocusGroup(!event.IsShiftModifier()))
899         {
900           // If the focus group is not changed, Move the focus towards right, "Shift-Tap" key moves the focus towards left.
901           if(!MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::LEFT : Toolkit::Control::KeyboardFocus::RIGHT))
902           {
903             // If the focus is not moved, Move the focus towards down, "Shift-Tap" key moves the focus towards up.
904             MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::UP : Toolkit::Control::KeyboardFocus::DOWN);
905           }
906         }
907       }
908
909       isFocusStartableKey = true;
910     }
911     else if(keyName == "space")
912     {
913       if(mIsFocusIndicatorShown == HIDE)
914       {
915         // Show focus indicator
916         mIsFocusIndicatorShown = SHOW;
917       }
918
919       isFocusStartableKey = true;
920     }
921     else if(keyName == "")
922     {
923       // Check the fake key event for evas-plugin case
924       if(mIsFocusIndicatorShown == HIDE)
925       {
926         // Show focus indicator
927         mIsFocusIndicatorShown = SHOW;
928       }
929
930       isFocusStartableKey = true;
931     }
932     else if(keyName == "Backspace")
933     {
934       // Emit signal to go back to the previous view???
935     }
936     else if(keyName == "Escape")
937     {
938     }
939   }
940   else if(event.GetState() == KeyEvent::UP)
941   {
942     if(keyName == "Return")
943     {
944       if(mIsFocusIndicatorShown == HIDE)
945       {
946         // Show focus indicator
947         mIsFocusIndicatorShown = SHOW;
948       }
949       else
950       {
951         // The focused actor has enter pressed on it
952         Actor actor = GetCurrentFocusActor();
953         if(actor)
954         {
955           DoKeyboardEnter(actor);
956         }
957       }
958
959       isFocusStartableKey = true;
960     }
961   }
962
963   if(isFocusStartableKey && mIsFocusIndicatorShown == SHOW)
964   {
965     Actor actor = GetCurrentFocusActor();
966     if(actor)
967     {
968       if(mEnableFocusIndicator == ENABLE)
969       {
970         // Make sure the focused actor is highlighted
971         actor.Add(GetFocusIndicatorActor());
972       }
973     }
974     else
975     {
976       // No actor is focused but keyboard focus is activated by the key press
977       // Let's try to move the initial focus
978       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
979     }
980   }
981 }
982
983 void KeyboardFocusManager::OnTouch(const TouchEvent& touch)
984 {
985   // if mIsFocusIndicatorShown is UNKNOWN, it means Configuration is not loaded.
986   // Try to load configuration.
987   if(mIsFocusIndicatorShown == UNKNOWN)
988   {
989     GetConfigurationFromStyleManger();
990   }
991
992   // Clear the focus when user touch the screen.
993   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
994   if(((touch.GetPointCount() < 1) || (touch.GetState(0) == PointState::DOWN)))
995   {
996     // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
997     if(mClearFocusOnTouch)
998     {
999       ClearFocus();
1000     }
1001
1002     // If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor
1003     Actor hitActor = touch.GetHitActor(0);
1004     if(hitActor && hitActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && hitActor.GetProperty<bool>(DevelActor::Property::TOUCH_FOCUSABLE))
1005     {
1006       SetCurrentFocusActor(hitActor);
1007     }
1008   }
1009 }
1010
1011 void KeyboardFocusManager::OnWindowFocusChanged(Window window, bool focusIn)
1012 {
1013   if(focusIn && mCurrentFocusedWindow.GetHandle() != window.GetRootLayer())
1014   {
1015     // Change Current Focused Window
1016     Layer rootLayer       = window.GetRootLayer();
1017     mCurrentFocusedWindow = rootLayer;
1018
1019     // Get Current Focused Actor from window
1020     Actor currentFocusedActor = GetFocusActorFromCurrentWindow();
1021     SetCurrentFocusActor(currentFocusedActor);
1022
1023     if(currentFocusedActor && (mEnableFocusIndicator == ENABLE))
1024     {
1025       // Make sure the focused actor is highlighted
1026       currentFocusedActor.Add(GetFocusIndicatorActor());
1027       mIsFocusIndicatorShown = SHOW;
1028     }
1029   }
1030 }
1031
1032 Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal()
1033 {
1034   return mPreFocusChangeSignal;
1035 }
1036
1037 Toolkit::KeyboardFocusManager::FocusChangedSignalType& KeyboardFocusManager::FocusChangedSignal()
1038 {
1039   return mFocusChangedSignal;
1040 }
1041
1042 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager::FocusGroupChangedSignal()
1043 {
1044   return mFocusGroupChangedSignal;
1045 }
1046
1047 Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal()
1048 {
1049   return mFocusedActorEnterKeySignal;
1050 }
1051
1052 bool KeyboardFocusManager::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1053 {
1054   Dali::BaseHandle handle(object);
1055
1056   bool                  connected(true);
1057   KeyboardFocusManager* manager = static_cast<KeyboardFocusManager*>(object); // TypeRegistry guarantees that this is the correct type.
1058
1059   if(0 == strcmp(signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE))
1060   {
1061     manager->PreFocusChangeSignal().Connect(tracker, functor);
1062   }
1063   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_CHANGED))
1064   {
1065     manager->FocusChangedSignal().Connect(tracker, functor);
1066   }
1067   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED))
1068   {
1069     manager->FocusGroupChangedSignal().Connect(tracker, functor);
1070   }
1071   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY))
1072   {
1073     manager->FocusedActorEnterKeySignal().Connect(tracker, functor);
1074   }
1075   else
1076   {
1077     // signalName does not match any signal
1078     connected = false;
1079   }
1080
1081   return connected;
1082 }
1083
1084 void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interface)
1085 {
1086   mCustomAlgorithmInterface = &interface;
1087 }
1088
1089 void KeyboardFocusManager::EnableFocusIndicator(bool enable)
1090 {
1091   if(!enable && mFocusIndicatorActor)
1092   {
1093     mFocusIndicatorActor.Unparent();
1094   }
1095
1096   mEnableFocusIndicator = enable ? ENABLE : DISABLE;
1097 }
1098
1099 bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
1100 {
1101   return (mEnableFocusIndicator == ENABLE);
1102 }
1103
1104 void KeyboardFocusManager::EnableDefaultAlgorithm(bool enable)
1105 {
1106   mEnableDefaultAlgorithm = enable;
1107 }
1108
1109 bool KeyboardFocusManager::IsDefaultAlgorithmEnabled() const
1110 {
1111   return mEnableDefaultAlgorithm;
1112 }
1113
1114 } // namespace Internal
1115
1116 } // namespace Toolkit
1117
1118 } // namespace Dali