Basic support of keyboard focus for multiple windows
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyboard-focus-manager-impl.cpp
index a950b35..5e447c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/public-api/actors/layer.h>
 #include <dali/devel-api/adaptor-framework/accessibility-adaptor.h>
 #include <dali/devel-api/adaptor-framework/singleton-service.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
+#include <dali/devel-api/adaptor-framework/lifecycle-controller.h>
 #include <dali/public-api/animation/constraints.h>
 #include <dali/public-api/common/stage.h>
 #include <dali/public-api/events/key-event.h>
+#include <dali/public-api/events/touch-data.h>
 #include <dali/public-api/object/type-registry.h>
-#include <dali/devel-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali/public-api/images/resource-image.h>
+#include <dali/integration-api/adaptors/adaptor.h>
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
-#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/public-api/styling/style-manager.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 
 namespace Dali
 {
@@ -55,8 +63,7 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEY
 
 const char* const IS_FOCUS_GROUP_PROPERTY_NAME = "isKeyboardFocusGroup"; // This property will be replaced by a flag in Control.
 
-const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.png";
-const Vector4 FOCUS_BORDER_IMAGE_BORDER = Vector4(7.0f, 7.0f, 7.0f, 7.0f);
+const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.9.png";
 
 BaseHandle Create()
 {
@@ -78,13 +85,15 @@ BaseHandle Create()
 
 DALI_TYPE_REGISTRATION_BEGIN_CREATE( Toolkit::KeyboardFocusManager, Dali::BaseHandle, Create, true )
 
-DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardPreFocusChange",           SIGNAL_PRE_FOCUS_CHANGE        )
-DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusChanged",             SIGNAL_FOCUS_CHANGED           )
-DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusGroupChanged",        SIGNAL_FOCUS_GROUP_CHANGED     )
+DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardPreFocusChange",           SIGNAL_PRE_FOCUS_CHANGE )
+DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusChanged",             SIGNAL_FOCUS_CHANGED )
+DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusGroupChanged",        SIGNAL_FOCUS_GROUP_CHANGED )
 DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusedActorEnterKey",     SIGNAL_FOCUSED_ACTOR_ENTER_KEY )
 
 DALI_TYPE_REGISTRATION_END()
 
+const unsigned int MAX_HISTORY_AMOUNT = 30; ///< Max length of focus history stack
+
 } // unnamed namespace
 
 Toolkit::KeyboardFocusManager KeyboardFocusManager::Get()
@@ -107,80 +116,160 @@ Toolkit::KeyboardFocusManager KeyboardFocusManager::Get()
 }
 
 KeyboardFocusManager::KeyboardFocusManager()
-: mCurrentFocusActor(0),
-  mFocusIndicatorActor(Actor()),
-  mFocusGroupLoopEnabled(false),
-  mIsKeyboardFocusEnabled(false),
-  mIsFocusIndicatorEnabled(false),
-  mIsWaitingKeyboardFocusChangeCommit(false),
-  mSlotDelegate(this)
+: mPreFocusChangeSignal(),
+  mFocusChangedSignal(),
+  mFocusGroupChangedSignal(),
+  mFocusedActorEnterKeySignal(),
+  mCurrentFocusActor(),
+  mFocusIndicatorActor(),
+  mIsFocusIndicatorShown( -1 ),
+  mFocusGroupLoopEnabled( false ),
+  mIsWaitingKeyboardFocusChangeCommit( false ),
+  mClearFocusOnTouch( true ),
+  mEnableFocusIndicator( true ),
+  mAlwaysShowIndicator( true ),
+  mFocusHistory(),
+  mSlotDelegate( this ),
+  mCustomAlgorithmInterface(NULL)
+{
+  // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown.
+
+  LifecycleController::Get().InitSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnAdaptorInit );
+}
+
+void KeyboardFocusManager::OnAdaptorInit()
 {
-  CreateDefaultFocusIndicatorActor();
+  if( Adaptor::IsAvailable() )
+  {
+    // Retrieve all the existing widnows
+    Dali::WindowContainer windows = Adaptor::Get().GetWindows();
+    for ( auto iter = windows.begin(); iter != windows.end(); ++iter )
+    {
+      DevelWindow::KeyEventSignal( *iter ).Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
+      DevelWindow::TouchSignal( *iter ).Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch);
+    }
 
-  OnPhysicalKeyboardStatusChanged(PhysicalKeyboard::Get());
+    // Get notified when any new window is created afterwards
+    Adaptor::Get().WindowCreatedSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnWindowCreated);
+  }
+}
 
