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