Merge "Add deviceName to GetNextFocusableView() in CustomFocusAlgorithm." into devel...
[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, const std::string& deviceName)
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, deviceName);
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   const std::string& keyName = event.GetKeyName();
789   const std::string& deviceName = event.GetDeviceName();
790
791   if(mIsFocusIndicatorShown == UNKNOWN)
792   {
793     GetConfigurationFromStyleManger();
794   }
795
796   bool isFocusStartableKey = false;
797
798   if(event.GetState() == KeyEvent::DOWN)
799   {
800     if(keyName == "Left")
801     {
802       if(mIsFocusIndicatorShown == HIDE)
803       {
804         // Show focus indicator
805         mIsFocusIndicatorShown = SHOW;
806       }
807       else
808       {
809         // Move the focus towards left
810         MoveFocus(Toolkit::Control::KeyboardFocus::LEFT, deviceName);
811       }
812
813       isFocusStartableKey = true;
814     }
815     else if(keyName == "Right")
816     {
817       if(mIsFocusIndicatorShown == HIDE)
818       {
819         // Show focus indicator
820         mIsFocusIndicatorShown = SHOW;
821       }
822       else
823       {
824         // Move the focus towards right
825         MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT, deviceName);
826       }
827
828       isFocusStartableKey = true;
829     }
830     else if(keyName == "Up")
831     {
832       if(mIsFocusIndicatorShown == HIDE)
833       {
834         // Show focus indicator
835         mIsFocusIndicatorShown = SHOW;
836       }
837       else
838       {
839         // Move the focus towards up
840         MoveFocus(Toolkit::Control::KeyboardFocus::UP, deviceName);
841       }
842
843       isFocusStartableKey = true;
844     }
845     else if(keyName == "Down")
846     {
847       if(mIsFocusIndicatorShown == HIDE)
848       {
849         // Show focus indicator
850         mIsFocusIndicatorShown = SHOW;
851       }
852       else
853       {
854         // Move the focus towards down
855         MoveFocus(Toolkit::Control::KeyboardFocus::DOWN, deviceName);
856       }
857
858       isFocusStartableKey = true;
859     }
860     else if(keyName == "Prior")
861     {
862       if(mIsFocusIndicatorShown == HIDE)
863       {
864         // Show focus indicator
865         mIsFocusIndicatorShown = SHOW;
866       }
867       else
868       {
869         // Move the focus towards the previous page
870         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP, deviceName);
871       }
872
873       isFocusStartableKey = true;
874     }
875     else if(keyName == "Next")
876     {
877       if(mIsFocusIndicatorShown == HIDE)
878       {
879         // Show focus indicator
880         mIsFocusIndicatorShown = SHOW;
881       }
882       else
883       {
884         // Move the focus towards the next page
885         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN, deviceName);
886       }
887
888       isFocusStartableKey = true;
889     }
890     else if(keyName == "Tab")
891     {
892       if(mIsFocusIndicatorShown == HIDE)
893       {
894         // Show focus indicator
895         mIsFocusIndicatorShown = SHOW;
896       }
897       else
898       {
899         // "Tab" key changes the focus group in the forward direction and
900         // "Shift-Tab" key changes it in the backward direction.
901         if(!DoMoveFocusToNextFocusGroup(!event.IsShiftModifier()))
902         {
903           // If the focus group is not changed, Move the focus towards forward, "Shift-Tap" key moves the focus towards backward.
904           MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::BACKWARD : Toolkit::Control::KeyboardFocus::FORWARD, deviceName);
905         }
906       }
907
908       isFocusStartableKey = true;
909     }
910     else if(keyName == "space")
911     {
912       if(mIsFocusIndicatorShown == HIDE)
913       {
914         // Show focus indicator
915         mIsFocusIndicatorShown = SHOW;
916       }
917
918       isFocusStartableKey = true;
919     }
920     else if(keyName == "")
921     {
922       // Check the fake key event for evas-plugin case
923       if(mIsFocusIndicatorShown == HIDE)
924       {
925         // Show focus indicator
926         mIsFocusIndicatorShown = SHOW;
927       }
928
929       isFocusStartableKey = true;
930     }
931     else if(keyName == "Backspace")
932     {
933       // Emit signal to go back to the previous view???
934     }
935     else if(keyName == "Escape")
936     {
937     }
938   }
939   else if(event.GetState() == KeyEvent::UP)
940   {
941     if(keyName == "Return")
942     {
943       if(mIsFocusIndicatorShown == HIDE)
944       {
945         // Show focus indicator
946         mIsFocusIndicatorShown = SHOW;
947       }
948       else
949       {
950         // The focused actor has enter pressed on it
951         Actor actor = GetCurrentFocusActor();
952         if(actor)
953         {
954           DoKeyboardEnter(actor);
955         }
956       }
957
958       isFocusStartableKey = true;
959     }
960   }
961
962   if(isFocusStartableKey && mIsFocusIndicatorShown == SHOW)
963   {
964     Actor actor = GetCurrentFocusActor();
965     if(actor)
966     {
967       if(mEnableFocusIndicator == ENABLE)
968       {
969         // Make sure the focused actor is highlighted
970         actor.Add(GetFocusIndicatorActor());
971       }
972     }
973     else
974     {
975       // No actor is focused but keyboard focus is activated by the key press
976       // Let's try to move the initial focus
977       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT, deviceName);
978     }
979   }
980 }
981
982 void KeyboardFocusManager::OnTouch(const TouchEvent& touch)
983 {
984   // if mIsFocusIndicatorShown is UNKNOWN, it means Configuration is not loaded.
985   // Try to load configuration.
986   if(mIsFocusIndicatorShown == UNKNOWN)
987   {
988     GetConfigurationFromStyleManger();
989   }
990
991   // Clear the focus when user touch the screen.
992   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
993   if(((touch.GetPointCount() < 1) || (touch.GetState(0) == PointState::DOWN)))
994   {
995     // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
996     if(mClearFocusOnTouch)
997     {
998       ClearFocus();
999     }
1000
1001     // If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor
1002     Actor hitActor = touch.GetHitActor(0);
1003     if(hitActor && hitActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && hitActor.GetProperty<bool>(DevelActor::Property::TOUCH_FOCUSABLE))
1004     {
1005       SetCurrentFocusActor(hitActor);
1006     }
1007   }
1008 }
1009
1010 bool KeyboardFocusManager::OnWheelEvent(const WheelEvent& event)
1011 {
1012   bool consumed = false;
1013   Actor actor = GetCurrentFocusActor();
1014   if(actor)
1015   {
1016     // Notify the actor about the wheel event
1017     consumed = EmitWheelSignals(actor, event);
1018   }
1019   return consumed;
1020 }
1021
1022 bool KeyboardFocusManager::EmitWheelSignals(Actor actor, const WheelEvent& event)
1023 {
1024   bool consumed = false;
1025
1026   if(actor)
1027   {
1028     Dali::Actor oldParent(actor.GetParent());
1029
1030     // Only do the conversion and emit the signal if the actor's wheel signal has connections.
1031     if(!actor.WheelEventSignal().Empty())
1032     {
1033       // Emit the signal to the parent
1034       consumed = actor.WheelEventSignal().Emit(actor, event);
1035     }
1036     // if actor doesn't consume WheelEvent, give WheelEvent to its parent.
1037     if(!consumed)
1038     {
1039       // The actor may have been removed/reparented during the signal callbacks.
1040       Dali::Actor parent = actor.GetParent();
1041
1042       if(parent &&
1043          (parent == oldParent))
1044       {
1045         consumed = EmitWheelSignals(parent, event);
1046       }
1047     }
1048   }
1049
1050   return consumed;
1051 }
1052
1053 void KeyboardFocusManager::OnWindowFocusChanged(Window window, bool focusIn)
1054 {
1055   if(focusIn && mCurrentFocusedWindow.GetHandle() != window.GetRootLayer())
1056   {
1057     // Change Current Focused Window
1058     Layer rootLayer       = window.GetRootLayer();
1059     mCurrentFocusedWindow = rootLayer;
1060
1061     // Get Current Focused Actor from window
1062     Actor currentFocusedActor = GetFocusActorFromCurrentWindow();
1063     SetCurrentFocusActor(currentFocusedActor);
1064
1065     if(currentFocusedActor && (mEnableFocusIndicator == ENABLE))
1066     {
1067       // Make sure the focused actor is highlighted
1068       currentFocusedActor.Add(GetFocusIndicatorActor());
1069       mIsFocusIndicatorShown = SHOW;
1070     }
1071   }
1072 }
1073
1074 Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal()
1075 {
1076   return mPreFocusChangeSignal;
1077 }
1078
1079 Toolkit::KeyboardFocusManager::FocusChangedSignalType& KeyboardFocusManager::FocusChangedSignal()
1080 {
1081   return mFocusChangedSignal;
1082 }
1083
1084 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager::FocusGroupChangedSignal()
1085 {
1086   return mFocusGroupChangedSignal;
1087 }
1088
1089 Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal()
1090 {
1091   return mFocusedActorEnterKeySignal;
1092 }
1093
1094 bool KeyboardFocusManager::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1095 {
1096   Dali::BaseHandle handle(object);
1097
1098   bool                  connected(true);
1099   KeyboardFocusManager* manager = static_cast<KeyboardFocusManager*>(object); // TypeRegistry guarantees that this is the correct type.
1100
1101   if(0 == strcmp(signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE))
1102   {
1103     manager->PreFocusChangeSignal().Connect(tracker, functor);
1104   }
1105   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_CHANGED))
1106   {
1107     manager->FocusChangedSignal().Connect(tracker, functor);
1108   }
1109   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED))
1110   {
1111     manager->FocusGroupChangedSignal().Connect(tracker, functor);
1112   }
1113   else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY))
1114   {
1115     manager->FocusedActorEnterKeySignal().Connect(tracker, functor);
1116   }
1117   else
1118   {
1119     // signalName does not match any signal
1120     connected = false;
1121   }
1122
1123   return connected;
1124 }
1125
1126 void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interface)
1127 {
1128   mCustomAlgorithmInterface = &interface;
1129 }
1130
1131 void KeyboardFocusManager::EnableFocusIndicator(bool enable)
1132 {
1133   if(!enable && mFocusIndicatorActor)
1134   {
1135     mFocusIndicatorActor.Unparent();
1136   }
1137
1138   mEnableFocusIndicator = enable ? ENABLE : DISABLE;
1139 }
1140
1141 bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
1142 {
1143   return (mEnableFocusIndicator == ENABLE);
1144 }
1145
1146 void KeyboardFocusManager::EnableDefaultAlgorithm(bool enable)
1147 {
1148   mEnableDefaultAlgorithm = enable;
1149 }
1150
1151 bool KeyboardFocusManager::IsDefaultAlgorithmEnabled() const
1152 {
1153   return mEnableDefaultAlgorithm;
1154 }
1155
1156 } // namespace Internal
1157
1158 } // namespace Toolkit
1159
1160 } // namespace Dali