-  Toolkit::KeyInputFocusManager::Get().UnhandledKeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
-  Stage::GetCurrent().TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouched);
-  PhysicalKeyboard::Get().StatusChangedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnPhysicalKeyboardStatusChanged);
+void KeyboardFocusManager::OnWindowCreated( Dali::Window& window )
+{
+  DevelWindow::KeyEventSignal( window ).Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
+  DevelWindow::TouchSignal( window ).Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch);
 }
 
 KeyboardFocusManager::~KeyboardFocusManager()
 {
 }
 
-bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor)
+void KeyboardFocusManager::GetConfigurationFromStyleManger()
+{
+    Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+    if( styleManager )
+    {
+      Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager );
+      mAlwaysShowIndicator = config["alwaysShowFocus"].Get<bool>();
+      mIsFocusIndicatorShown = static_cast<int>(mAlwaysShowIndicator);
+      mClearFocusOnTouch = mIsFocusIndicatorShown ? false : true;
+    }
+}
+
+bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor )
 {
   DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" );
 
-  if( actor )
+  if( mIsFocusIndicatorShown == -1 )
   {
-    return DoSetCurrentFocusActor( actor.GetId() );
+    GetConfigurationFromStyleManger();
   }
 
-  return false;
+  return DoSetCurrentFocusActor( actor );
 }
 
-bool KeyboardFocusManager::DoSetCurrentFocusActor(const unsigned int actorID)
+bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor )
 {
-  Actor rootActor = Stage::GetCurrent().GetRootLayer();
-  Actor actor = rootActor.FindChildById(actorID);
+  bool success = false;
 
-  // Check whether the actor is in the stage
-  if(actor)
+  Actor currentFocusedActor = GetCurrentFocusActor();
+
+  // If developer set focus on same actor, doing nothing
+  if( actor == currentFocusedActor )
   {
-    // Set the focus only when the actor is keyboard focusable
-    if(actor.IsKeyboardFocusable())
+    if( !actor )
     {
-      // Draw the focus indicator upon the focused actor
-      if(mIsFocusIndicatorEnabled && mFocusIndicatorActor)
-      {
-        actor.Add(mFocusIndicatorActor);
-      }
+      return false;
+    }
+    return true;
+  }
 
-      // Send notification for the change of focus actor
-      if( !mFocusChangedSignal.Empty() )
-      {
-        mFocusChangedSignal.Emit(GetCurrentFocusActor(), actor);
-      }
+  // Check whether the actor is in the stage and is keyboard focusable.
+  if( actor && actor.IsKeyboardFocusable() && actor.OnStage() )
+  {
+    if( mIsFocusIndicatorShown && mEnableFocusIndicator )
+    {
+      actor.Add( GetFocusIndicatorActor() );
+    }
+
+    // Send notification for the change of focus actor
+    if( !mFocusChangedSignal.Empty() )
+    {
+      mFocusChangedSignal.Emit(currentFocusedActor, actor);
+    }
+
+    Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor);
+    if( currentlyFocusedControl )
+    {
+      // Do we need it to remember if it was previously DISABLED?
+      currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL );
+      currentlyFocusedControl.ClearKeyInputFocus();
+    }
 
-      DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
+    DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
 
-      // Save the current focused actor
-      mCurrentFocusActor = actorID;
+    // Save the current focused actor
+    mCurrentFocusActor = actor;
 
-      DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
-      return true;
+    Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor);
+    if( newlyFocusedControl )
+    {
+      newlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::FOCUSED );
+      newlyFocusedControl.SetKeyInputFocus();
     }
+
+    // Push Current Focused Actor to FocusHistory
+    mFocusHistory.push_back( actor );
+
+    // Delete first element before add new element when Stack is full.
+    if( mFocusHistory.size() > MAX_HISTORY_AMOUNT )
+    {
+       FocusStackIterator beginPos = mFocusHistory.begin();
+       mFocusHistory.erase( beginPos );
+    }
+
+    DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
+    success = true;
+  }
+  else
+  {
+    DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
   }
 
