Update toolkit-window to add/remove actors in the correct Scene
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyboard-focus-manager-impl.cpp
1 /*
2  * Copyright (c) 2019 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 <cstring> // for strcmp
23 #include <dali/public-api/actors/layer.h>
24 #include <dali/devel-api/adaptor-framework/accessibility-adaptor.h>
25 #include <dali/devel-api/adaptor-framework/singleton-service.h>
26 #include <dali/devel-api/adaptor-framework/lifecycle-controller.h>
27 #include <dali/public-api/animation/constraints.h>
28 #include <dali/public-api/common/stage.h>
29 #include <dali/public-api/events/key-event.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/object/type-registry.h>
32 #include <dali/public-api/object/type-registry-helper.h>
33 #include <dali/public-api/object/property-map.h>
34 #include <dali/public-api/images/resource-image.h>
35 #include <dali/integration-api/adaptors/adaptor.h>
36 #include <dali/integration-api/adaptors/scene-holder.h>
37 #include <dali/integration-api/debug.h>
38
39 // INTERNAL INCLUDES
40 #include <dali-toolkit/public-api/controls/control.h>
41 #include <dali-toolkit/public-api/controls/control-impl.h>
42 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
43 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
44 #include <dali-toolkit/devel-api/controls/control-devel.h>
45 #include <dali-toolkit/public-api/styling/style-manager.h>
46 #include <dali-toolkit/devel-api/styling/style-manager-devel.h>
47
48 namespace Dali
49 {
50
51 namespace Toolkit
52 {
53
54 namespace Internal
55 {
56
57 namespace // Unnamed namespace
58 {
59
60 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEYBOARD_FOCUS_MANAGER");
62 #endif
63
64 const char* const IS_FOCUS_GROUP_PROPERTY_NAME = "isKeyboardFocusGroup"; // This property will be replaced by a flag in Control.
65
66 const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.9.png";
67
68 BaseHandle Create()
69 {
70   BaseHandle handle = KeyboardFocusManager::Get();
71
72   if ( !handle )
73   {
74     SingletonService singletonService( SingletonService::Get() );
75     if ( singletonService )
76     {
77       Toolkit::KeyboardFocusManager manager = Toolkit::KeyboardFocusManager( new Internal::KeyboardFocusManager() );
78       singletonService.Register( typeid( manager ), manager );
79       handle = manager;
80     }
81   }
82
83   return handle;
84 }
85
86 DALI_TYPE_REGISTRATION_BEGIN_CREATE( Toolkit::KeyboardFocusManager, Dali::BaseHandle, Create, true )
87
88 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardPreFocusChange",           SIGNAL_PRE_FOCUS_CHANGE )
89 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusChanged",             SIGNAL_FOCUS_CHANGED )
90 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusGroupChanged",        SIGNAL_FOCUS_GROUP_CHANGED )
91 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusedActorEnterKey",     SIGNAL_FOCUSED_ACTOR_ENTER_KEY )
92
93 DALI_TYPE_REGISTRATION_END()
94
95 const unsigned int MAX_HISTORY_AMOUNT = 30; ///< Max length of focus history stack
96
97 } // unnamed namespace
98
99 Toolkit::KeyboardFocusManager KeyboardFocusManager::Get()
100 {
101   Toolkit::KeyboardFocusManager manager;
102
103   SingletonService singletonService( SingletonService::Get() );
104   if ( singletonService )
105   {
106     // Check whether the keyboard focus manager is already created
107     Dali::BaseHandle handle = singletonService.GetSingleton( typeid( Toolkit::KeyboardFocusManager ) );
108     if(handle)
109     {
110       // If so, downcast the handle of singleton to keyboard focus manager
111       manager = Toolkit::KeyboardFocusManager( dynamic_cast< KeyboardFocusManager* >( handle.GetObjectPtr() ) );
112     }
113   }
114
115   return manager;
116 }
117
118 KeyboardFocusManager::KeyboardFocusManager()
119 : mPreFocusChangeSignal(),
120   mFocusChangedSignal(),
121   mFocusGroupChangedSignal(),
122   mFocusedActorEnterKeySignal(),
123   mCurrentFocusActor(),
124   mFocusIndicatorActor(),
125   mIsFocusIndicatorShown( -1 ),
126   mFocusGroupLoopEnabled( false ),
127   mIsWaitingKeyboardFocusChangeCommit( false ),
128   mClearFocusOnTouch( true ),
129   mEnableFocusIndicator( true ),
130   mAlwaysShowIndicator( true ),
131   mFocusHistory(),
132   mSlotDelegate( this ),
133   mCustomAlgorithmInterface(NULL)
134 {
135   // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown.
136
137   LifecycleController::Get().InitSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnAdaptorInit );
138 }
139
140 void KeyboardFocusManager::OnAdaptorInit()
141 {
142   if( Adaptor::IsAvailable() )
143   {
144     // Retrieve all the existing scene holders
145     Dali::SceneHolderList sceneHolders = Adaptor::Get().GetSceneHolders();
146     for( auto iter = sceneHolders.begin(); iter != sceneHolders.end(); ++iter )
147     {
148       ( *iter ).KeyEventSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent );
149       ( *iter ).TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch );
150     }
151
152     // Get notified when any new scene holder is created afterwards
153     Adaptor::Get().WindowCreatedSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnSceneHolderCreated );
154   }
155 }
156
157 void KeyboardFocusManager::OnSceneHolderCreated( Dali::Integration::SceneHolder& sceneHolder )
158 {
159   sceneHolder.KeyEventSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent );
160   sceneHolder.TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch );
161 }
162
163 KeyboardFocusManager::~KeyboardFocusManager()
164 {
165 }
166
167 void KeyboardFocusManager::GetConfigurationFromStyleManger()
168 {
169     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
170     if( styleManager )
171     {
172       Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager );
173       mAlwaysShowIndicator = config["alwaysShowFocus"].Get<bool>();
174       mIsFocusIndicatorShown = static_cast<int>(mAlwaysShowIndicator);
175       mClearFocusOnTouch = mIsFocusIndicatorShown ? false : true;
176     }
177 }
178
179 bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor )
180 {
181   DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" );
182
183   if( mIsFocusIndicatorShown == -1 )
184   {
185     GetConfigurationFromStyleManger();
186   }
187
188   return DoSetCurrentFocusActor( actor );
189 }
190
191 bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor )
192 {
193   bool success = false;
194
195   Actor currentFocusedActor = GetCurrentFocusActor();
196
197   // If developer set focus on same actor, doing nothing
198   if( actor == currentFocusedActor )
199   {
200     if( !actor )
201     {
202       return false;
203     }
204     return true;
205   }
206
207   // Check whether the actor is in the stage and is keyboard focusable.
208   if( actor && actor.IsKeyboardFocusable() && actor.OnStage() )
209   {
210     if( mIsFocusIndicatorShown && mEnableFocusIndicator )
211     {
212       actor.Add( GetFocusIndicatorActor() );
213     }
214
215     // Send notification for the change of focus actor
216     if( !mFocusChangedSignal.Empty() )
217     {
218       mFocusChangedSignal.Emit(currentFocusedActor, actor);
219     }
220
221     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor);
222     if( currentlyFocusedControl )
223     {
224       // Do we need it to remember if it was previously DISABLED?
225       currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL );
226       currentlyFocusedControl.ClearKeyInputFocus();
227     }
228
229     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
230
231     // Save the current focused actor
232     mCurrentFocusActor = actor;
233
234     Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor);
235     if( newlyFocusedControl )
236     {
237       newlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::FOCUSED );
238       newlyFocusedControl.SetKeyInputFocus();
239     }
240
241     // Push Current Focused Actor to FocusHistory
242     mFocusHistory.push_back( actor );
243
244     // Delete first element before add new element when Stack is full.
245     if( mFocusHistory.size() > MAX_HISTORY_AMOUNT )
246     {
247        FocusStackIterator beginPos = mFocusHistory.begin();
248        mFocusHistory.erase( beginPos );
249     }
250
251     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
252     success = true;
253   }
254   else
255   {
256     DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
257   }
258
259   return success;
260 }
261
262 Actor KeyboardFocusManager::GetCurrentFocusActor()
263 {
264   Actor actor = mCurrentFocusActor.GetHandle();
265   if( actor && ! actor.OnStage() )
266   {
267     // If the actor has been removed from the stage, then it should not be focused
268
269     actor.Reset();
270     mCurrentFocusActor.Reset();
271   }
272   return actor;
273 }
274
275 Actor KeyboardFocusManager::GetCurrentFocusGroup()
276 {
277   return GetFocusGroup(GetCurrentFocusActor());
278 }
279
280 void KeyboardFocusManager::MoveFocusBackward()
281 {
282   // Find Pre Focused Actor when the list size is more than 1
283   if( mFocusHistory.size() > 1 )
284   {
285     // Delete current focused actor in history
286     mFocusHistory.pop_back();
287
288     // If pre-focused actors are not on stage or deleted, remove them in stack
289     while( mFocusHistory.size() > 0 )
290     {
291       // Get pre focused actor
292       Actor target = mFocusHistory[ mFocusHistory.size() -1 ].GetHandle();
293
294       // Impl of Actor is not null
295       if( target && target.OnStage() )
296       {
297         // Delete pre focused actor in history because it will pushed again by SetCurrentFocusActor()
298         mFocusHistory.pop_back();
299         SetCurrentFocusActor( target );
300         break;
301       }
302       else
303       {
304         // Target is empty handle or off stage. Erase from queue
305         mFocusHistory.pop_back();
306       }
307     }
308
309     // if there is no actor which can get focus, then push current focus actor in stack again
310     if( mFocusHistory.size() == 0 )
311     {
312       Actor currentFocusedActor = GetCurrentFocusActor();
313       mFocusHistory.push_back( currentFocusedActor );
314     }
315   }
316 }
317
318 bool KeyboardFocusManager::IsLayoutControl(Actor actor) const
319 {
320   Toolkit::Control control = Toolkit::Control::DownCast(actor);
321   return control && GetImplementation( control ).IsKeyboardNavigationSupported();
322 }
323
324 Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const
325 {
326   // Get the actor's parent layout control that supports two dimensional keyboard navigation
327   Actor rootActor;
328   Actor parent;
329   if(actor)
330   {
331     Integration::SceneHolder window = Integration::SceneHolder::Get( actor );
332     if ( window )
333     {
334       rootActor = window.GetRootLayer();
335     }
336
337     parent = actor.GetParent();
338   }
339
340   while( parent && !IsLayoutControl(parent) && parent != rootActor )
341   {
342     parent = parent.GetParent();
343   }
344
345   return Toolkit::Control::DownCast(parent);
346 }
347
348 bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction)
349 {
350   Actor currentFocusActor = GetCurrentFocusActor();
351
352   bool succeed = false;
353
354   // Go through the actor's hierarchy until we find a layout control that knows how to move the focus
355   Toolkit::Control parentLayoutControl = GetParentLayoutControl( currentFocusActor );
356   while( parentLayoutControl && !succeed )
357   {
358     succeed = DoMoveFocusWithinLayoutControl( parentLayoutControl, currentFocusActor, direction );
359     parentLayoutControl = GetParentLayoutControl( parentLayoutControl );
360   }
361
362   if( !succeed )
363   {
364     Actor nextFocusableActor;
365
366     Toolkit::Control currentFocusControl = Toolkit::Control::DownCast(currentFocusActor);
367
368     // If the current focused actor is a control, then find the next focusable actor via the focusable properties.
369     if( currentFocusControl )
370     {
371       int actorId = -1;
372       Property::Index index = Property::INVALID_INDEX;
373       Property::Value value;
374
375       // Find property index based upon focus direction
376       switch ( direction )
377       {
378         case Toolkit::Control::KeyboardFocus::LEFT:
379         {
380           index = Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID;
381           break;
382         }
383         case Toolkit::Control::KeyboardFocus::RIGHT:
384         {
385           index = Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID;
386           break;
387         }
388         case Toolkit::Control::KeyboardFocus::UP:
389         {
390           index = Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID;
391           break;
392         }
393         case Toolkit::Control::KeyboardFocus::DOWN:
394         {
395           index = Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID;
396           break;
397         }
398         default:
399           break;
400       }
401
402       // If the focusable property is set then determine next focusable actor
403       if( index != Property::INVALID_INDEX)
404       {
405         value = currentFocusActor.GetProperty( index );
406         actorId = value.Get<int>();
407
408         // If actor's id is valid then find actor form actor's id. The actor should be on the stage.
409         if( actorId != -1 )
410         {
411           if( currentFocusActor.GetParent() )
412           {
413             nextFocusableActor = currentFocusActor.GetParent().FindChildById( actorId );
414           }
415
416           if( !nextFocusableActor )
417           {
418             Integration::SceneHolder window = Integration::SceneHolder::Get( currentFocusActor );
419             if ( window )
420             {
421               nextFocusableActor = window.GetRootLayer().FindChildById( actorId );
422             }
423           }
424         }
425       }
426     }
427
428     if( !nextFocusableActor )
429     {
430       // If the implementation of CustomAlgorithmInterface is provided then the PreFocusChangeSignal is no longer emitted.
431       if( mCustomAlgorithmInterface )
432       {
433         mIsWaitingKeyboardFocusChangeCommit = true;
434         nextFocusableActor = mCustomAlgorithmInterface->GetNextFocusableActor( currentFocusActor, Actor(), direction );
435         mIsWaitingKeyboardFocusChangeCommit = false;
436       }
437       else if( !mPreFocusChangeSignal.Empty() )
438       {
439         // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to
440         mIsWaitingKeyboardFocusChangeCommit = true;
441         nextFocusableActor = mPreFocusChangeSignal.Emit( currentFocusActor, Actor(), direction );
442         mIsWaitingKeyboardFocusChangeCommit = false;
443       }
444     }
445
446     if( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() )
447     {
448       // Whether the next focusable actor is a layout control
449       if( IsLayoutControl( nextFocusableActor ) )
450       {
451         // If so, move the focus inside it.
452         Toolkit::Control layoutControl = Toolkit::Control::DownCast( nextFocusableActor) ;
453         succeed = DoMoveFocusWithinLayoutControl( layoutControl, currentFocusActor, direction );
454       }
455       else
456       {
457         // Otherwise, just set focus to the next focusable actor
458         succeed = SetCurrentFocusActor( nextFocusableActor );
459       }
460     }
461   }
462
463   return succeed;
464 }
465
466 bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control control, Actor actor, Toolkit::Control::KeyboardFocus::Direction direction)
467 {
468   // Ask the control for the next actor to focus
469   Actor nextFocusableActor = GetImplementation( control ).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
470   if(nextFocusableActor)
471   {
472     if(!nextFocusableActor.IsKeyboardFocusable())
473     {
474       // If the actor is not focusable, ask the same layout control for the next actor to focus
475       return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
476     }
477     else
478     {
479       Actor currentFocusActor = GetCurrentFocusActor();
480       Actor committedFocusActor = nextFocusableActor;
481
482       // We will try to move the focus to the actor. Emit a signal to notify the proposed actor to focus
483       // Signal handler can check the proposed actor and return a different actor if it wishes.
484       if( !mPreFocusChangeSignal.Empty() )
485       {
486         mIsWaitingKeyboardFocusChangeCommit = true;
487         committedFocusActor = mPreFocusChangeSignal.Emit(currentFocusActor, nextFocusableActor, direction);
488         mIsWaitingKeyboardFocusChangeCommit = false;
489       }
490
491       if (committedFocusActor && committedFocusActor.IsKeyboardFocusable())
492       {
493         // Whether the commited focusable actor is a layout control
494         if(IsLayoutControl(committedFocusActor))
495         {
496           // If so, move the focus inside it.
497           Toolkit::Control layoutControl = Toolkit::Control::DownCast(committedFocusActor);
498           return DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
499         }
500         else
501         {
502           // Otherwise, just set focus to the next focusable actor
503           if(committedFocusActor == nextFocusableActor)
504           {
505             // If the application hasn't changed our proposed actor, we informs the layout control we will
506             // move the focus to what the control returns. The control might wish to perform some actions
507             // before the focus is actually moved.
508             GetImplementation( control ).OnKeyboardFocusChangeCommitted( committedFocusActor );
509           }
510
511           return SetCurrentFocusActor(committedFocusActor);
512         }
513       }
514       else
515       {
516         return false;
517       }
518     }
519   }
520   else
521   {
522     // No more actor can be focused in the given direction within the same layout control.
523     return false;
524   }
525 }
526
527 bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward)
528 {
529   bool succeed = false;
530
531   // Get the parent layout control of the current focus group
532   Toolkit::Control parentLayoutControl = GetParentLayoutControl(GetCurrentFocusGroup());
533
534   while(parentLayoutControl && !succeed)
535   {
536     // If the current focus group has a parent layout control, we can probably automatically
537     // move the focus to the next focus group in the forward or backward direction.
538     Toolkit::Control::KeyboardFocus::Direction direction = forward ? Toolkit::Control::KeyboardFocus::RIGHT : Toolkit::Control::KeyboardFocus::LEFT;
539     succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction);
540     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
541   }
542
543   if(!mFocusGroupChangedSignal.Empty())
544   {
545     // Emit a focus group changed signal. The applicaton can move the focus to a new focus group
546     mFocusGroupChangedSignal.Emit(GetCurrentFocusActor(), forward);
547   }
548
549   return succeed;
550 }
551
552 void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
553 {
554   if( actor )
555   {
556     Toolkit::Control control = Toolkit::Control::DownCast( actor );
557     if( control )
558     {
559       // Notify the control that enter has been pressed on it.
560       GetImplementation( control ).KeyboardEnter();
561     }
562
563     // Send a notification for the actor.
564     if( !mFocusedActorEnterKeySignal.Empty() )
565     {
566       mFocusedActorEnterKeySignal.Emit( actor );
567     }
568   }
569 }
570
571 void KeyboardFocusManager::ClearFocus()
572 {
573   Actor actor = GetCurrentFocusActor();
574   if( actor )
575   {
576     if( mFocusIndicatorActor )
577     {
578       actor.Remove( mFocusIndicatorActor );
579     }
580
581     // Send notification for the change of focus actor
582     if( !mFocusChangedSignal.Empty() )
583     {
584       mFocusChangedSignal.Emit( actor, Actor() );
585     }
586
587     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast( actor );
588     if( currentlyFocusedControl )
589     {
590       currentlyFocusedControl.SetProperty( DevelControl::Property::STATE, DevelControl::NORMAL );
591       currentlyFocusedControl.ClearKeyInputFocus();
592     }
593   }
594
595   mCurrentFocusActor.Reset();
596   mIsFocusIndicatorShown = static_cast<int>(mAlwaysShowIndicator);
597 }
598
599 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
600 {
601   mFocusGroupLoopEnabled = enabled;
602 }
603
604 bool KeyboardFocusManager::GetFocusGroupLoop() const
605 {
606   return mFocusGroupLoopEnabled;
607 }
608
609 void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup)
610 {
611   if(actor)
612   {
613     // Create/Set focus group property.
614     actor.RegisterProperty( IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE );
615   }
616 }
617
618 bool KeyboardFocusManager::IsFocusGroup(Actor actor) const
619 {
620   // Check whether the actor is a focus group
621   bool isFocusGroup = false;
622
623   if(actor)
624   {
625     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
626     if(propertyIsFocusGroup != Property::INVALID_INDEX)
627     {
628       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
629     }
630   }
631
632   return isFocusGroup;
633 }
634
635 Actor KeyboardFocusManager::GetFocusGroup(Actor actor)
636 {
637   // Go through the actor's hierarchy to check which focus group the actor belongs to
638   while (actor && !IsFocusGroup(actor))
639   {
640     actor = actor.GetParent();
641   }
642
643   return actor;
644 }
645
646 void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator)
647 {
648   if(mFocusIndicatorActor != indicator)
649   {
650     Actor currentFocusActor = GetCurrentFocusActor();
651     if(currentFocusActor)
652     {
653       // The new focus indicator should be added to the current focused actor immediately
654       if(mFocusIndicatorActor)
655       {
656         currentFocusActor.Remove(mFocusIndicatorActor);
657       }
658
659       if(indicator)
660       {
661         currentFocusActor.Add(indicator);
662       }
663     }
664
665     mFocusIndicatorActor = indicator;
666   }
667 }
668
669 Actor KeyboardFocusManager::GetFocusIndicatorActor()
670 {
671   if( ! mFocusIndicatorActor )
672   {
673     // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors
674     mFocusIndicatorActor = Toolkit::ImageView::New( FOCUS_BORDER_IMAGE_PATH );
675
676     // Apply size constraint to the focus indicator
677     mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
678   }
679
680   mFocusIndicatorActor.SetParentOrigin( ParentOrigin::CENTER );
681   mFocusIndicatorActor.SetAnchorPoint( AnchorPoint::CENTER );
682   mFocusIndicatorActor.SetPosition(0.0f, 0.0f);
683
684   return mFocusIndicatorActor;
685 }
686
687 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
688 {
689   AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
690   bool isAccessibilityEnabled = accessibilityAdaptor.IsEnabled();
691
692   Toolkit::AccessibilityManager accessibilityManager = Toolkit::AccessibilityManager::Get();
693
694   std::string keyName = event.keyPressedName;
695
696   if( mIsFocusIndicatorShown == -1 )
697   {
698     GetConfigurationFromStyleManger();
699   }
700
701   bool isFocusStartableKey = false;
702
703   if(event.state == KeyEvent::Down)
704   {
705     if (keyName == "Left")
706     {
707       if(!isAccessibilityEnabled)
708       {
709         if(!mIsFocusIndicatorShown)
710         {
711           // Show focus indicator
712           mIsFocusIndicatorShown = 1;
713         }
714         else
715         {
716           // Move the focus towards left
717           MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
718         }
719
720         isFocusStartableKey = true;
721       }
722       else
723       {
724         // Move the accessibility focus backward
725         accessibilityManager.MoveFocusBackward();
726       }
727     }
728     else if (keyName == "Right")
729     {
730       if(!isAccessibilityEnabled)
731       {
732         if(!mIsFocusIndicatorShown)
733         {
734           // Show focus indicator
735           mIsFocusIndicatorShown = 1;
736         }
737         else
738         {
739           // Move the focus towards right
740           MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
741         }
742       }
743       else
744       {
745         // Move the accessibility focus forward
746         accessibilityManager.MoveFocusForward();
747       }
748
749       isFocusStartableKey = true;
750     }
751     else if (keyName == "Up" && !isAccessibilityEnabled)
752     {
753       if(!mIsFocusIndicatorShown)
754       {
755         // Show focus indicator
756         mIsFocusIndicatorShown = 1;
757       }
758       else
759       {
760         // Move the focus towards up
761         MoveFocus(Toolkit::Control::KeyboardFocus::UP);
762       }
763
764       isFocusStartableKey = true;
765     }
766     else if (keyName == "Down" && !isAccessibilityEnabled)
767     {
768       if(!mIsFocusIndicatorShown)
769       {
770         // Show focus indicator
771         mIsFocusIndicatorShown = 1;
772       }
773       else
774       {
775         // Move the focus towards down
776         MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
777       }
778
779       isFocusStartableKey = true;
780     }
781     else if (keyName == "Prior" && !isAccessibilityEnabled)
782     {
783       if(!mIsFocusIndicatorShown)
784       {
785         // Show focus indicator
786         mIsFocusIndicatorShown = 1;
787       }
788       else
789       {
790         // Move the focus towards the previous page
791         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
792       }
793
794       isFocusStartableKey = true;
795     }
796     else if (keyName == "Next" && !isAccessibilityEnabled)
797     {
798       if(!mIsFocusIndicatorShown)
799       {
800         // Show focus indicator
801         mIsFocusIndicatorShown = 1;
802       }
803       else
804       {
805         // Move the focus towards the next page
806         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
807       }
808
809       isFocusStartableKey = true;
810     }
811     else if (keyName == "Tab" && !isAccessibilityEnabled)
812     {
813       if(!mIsFocusIndicatorShown)
814       {
815         // Show focus indicator
816         mIsFocusIndicatorShown = 1;
817       }
818       else
819       {
820         // "Tab" key changes the focus group in the forward direction and
821         // "Shift-Tab" key changes it in the backward direction.
822         DoMoveFocusToNextFocusGroup(!event.IsShiftModifier());
823       }
824
825       isFocusStartableKey = true;
826     }
827     else if (keyName == "space" && !isAccessibilityEnabled)
828     {
829       if(!mIsFocusIndicatorShown)
830       {
831         // Show focus indicator
832         mIsFocusIndicatorShown = 1;
833       }
834
835       isFocusStartableKey = true;
836     }
837     else if (keyName == "" && !isAccessibilityEnabled)
838     {
839       // Check the fake key event for evas-plugin case
840       if(!mIsFocusIndicatorShown)
841       {
842         // Show focus indicator
843         mIsFocusIndicatorShown = 1;
844       }
845
846       isFocusStartableKey = true;
847     }
848     else if (keyName == "Backspace" && !isAccessibilityEnabled)
849     {
850       // Emit signal to go back to the previous view???
851     }
852     else if (keyName == "Escape" && !isAccessibilityEnabled)
853     {
854     }
855   }
856   else if(event.state == KeyEvent::Up)
857   {
858     if (keyName == "Return")
859     {
860       if(!mIsFocusIndicatorShown && !isAccessibilityEnabled)
861       {
862         // Show focus indicator
863         mIsFocusIndicatorShown = 1;
864       }
865       else
866       {
867         // The focused actor has enter pressed on it
868         Actor actor;
869         if( !isAccessibilityEnabled )
870         {
871           actor = GetCurrentFocusActor();
872         }
873         else
874         {
875           actor = accessibilityManager.GetCurrentFocusActor();
876         }
877
878         if( actor )
879         {
880           DoKeyboardEnter( actor );
881         }
882       }
883
884       isFocusStartableKey = true;
885     }
886   }
887
888   if(isFocusStartableKey && mIsFocusIndicatorShown && !isAccessibilityEnabled)
889   {
890     Actor actor = GetCurrentFocusActor();
891     if( actor )
892     {
893       if( mEnableFocusIndicator )
894       {
895         // Make sure the focused actor is highlighted
896         actor.Add( GetFocusIndicatorActor() );
897       }
898     }
899     else
900     {
901       // No actor is focused but keyboard focus is activated by the key press
902       // Let's try to move the initial focus
903       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
904     }
905   }
906 }
907
908 void KeyboardFocusManager::OnTouch(const TouchData& touch)
909 {
910   // if mIsFocusIndicatorShown is -1, it means Configuration is not loaded.
911   // Try to load configuration.
912   if( mIsFocusIndicatorShown == -1 )
913   {
914     GetConfigurationFromStyleManger();
915   }
916
917   // Clear the focus when user touch the screen.
918   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
919   // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
920   if( (( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN )) && mClearFocusOnTouch )
921   {
922     ClearFocus();
923   }
924 }
925
926 Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal()
927 {
928   return mPreFocusChangeSignal;
929 }
930
931 Toolkit::KeyboardFocusManager::FocusChangedSignalType& KeyboardFocusManager::FocusChangedSignal()
932 {
933   return mFocusChangedSignal;
934 }
935
936 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager::FocusGroupChangedSignal()
937 {
938   return mFocusGroupChangedSignal;
939 }
940
941 Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal()
942 {
943   return mFocusedActorEnterKeySignal;
944 }
945
946 bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
947 {
948   Dali::BaseHandle handle( object );
949
950   bool connected( true );
951   KeyboardFocusManager* manager = static_cast< KeyboardFocusManager* >( object ); // TypeRegistry guarantees that this is the correct type.
952
953   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE ) )
954   {
955     manager->PreFocusChangeSignal().Connect( tracker, functor );
956   }
957   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) )
958   {
959     manager->FocusChangedSignal().Connect( tracker, functor );
960   }
961   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED ) )
962   {
963     manager->FocusGroupChangedSignal().Connect( tracker, functor );
964   }
965   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) )
966   {
967     manager->FocusedActorEnterKeySignal().Connect( tracker, functor );
968   }
969   else
970   {
971     // signalName does not match any signal
972     connected = false;
973   }
974
975   return connected;
976 }
977
978 void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interface)
979 {
980   mCustomAlgorithmInterface = &interface;
981 }
982
983 void KeyboardFocusManager::EnableFocusIndicator(bool enable)
984 {
985   if( !enable && mFocusIndicatorActor )
986   {
987     mFocusIndicatorActor.Unparent();
988   }
989
990   mEnableFocusIndicator = enable;
991 }
992
993 bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
994 {
995   return mEnableFocusIndicator;
996 }
997
998 } // namespace Internal
999
1000 } // namespace Toolkit
1001
1002 } // namespace Dali