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