-  DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
-  return false;
+  return success;
 }
 
 Actor KeyboardFocusManager::GetCurrentFocusActor()
 {
-  Actor rootActor = Stage::GetCurrent().GetRootLayer();
-  return rootActor.FindChildById(mCurrentFocusActor);
+  Actor actor = mCurrentFocusActor.GetHandle();
+  if( actor && ! actor.OnStage() )
+  {
+    // If the actor has been removed from the stage, then it should not be focused
+
+    actor.Reset();
+    mCurrentFocusActor.Reset();
+  }
+  return actor;
 }
 
 Actor KeyboardFocusManager::GetCurrentFocusGroup()
@@ -188,6 +277,44 @@ Actor KeyboardFocusManager::GetCurrentFocusGroup()
   return GetFocusGroup(GetCurrentFocusActor());
 }
 
+void KeyboardFocusManager::MoveFocusBackward()
+{
+  // Find Pre Focused Actor when the list size is more than 1
+  if( mFocusHistory.size() > 1 )
+  {
+    // Delete current focused actor in history
+    mFocusHistory.pop_back();
+
+    // If pre-focused actors are not on stage or deleted, remove them in stack
+    while( mFocusHistory.size() > 0 )
+    {
+      // Get pre focused actor
+      Actor target = mFocusHistory[ mFocusHistory.size() -1 ].GetHandle();
+
+      // Impl of Actor is not null
+      if( target && target.OnStage() )
+      {
+        // Delete pre focused actor in history because it will pushed again by SetCurrentFocusActor()
+        mFocusHistory.pop_back();
+        SetCurrentFocusActor( target );
+        break;
+      }
+      else
+      {
+        // Target is empty handle or off stage. Erase from queue
+        mFocusHistory.pop_back();
+      }
+    }
+
+    // if there is no actor which can get focus, then push current focus actor in stack again
+    if( mFocusHistory.size() == 0 )
+    {
+      Actor currentFocusedActor = GetCurrentFocusActor();
+      mFocusHistory.push_back( currentFocusedActor );
+    }
+  }
+}
+
 bool KeyboardFocusManager::IsLayoutControl(Actor actor) const
 {
   Toolkit::Control control = Toolkit::Control::DownCast(actor);
@@ -197,10 +324,11 @@ bool KeyboardFocusManager::IsLayoutControl(Actor actor) const
 Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const
 {
   // Get the actor's parent layout control that supports two dimensional keyboard navigation
-  Actor rootActor = Stage::GetCurrent().GetRootLayer();
+  Actor rootActor;
   Actor parent;
   if(actor)
   {
+    rootActor = DevelWindow::Get( actor ).GetRootLayer();
     parent = actor.GetParent();
   }
 
@@ -219,33 +347,106 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction
   bool succeed = false;
 
   // Go through the actor's hierarchy until we find a layout control that knows how to move the focus
-  Toolkit::Control parentLayoutControl = GetParentLayoutControl(currentFocusActor);
-  while(parentLayoutControl && !succeed)
+  Toolkit::Control parentLayoutControl = GetParentLayoutControl( currentFocusActor );
+  while( parentLayoutControl && !succeed )
   {
-    succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, currentFocusActor, direction);
-    parentLayoutControl = GetParentLayoutControl(parentLayoutControl);
+    succeed = DoMoveFocusWithinLayoutControl( parentLayoutControl, currentFocusActor, direction );
+    parentLayoutControl = GetParentLayoutControl( parentLayoutControl );
   }
 
-  if(!succeed && !mPreFocusChangeSignal.Empty())
+  if( !succeed )
   {
-    // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to
-    mIsWaitingKeyboardFocusChangeCommit = true;
-    Actor nextFocusableActor = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction);
-    mIsWaitingKeyboardFocusChangeCommit = false;
+    Actor nextFocusableActor;
+
+    Toolkit::Control currentFocusControl = Toolkit::Control::DownCast(currentFocusActor);
+
+    // If the current focused actor is a control, then find the next focusable actor via the focusable properties.
+    if( currentFocusControl )
+    {
+      int actorId = -1;
+      Property::Index index = Property::INVALID_INDEX;
+      Property::Value value;
+
+      // Find property index based upon focus direction
+      switch ( direction )
+      {
+        case Toolkit::Control::KeyboardFocus::LEFT:
+        {
+          index = Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID;
+          break;
+        }
+        case Toolkit::Control::KeyboardFocus::RIGHT:
+        {
+          index = Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID;
+          break;
+        }
+        case Toolkit::Control::KeyboardFocus::UP:
+        {
+          index = Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID;
+          break;
+        }
+        case Toolkit::Control::KeyboardFocus::DOWN:
+        {
+          index = Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID;
+          break;
+        }
+        default:
+          break;
+      }
+
+      // If the focusable property is set then determine next focusable actor
+      if( index != Property::INVALID_INDEX)
+      {
+        value = currentFocusActor.GetProperty( index );
+        actorId = value.Get<int>();
+
+        // If actor's id is valid then find actor form actor's id. The actor should be on the stage.
+        if( actorId != -1 )
+        {
+          if( currentFocusActor.GetParent() )
+          {
+            nextFocusableActor = currentFocusActor.GetParent().FindChildById( actorId );
+          }
+
+          if( !nextFocusableActor )
+          {
+            nextFocusableActor = DevelWindow::Get( currentFocusActor ).GetRootLayer().FindChildById( actorId );
+          }
+        }
+      }
+    }
 
-    if ( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() )
+    if( !nextFocusableActor )
+    {
+      // If the implementation of CustomAlgorithmInterface is provided then the PreFocusChangeSignal is no longer emitted.
+      if( mCustomAlgorithmInterface )
+      {
+        mIsWaitingKeyboardFocusChangeCommit = true;
+        nextFocusableActor = mCustomAlgorithmInterface->GetNextFocusableActor( currentFocusActor, Actor(), direction );
+        mIsWaitingKeyboardFocusChangeCommit = false;
+      }
+      else if( !mPreFocusChangeSignal.Empty() )
+      {
+        // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to
+        mIsWaitingKeyboardFocusChangeCommit = true;
+        nextFocusableActor = mPreFocusChangeSignal.Emit( currentFocusActor, Actor(), direction );
+        mIsWaitingKeyboardFocusChangeCommit = false;
+      }
+    }
+
+    if( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() )
     {
       // Whether the next focusable actor is a layout control
-      if(IsLayoutControl(nextFocusableActor))
+      if( IsLayoutControl( nextFocusableActor ) )
       {
         // If so, move the focus inside it.
-        Toolkit::Control layoutControl = Toolkit::Control::DownCast(nextFocusableActor);
-        succeed = DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction);
+        Toolkit::Control layoutControl = Toolkit::Control::DownCast( nextFocusableActor) ;
+        succeed = DoMoveFocusWithinLayoutControl( layoutControl, currentFocusActor, direction );
       }
       else
       {
         // Otherwise, just set focus to the next focusable actor
-        succeed = SetCurrentFocusActor(nextFocusableActor);
+        succeed = SetCurrentFocusActor( nextFocusableActor );
       }
     }
   }
