(Vector) Use scaling factor for rasterization
[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/window-devel.h>
27 #include <dali/devel-api/adaptor-framework/lifecycle-controller.h>
28 #include <dali/public-api/animation/constraints.h>
29 #include <dali/public-api/common/stage.h>
30 #include <dali/public-api/events/key-event.h>
31 #include <dali/public-api/events/touch-data.h>
32 #include <dali/public-api/object/type-registry.h>
33 #include <dali/public-api/object/type-registry-helper.h>
34 #include <dali/public-api/object/property-map.h>
35 #include <dali/public-api/images/resource-image.h>
36 #include <dali/integration-api/adaptors/adaptor.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 widnows
145     Dali::WindowContainer windows = Adaptor::Get().GetWindows();
146     for ( auto iter = windows.begin(); iter != windows.end(); ++iter )
147     {
148       DevelWindow::KeyEventSignal( *iter ).Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
149       DevelWindow::TouchSignal( *iter ).Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch);
150     }
151
152     // Get notified when any new window is created afterwards
153     Adaptor::Get().WindowCreatedSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnWindowCreated);
154   }
155 }
156
157 void KeyboardFocusManager::OnWindowCreated( Dali::Window& window )
158 {
159   DevelWindow::KeyEventSignal( window ).Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
160   DevelWindow::TouchSignal( window ).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     rootActor = DevelWindow::Get( actor ).GetRootLayer();
332     parent = actor.GetParent();
333   }
334
335   while( parent && !IsLayoutControl(parent) && parent != rootActor )
336   {
337     parent = parent.GetParent();
338   }
339
340   return Toolkit::Control::DownCast(parent);
341 }
342
343 bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction)
344 {
345   Actor currentFocusActor = GetCurrentFocusActor();
346
347   bool succeed = false;
348
349   // Go through the actor's hierarchy until we find a layout control that knows how to move the focus
350   Toolkit::Control parentLayoutControl = GetParentLayoutControl( currentFocusActor );
351   while( parentLayoutControl && !succeed )
352   {
353     succeed = DoMoveFocusWithinLayoutControl( parentLayoutControl, currentFocusActor, direction );
354     parentLayoutControl = GetParentLayoutControl( parentLayoutControl );
355   }
356
357   if( !succeed )
358   {
359     Actor nextFocusableActor;
360
361     Toolkit::Control currentFocusControl = Toolkit::Control::DownCast(currentFocusActor);
362
363     // If the current focused actor is a control, then find the next focusable actor via the focusable properties.
364     if( currentFocusControl )
365     {
366       int actorId = -1;
367       Property::Index index = Property::INVALID_INDEX;
368       Property::Value value;
369
370       // Find property index based upon focus direction
371       switch ( direction )
372       {
373         case Toolkit::Control::KeyboardFocus::LEFT:
374         {
375           index = Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID;
376           break;
377         }
378         case Toolkit::Control::KeyboardFocus::RIGHT:
379         {
380           index = Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID;
381           break;
382         }
383         case Toolkit::Control::KeyboardFocus::UP:
384         {
385           index = Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID;
386           break;
387         }
388         case Toolkit::Control::KeyboardFocus::DOWN:
389         {
390           index = Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID;
391           break;
392         }
393         default:
394           break;
395       }
396
397       // If the focusable property is set then determine next focusable actor
398       if( index != Property::INVALID_INDEX)
399       {
400         value = currentFocusActor.GetProperty( index );
401         actorId = value.Get<int>();
402
403         // If actor's id is valid then find actor form actor's id. The actor should be on the stage.
404         if( actorId != -1 )
405         {
406           if( currentFocusActor.GetParent() )
407           {
408             nextFocusableActor = currentFocusActor.GetParent().FindChildById( actorId );
409           }
410
411           if( !nextFocusableActor )
412           {
413             nextFocusableActor = DevelWindow::Get( currentFocusActor ).GetRootLayer().FindChildById( actorId );
414           }
415         }
416       }
417     }
418
419     if( !nextFocusableActor )
420     {
421       // If the implementation of CustomAlgorithmInterface is provided then the PreFocusChangeSignal is no longer emitted.
422       if( mCustomAlgorithmInterface )
423       {
424         mIsWaitingKeyboardFocusChangeCommit = true;
425         nextFocusableActor = mCustomAlgorithmInterface->GetNextFocusableActor( currentFocusActor, Actor(), direction );
426         mIsWaitingKeyboardFocusChangeCommit = false;
427       }
428       else if( !mPreFocusChangeSignal.Empty() )
429       {
430         // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to
431         mIsWaitingKeyboardFocusChangeCommit = true;
432         nextFocusableActor = mPreFocusChangeSignal.Emit( currentFocusActor, Actor(), direction );
433         mIsWaitingKeyboardFocusChangeCommit = false;
434       }
435     }
436
437     if( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() )
438     {
439       // Whether the next focusable actor is a layout control
440       if( IsLayoutControl( nextFocusableActor ) )
441       {
442         // If so, move the focus inside it.
443         Toolkit::Control layoutControl = Toolkit::Control::DownCast( nextFocusableActor) ;
444         succeed = DoMoveFocusWithinLayoutControl( layoutControl, currentFocusActor, direction );
445       }
446       else
447       {
448         // Otherwise, just set focus to the next focusable actor
449         succeed = SetCurrentFocusActor( nextFocusableActor );
450       }
451     }
452   }
453
454   return succeed;
455 }
456
457 bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control control, Actor actor, Toolkit::Control::KeyboardFocus::Direction direction)
458 {
459   // Ask the control for the next actor to focus
460   Actor nextFocusableActor = GetImplementation( control ).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
461   if(nextFocusableActor)
462   {
463     if(!nextFocusableActor.IsKeyboardFocusable())
464     {
465       // If the actor is not focusable, ask the same layout control for the next actor to focus
466       return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
467     }
468     else
469     {
470       Actor currentFocusActor = GetCurrentFocusActor();
471       Actor committedFocusActor = nextFocusableActor;
472
473       // We will try to move the focus to the actor. Emit a signal to notify the proposed actor to focus
474       // Signal handler can check the proposed actor and return a different actor if it wishes.
475       if( !mPreFocusChangeSignal.Empty() )
476       {
477         mIsWaitingKeyboardFocusChangeCommit = true;
478         committedFocusActor = mPreFocusChangeSignal.Emit(currentFocusActor, nextFocusableActor, direction);
479         mIsWaitingKeyboardFocusChangeCommit = false;
480       }
481
482       if (committedFocusActor && committedFocusActor.IsKeyboardFocusable())
483       {
484         // Whether the commited focusable actor is a layout control
485         if(IsLayoutControl(committedFocusActor))
486         {
487           // If so, move the focus inside it.
488           Toolkit::Control layoutControl = Toolkit::Control::DownCast(committedFocusActor);
489           return DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
490         }
491         else
492         {
493           // Otherwise, just set focus to the next focusable actor
494           if(committedFocusActor == nextFocusableActor)
495           {
496             // If the application hasn't changed our proposed actor, we informs the layout control we will
497             // move the focus to what the control returns. The control might wish to perform some actions
498             // before the focus is actually moved.
499             GetImplementation( control ).OnKeyboardFocusChangeCommitted( committedFocusActor );
500           }
501
502           return SetCurrentFocusActor(committedFocusActor);
503         }
504       }
505       else
506       {
507         return false;
508       }
509     }
510   }
511   else
512   {
513     // No more actor can be focused in the given direction within the same layout control.
514     return false;
515   }
516 }
517
518 bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward)
519 {
520   bool succeed = false;
521
522   // Get the parent layout control of the current focus group
523   Toolkit::Control parentLayoutControl = GetParentLayoutControl(GetCurrentFocusGroup());
524
525   while(parentLayoutControl && !succeed)
526   {
527     // If the current focus group has a parent layout control, we can probably automatically
528     // move the focus to the next focus group in the forward or backward direction.
529     Toolkit::Control::KeyboardFocus::Direction direction = forward ? Toolkit::Control::KeyboardFocus::RIGHT : Toolkit::Control::KeyboardFocus::LEFT;
530     succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction);
531     parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
532   }
533
534   if(!mFocusGroupChangedSignal.Empty())
535   {
536     // Emit a focus group changed signal. The applicaton can move the focus to a new focus group
537     mFocusGroupChangedSignal.Emit(GetCurrentFocusActor(), forward);
538   }
539
540   return succeed;
541 }
542
543 void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
544 {
545   if( actor )
546   {
547     Toolkit::Control control = Toolkit::Control::DownCast( actor );
548     if( control )
549     {
550       // Notify the control that enter has been pressed on it.
551       GetImplementation( control ).KeyboardEnter();
552     }
553
554     // Send a notification for the actor.
555     if( !mFocusedActorEnterKeySignal.Empty() )
556     {
557       mFocusedActorEnterKeySignal.Emit( actor );
558     }
559   }
560 }
561
562 void KeyboardFocusManager::ClearFocus()
563 {
564   Actor actor = GetCurrentFocusActor();
565   if( actor )
566   {
567     if( mFocusIndicatorActor )
568     {
569       actor.Remove( mFocusIndicatorActor );
570     }
571
572     // Send notification for the change of focus actor
573     if( !mFocusChangedSignal.Empty() )
574     {
575       mFocusChangedSignal.Emit( actor, Actor() );
576     }
577
578     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast( actor );
579     if( currentlyFocusedControl )
580     {
581       currentlyFocusedControl.SetProperty( DevelControl::Property::STATE, DevelControl::NORMAL );
582       currentlyFocusedControl.ClearKeyInputFocus();
583     }
584   }
585
586   mCurrentFocusActor.Reset();
587   mIsFocusIndicatorShown = static_cast<int>(mAlwaysShowIndicator);
588 }
589
590 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
591 {
592   mFocusGroupLoopEnabled = enabled;
593 }
594
595 bool KeyboardFocusManager::GetFocusGroupLoop() const
596 {
597   return mFocusGroupLoopEnabled;
598 }
599
600 void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup)
601 {
602   if(actor)
603   {
604     // Create/Set focus group property.
605     actor.RegisterProperty( IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE );
606   }
607 }
608
609 bool KeyboardFocusManager::IsFocusGroup(Actor actor) const
610 {
611   // Check whether the actor is a focus group
612   bool isFocusGroup = false;
613
614   if(actor)
615   {
616     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
617     if(propertyIsFocusGroup != Property::INVALID_INDEX)
618     {
619       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
620     }
621   }
622
623   return isFocusGroup;
624 }
625
626 Actor KeyboardFocusManager::GetFocusGroup(Actor actor)
627 {
628   // Go through the actor's hierarchy to check which focus group the actor belongs to
629   while (actor && !IsFocusGroup(actor))
630   {
631     actor = actor.GetParent();
632   }
633
634   return actor;
635 }
636
637 void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator)
638 {
639   if(mFocusIndicatorActor != indicator)
640   {
641     Actor currentFocusActor = GetCurrentFocusActor();
642     if(currentFocusActor)
643     {
644       // The new focus indicator should be added to the current focused actor immediately
645       if(mFocusIndicatorActor)
646       {
647         currentFocusActor.Remove(mFocusIndicatorActor);
648       }
649
650       if(indicator)
651       {
652         currentFocusActor.Add(indicator);
653       }
654     }
655
656     mFocusIndicatorActor = indicator;
657   }
658 }
659
660 Actor KeyboardFocusManager::GetFocusIndicatorActor()
661 {
662   if( ! mFocusIndicatorActor )
663   {
664     // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors
665     mFocusIndicatorActor = Toolkit::ImageView::New( FOCUS_BORDER_IMAGE_PATH );
666
667     // Apply size constraint to the focus indicator
668     mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
669   }
670
671   mFocusIndicatorActor.SetParentOrigin( ParentOrigin::CENTER );
672   mFocusIndicatorActor.SetAnchorPoint( AnchorPoint::CENTER );
673   mFocusIndicatorActor.SetPosition(0.0f, 0.0f);
674
675   return mFocusIndicatorActor;
676 }
677
678 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
679 {
680   AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
681   bool isAccessibilityEnabled = accessibilityAdaptor.IsEnabled();
682
683   Toolkit::AccessibilityManager accessibilityManager = Toolkit::AccessibilityManager::Get();
684
685   std::string keyName = event.keyPressedName;
686
687   if( mIsFocusIndicatorShown == -1 )
688   {
689     GetConfigurationFromStyleManger();
690   }
691
692   bool isFocusStartableKey = false;
693
694   if(event.state == KeyEvent::Down)
695   {
696     if (keyName == "Left")
697     {
698       if(!isAccessibilityEnabled)
699       {
700         if(!mIsFocusIndicatorShown)
701         {
702           // Show focus indicator
703           mIsFocusIndicatorShown = 1;
704         }
705         else
706         {
707           // Move the focus towards left
708           MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
709         }
710
711         isFocusStartableKey = true;
712       }
713       else
714       {
715         // Move the accessibility focus backward
716         accessibilityManager.MoveFocusBackward();
717       }
718     }
719     else if (keyName == "Right")
720     {
721       if(!isAccessibilityEnabled)
722       {
723         if(!mIsFocusIndicatorShown)
724         {
725           // Show focus indicator
726           mIsFocusIndicatorShown = 1;
727         }
728         else
729         {
730           // Move the focus towards right
731           MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
732         }
733       }
734       else
735       {
736         // Move the accessibility focus forward
737         accessibilityManager.MoveFocusForward();
738       }
739
740       isFocusStartableKey = true;
741     }
742     else if (keyName == "Up" && !isAccessibilityEnabled)
743     {
744       if(!mIsFocusIndicatorShown)
745       {
746         // Show focus indicator
747         mIsFocusIndicatorShown = 1;
748       }
749       else
750       {
751         // Move the focus towards up
752         MoveFocus(Toolkit::Control::KeyboardFocus::UP);
753       }
754
755       isFocusStartableKey = true;
756     }
757     else if (keyName == "Down" && !isAccessibilityEnabled)
758     {
759       if(!mIsFocusIndicatorShown)
760       {
761         // Show focus indicator
762         mIsFocusIndicatorShown = 1;
763       }
764       else
765       {
766         // Move the focus towards down
767         MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
768       }
769
770       isFocusStartableKey = true;
771     }
772     else if (keyName == "Prior" && !isAccessibilityEnabled)
773     {
774       if(!mIsFocusIndicatorShown)
775       {
776         // Show focus indicator
777         mIsFocusIndicatorShown = 1;
778       }
779       else
780       {
781         // Move the focus towards the previous page
782         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
783       }
784
785       isFocusStartableKey = true;
786     }
787     else if (keyName == "Next" && !isAccessibilityEnabled)
788     {
789       if(!mIsFocusIndicatorShown)
790       {
791         // Show focus indicator
792         mIsFocusIndicatorShown = 1;
793       }
794       else
795       {
796         // Move the focus towards the next page
797         MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
798       }
799
800       isFocusStartableKey = true;
801     }
802     else if (keyName == "Tab" && !isAccessibilityEnabled)
803     {
804       if(!mIsFocusIndicatorShown)
805       {
806         // Show focus indicator
807         mIsFocusIndicatorShown = 1;
808       }
809       else
810       {
811         // "Tab" key changes the focus group in the forward direction and
812         // "Shift-Tab" key changes it in the backward direction.
813         DoMoveFocusToNextFocusGroup(!event.IsShiftModifier());
814       }
815
816       isFocusStartableKey = true;
817     }
818     else if (keyName == "space" && !isAccessibilityEnabled)
819     {
820       if(!mIsFocusIndicatorShown)
821       {
822         // Show focus indicator
823         mIsFocusIndicatorShown = 1;
824       }
825
826       isFocusStartableKey = true;
827     }
828     else if (keyName == "" && !isAccessibilityEnabled)
829     {
830       // Check the fake key event for evas-plugin case
831       if(!mIsFocusIndicatorShown)
832       {
833         // Show focus indicator
834         mIsFocusIndicatorShown = 1;
835       }
836
837       isFocusStartableKey = true;
838     }
839     else if (keyName == "Backspace" && !isAccessibilityEnabled)
840     {
841       // Emit signal to go back to the previous view???
842     }
843     else if (keyName == "Escape" && !isAccessibilityEnabled)
844     {
845     }
846   }
847   else if(event.state == KeyEvent::Up)
848   {
849     if (keyName == "Return")
850     {
851       if(!mIsFocusIndicatorShown && !isAccessibilityEnabled)
852       {
853         // Show focus indicator
854         mIsFocusIndicatorShown = 1;
855       }
856       else
857       {
858         // The focused actor has enter pressed on it
859         Actor actor;
860         if( !isAccessibilityEnabled )
861         {
862           actor = GetCurrentFocusActor();
863         }
864         else
865         {
866           actor = accessibilityManager.GetCurrentFocusActor();
867         }
868
869         if( actor )
870         {
871           DoKeyboardEnter( actor );
872         }
873       }
874
875       isFocusStartableKey = true;
876     }
877   }
878
879   if(isFocusStartableKey && mIsFocusIndicatorShown && !isAccessibilityEnabled)
880   {
881     Actor actor = GetCurrentFocusActor();
882     if( actor )
883     {
884       if( mEnableFocusIndicator )
885       {
886         // Make sure the focused actor is highlighted
887         actor.Add( GetFocusIndicatorActor() );
888       }
889     }
890     else
891     {
892       // No actor is focused but keyboard focus is activated by the key press
893       // Let's try to move the initial focus
894       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
895     }
896   }
897 }
898
899 void KeyboardFocusManager::OnTouch(const TouchData& touch)
900 {
901   // if mIsFocusIndicatorShown is -1, it means Configuration is not loaded.
902   // Try to load configuration.
903   if( mIsFocusIndicatorShown == -1 )
904   {
905     GetConfigurationFromStyleManger();
906   }
907
908   // Clear the focus when user touch the screen.
909   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
910   // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
911   if( (( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN )) && mClearFocusOnTouch )
912   {
913     ClearFocus();
914   }
915 }
916
917 Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal()
918 {
919   return mPreFocusChangeSignal;
920 }
921
922 Toolkit::KeyboardFocusManager::FocusChangedSignalType& KeyboardFocusManager::FocusChangedSignal()
923 {
924   return mFocusChangedSignal;
925 }
926
927 Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager::FocusGroupChangedSignal()
928 {
929   return mFocusGroupChangedSignal;
930 }
931
932 Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal()
933 {
934   return mFocusedActorEnterKeySignal;
935 }
936
937 bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
938 {
939   Dali::BaseHandle handle( object );
940
941   bool connected( true );
942   KeyboardFocusManager* manager = static_cast< KeyboardFocusManager* >( object ); // TypeRegistry guarantees that this is the correct type.
943
944   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE ) )
945   {
946     manager->PreFocusChangeSignal().Connect( tracker, functor );
947   }
948   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) )
949   {
950     manager->FocusChangedSignal().Connect( tracker, functor );
951   }
952   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED ) )
953   {
954     manager->FocusGroupChangedSignal().Connect( tracker, functor );
955   }
956   else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) )
957   {
958     manager->FocusedActorEnterKeySignal().Connect( tracker, functor );
959   }
960   else
961   {
962     // signalName does not match any signal
963     connected = false;
964   }
965
966   return connected;
967 }
968
969 void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interface)
970 {
971   mCustomAlgorithmInterface = &interface;
972 }
973
974 void KeyboardFocusManager::EnableFocusIndicator(bool enable)
975 {
976   if( !enable && mFocusIndicatorActor )
977   {
978     mFocusIndicatorActor.Unparent();
979   }
980
981   mEnableFocusIndicator = enable;
982 }
983
984 bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
985 {
986   return mEnableFocusIndicator;
987 }
988
989 } // namespace Internal
990
991 } // namespace Toolkit
992
993 } // namespace Dali