@@ -361,22 +562,29 @@ void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
 void KeyboardFocusManager::ClearFocus()
 {
   Actor actor = GetCurrentFocusActor();
-  if(actor)
+  if( actor )
   {
-    if(mFocusIndicatorActor)
+    if( mFocusIndicatorActor )
     {
-      actor.Remove(mFocusIndicatorActor);
+      actor.Remove( mFocusIndicatorActor );
     }
 
     // Send notification for the change of focus actor
     if( !mFocusChangedSignal.Empty() )
     {
-      mFocusChangedSignal.Emit(actor, Actor());
+      mFocusChangedSignal.Emit( actor, Actor() );
+    }
+
+    Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast( actor );
+    if( currentlyFocusedControl )
+    {
+      currentlyFocusedControl.SetProperty( DevelControl::Property::STATE, DevelControl::NORMAL );
+      currentlyFocusedControl.ClearKeyInputFocus();
     }
   }
 
-  mCurrentFocusActor = 0;
-  mIsFocusIndicatorEnabled = false;
+  mCurrentFocusActor.Reset();
+  mIsFocusIndicatorShown = static_cast<int>(mAlwaysShowIndicator);
 }
 
 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
@@ -451,62 +659,24 @@ void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator)
 
 Actor KeyboardFocusManager::GetFocusIndicatorActor()
 {
-  return mFocusIndicatorActor;
-}
-
-void KeyboardFocusManager::CreateDefaultFocusIndicatorActor()
-{
-  // Create a focus indicator actor shared by all the keyboard focusable actors
-  Image borderImage = ResourceImage::New(FOCUS_BORDER_IMAGE_PATH);
-
-  ImageActor focusIndicator = ImageActor::New(borderImage);
-  focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
-  focusIndicator.SetStyle( ImageActor::STYLE_NINE_PATCH );
-  focusIndicator.SetNinePatchBorder(FOCUS_BORDER_IMAGE_BORDER);
-  focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f));
-
-  // Apply size constraint to the focus indicator
-  focusIndicator.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+  if( ! mFocusIndicatorActor )
+  {
+    // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors
+    mFocusIndicatorActor = Toolkit::ImageView::New( FOCUS_BORDER_IMAGE_PATH );
 
-  SetFocusIndicatorActor(focusIndicator);
-}
+    // Apply size constraint to the focus indicator
+    mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+  }
 
-void KeyboardFocusManager::OnPhysicalKeyboardStatusChanged(PhysicalKeyboard keyboard)
-{
-  mIsKeyboardFocusEnabled = keyboard.IsAttached();
+  mFocusIndicatorActor.SetParentOrigin( ParentOrigin::CENTER );
+  mFocusIndicatorActor.SetAnchorPoint( AnchorPoint::CENTER );
+  mFocusIndicatorActor.SetPosition(0.0f, 0.0f);
 
-  if(mIsKeyboardFocusEnabled)
-  {
-    // Show indicator when keyboard focus turned on if there is focused actor.
-    Actor actor = GetCurrentFocusActor();
-    if(actor)
-    {
-      if(mFocusIndicatorActor)
-      {
-        actor.Add(mFocusIndicatorActor);
-      }
-    }
-    mIsFocusIndicatorEnabled = true;
-  }
-  else
-  {
-    // Hide indicator when keyboard focus turned off
-    Actor actor = GetCurrentFocusActor();
-    if(actor)
-    {
-      actor.Remove(mFocusIndicatorActor);
-    }
-    mIsFocusIndicatorEnabled = false;
-  }
+  return mFocusIndicatorActor;
 }
 
 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 {
-  if(!mIsKeyboardFocusEnabled)
-  {
-    return;
-  }
-
   AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
   bool isAccessibilityEnabled = accessibilityAdaptor.IsEnabled();
 
@@ -514,6 +684,11 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 
   std::string keyName = event.keyPressedName;
 
+  if( mIsFocusIndicatorShown == -1 )
+  {
+    GetConfigurationFromStyleManger();
+  }
+
   bool isFocusStartableKey = false;
 
   if(event.state == KeyEvent::Down)
@@ -522,10 +697,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     {
       if(!isAccessibilityEnabled)
       {
-        if(!mIsFocusIndicatorEnabled)
+        if(!mIsFocusIndicatorShown)
         {
           // Show focus indicator
-          mIsFocusIndicatorEnabled = true;
+          mIsFocusIndicatorShown = 1;
         }
         else
         {
@@ -545,10 +720,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     {
       if(!isAccessibilityEnabled)
       {
-        if(!mIsFocusIndicatorEnabled)
+        if(!mIsFocusIndicatorShown)
         {
           // Show focus indicator
-          mIsFocusIndicatorEnabled = true;
+          mIsFocusIndicatorShown = 1;
         }
         else
         {
@@ -566,10 +741,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "Up" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = true;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -581,10 +756,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "Down" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = true;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -594,12 +769,42 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 
       isFocusStartableKey = true;
     }
+    else if (keyName == "Prior" && !isAccessibilityEnabled)
+    {
+      if(!mIsFocusIndicatorShown)
+      {
+        // Show focus indicator
+        mIsFocusIndicatorShown = 1;
+      }
+      else
+      {
+        // Move the focus towards the previous page
+        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
+      }
+
+      isFocusStartableKey = true;
+    }
+    else if (keyName == "Next" && !isAccessibilityEnabled)
+    {
+      if(!mIsFocusIndicatorShown)
+      {
+        // Show focus indicator
+        mIsFocusIndicatorShown = 1;
+      }
+      else
+      {
+        // Move the focus towards the next page
+        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
+      }
+
+      isFocusStartableKey = true;
+    }
     else if (keyName == "Tab" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = true;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -612,10 +817,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "space" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = true;
+        mIsFocusIndicatorShown = 1;
       }
 
       isFocusStartableKey = true;
@@ -623,10 +828,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     else if (keyName == "" && !isAccessibilityEnabled)
     {
       // Check the fake key event for evas-plugin case
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = true;
+        mIsFocusIndicatorShown = 1;
       }
 
       isFocusStartableKey = true;
@@ -635,15 +840,18 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     {
       // Emit signal to go back to the previous view???
     }
+    else if (keyName == "Escape" && !isAccessibilityEnabled)
+    {
+    }
   }
   else if(event.state == KeyEvent::Up)
   {
     if (keyName == "Return")
     {
-      if(!mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
+      if(!mIsFocusIndicatorShown && !isAccessibilityEnabled)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = true;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -668,28 +876,39 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
   }
 
-  if(isFocusStartableKey && mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
+  if(isFocusStartableKey && mIsFocusIndicatorShown && !isAccessibilityEnabled)
   {
     Actor actor = GetCurrentFocusActor();
-    if( !actor )
+    if( actor )
+    {
+      if( mEnableFocusIndicator )
+      {
+        // Make sure the focused actor is highlighted
+        actor.Add( GetFocusIndicatorActor() );
+      }
+    }
+    else
     {
       // No actor is focused but keyboard focus is activated by the key press
       // Let's try to move the initial focus
       MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
     }
-    else if(mFocusIndicatorActor)
-    {
-      // Make sure the focused actor is highlighted
-      actor.Add(mFocusIndicatorActor);
-    }
   }
 }
 
-void KeyboardFocusManager::OnTouched(const TouchEvent& touchEvent)
+void KeyboardFocusManager::OnTouch(const TouchData& touch)
 {
+  // if mIsFocusIndicatorShown is -1, it means Configuration is not loaded.
+  // Try to load configuration.
+  if( mIsFocusIndicatorShown == -1 )
+  {
+    GetConfigurationFromStyleManger();
+  }
+
   // Clear the focus when user touch the screen.
   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
-  if( ( touchEvent.GetPointCount() < 1 ) || ( touchEvent.GetPoint( 0 ).state == TouchPoint::Down ) )
+  // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
+  if( (( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN )) && mClearFocusOnTouch )
   {
     ClearFocus();
   }
@@ -720,17 +939,17 @@ bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTracke
   Dali::BaseHandle handle( object );
 
   bool connected( true );
-  KeyboardFocusManager* manager = dynamic_cast<KeyboardFocusManager*>( object );
+  KeyboardFocusManager* manager = static_cast< KeyboardFocusManager* >( object ); // TypeRegistry guarantees that this is the correct type.
 
   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE ) )
   {
     manager->PreFocusChangeSignal().Connect( tracker, functor );
   }
-  if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) )
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) )
   {
     manager->FocusChangedSignal().Connect( tracker, functor );
   }
-  if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED ) )
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED ) )
   {
     manager->FocusGroupChangedSignal().Connect( tracker, functor );
   }
@@ -747,6 +966,26 @@ bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTracke
   return connected;
 }
 
+void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interface)
+{
+  mCustomAlgorithmInterface = &interface;
+}
+
+void KeyboardFocusManager::EnableFocusIndicator(bool enable)
+{
+  if( !enable && mFocusIndicatorActor )
+  {
+    mFocusIndicatorActor.Unparent();
+  }
+
+  mEnableFocusIndicator = enable;
+}
+
+bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
+{
+  return mEnableFocusIndicator;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit