Merge "Add clockwise and counter clockwise direction type and movefocus" into devel...
authorjoogab yun <joogab.yun@samsung.com>
Mon, 21 Mar 2022 00:57:40 +0000 (00:57 +0000)
committerGerrit Code Review <gerrit@review>
Mon, 21 Mar 2022 00:57:40 +0000 (00:57 +0000)
1  2 
automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h

@@@ -55,12 -55,11 +55,12 @@@ public
    : mInterfaceVerified(interfaceVerified),
      mCurrentFocusedActor(),
      mProposedActorToFocus(),
 -    mDirection(Control::KeyboardFocus::LEFT)
 +    mDirection(Control::KeyboardFocus::LEFT),
 +    mDeviceName("")
    {
    }
  
 -  Actor GetNextFocusableActor(Actor currentFocusedActor, Actor proposedActorToFocus, Control::KeyboardFocus::Direction direction)
 +  Actor GetNextFocusableActor(Actor currentFocusedActor, Actor proposedActorToFocus, Control::KeyboardFocus::Direction direction, const std::string& deviceName)
    {
      tet_infoline("Verifying CustomAlgorithm()");
  
@@@ -69,7 -68,6 +69,7 @@@
      mCurrentFocusedActor  = currentFocusedActor;
      mProposedActorToFocus = proposedActorToFocus;
      mDirection            = direction;
 +    mDeviceName           = deviceName;
  
      return mProposedActorToFocus;
    }
      mCurrentFocusedActor  = Actor();
      mProposedActorToFocus = Actor();
      mDirection            = Control::KeyboardFocus::LEFT;
 +    mDeviceName           = "";
    }
  
    bool&                             mInterfaceVerified;
    Actor                             mCurrentFocusedActor;
    Actor                             mProposedActorToFocus;
    Control::KeyboardFocus::Direction mDirection;
 +  std::string mDeviceName;
  };
  
  // Functors to test whether PreFocusChange signal is emitted when the keyboard focus is about to change
@@@ -582,19 -578,17 +582,19 @@@ int UtcDaliKeyboardFocusManagerCustomAl
    preFocusChangeCallback.Reset();
  
    bool            customAlgorithmInterfaceVerified = false;
 +  std::string     deviceName                       = "deviceName";
    CustomAlgorithm customAlgorithm(customAlgorithmInterfaceVerified);
    Toolkit::DevelKeyboardFocusManager::SetCustomAlgorithm(manager, customAlgorithm);
  
    // Move the focus towards right
 -  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false);
 +  DALI_TEST_CHECK(Toolkit::DevelKeyboardFocusManager::MoveFocus(manager, Control::KeyboardFocus::RIGHT, deviceName) == false);
  
    // Because no layout control in the stage and the first actor is focused, it should invoke CustomAlgorithm
    DALI_TEST_CHECK(customAlgorithm.mInterfaceVerified);
    DALI_TEST_CHECK(customAlgorithm.mCurrentFocusedActor == Actor());
    DALI_TEST_CHECK(customAlgorithm.mProposedActorToFocus == Actor());
    DALI_TEST_CHECK(customAlgorithm.mDirection == Control::KeyboardFocus::RIGHT);
 +  DALI_TEST_EQUALS(customAlgorithm.mDeviceName, deviceName, TEST_LOCATION );
    customAlgorithm.Reset();
  
    // Check that the focus is set on the first actor
    focusChangedCallback.Reset();
  
    // Move the focus towards right
 -  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false);
 +  DALI_TEST_CHECK(Toolkit::DevelKeyboardFocusManager::MoveFocus(manager, Control::KeyboardFocus::RIGHT, deviceName) == false);
  
    // Because no layout control in the stage and the first actor is focused, it should invoke CustomAlgorithm
    DALI_TEST_CHECK(customAlgorithm.mInterfaceVerified);
    DALI_TEST_CHECK(customAlgorithm.mCurrentFocusedActor == first);
    DALI_TEST_CHECK(customAlgorithm.mProposedActorToFocus == Actor());
    DALI_TEST_CHECK(customAlgorithm.mDirection == Control::KeyboardFocus::RIGHT);
 +  DALI_TEST_EQUALS(customAlgorithm.mDeviceName, deviceName, TEST_LOCATION );
    customAlgorithm.Reset();
  
    // Check that the focus is set on the second actor
    focusChangedCallback.Reset();
  
    // Move the focus towards up
 -  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::UP) == false);
 +  DALI_TEST_CHECK(Toolkit::DevelKeyboardFocusManager::MoveFocus(manager, Control::KeyboardFocus::UP, deviceName) == false);
  
    // Because no layout control in the stage and no actor is focused, it should invoke CustomAlgorithm
    DALI_TEST_CHECK(customAlgorithm.mInterfaceVerified);
    DALI_TEST_CHECK(customAlgorithm.mCurrentFocusedActor == second);
    DALI_TEST_CHECK(customAlgorithm.mProposedActorToFocus == Actor());
    DALI_TEST_CHECK(customAlgorithm.mDirection == Control::KeyboardFocus::UP);
 +  DALI_TEST_EQUALS(customAlgorithm.mDeviceName, deviceName, TEST_LOCATION );
    customAlgorithm.Reset();
    DALI_TEST_CHECK(!focusChangedCallback.mSignalVerified);
  
@@@ -678,12 -670,16 +678,16 @@@ int UtcDaliKeyboardFocusManagerFocusabl
    button1.SetProperty(Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::Value((int)button2.GetProperty<int>(Actor::Property::ID)));
    button1.SetProperty(Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::Value((int)button2.GetProperty<int>(Actor::Property::ID)));
    button1.SetProperty(Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::Value((int)button2.GetProperty<int>(Actor::Property::ID)));
+   button1.SetProperty(Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::Value((int)button2.GetProperty< int >( Actor::Property::ID)));
+   button1.SetProperty(Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::Value((int)button2.GetProperty< int >( Actor::Property::ID)));
  
    // set the navigation properties of button2
    button2.SetProperty(Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::Value((int)button1.GetProperty<int>(Actor::Property::ID)));
    button2.SetProperty(Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::Value((int)button1.GetProperty<int>(Actor::Property::ID)));
    button2.SetProperty(Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::Value((int)button1.GetProperty<int>(Actor::Property::ID)));
    button2.SetProperty(Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::Value((int)button1.GetProperty<int>(Actor::Property::ID)));
+   button2.SetProperty(Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::Value((int)button1.GetProperty< int >( Actor::Property::ID)));
+   button2.SetProperty(Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::Value((int)button1.GetProperty< int >( Actor::Property::ID)));
  
    // Move the focus towards left
    DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
    DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
    focusChangedCallback.Reset();
  
+   // Move the focus towards clockwise
+   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::CLOCKWISE) == true);
+   // Confirm whether focus is moved to button2
+   DALI_TEST_EQUALS(button2.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button1);
+   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button2);
+   focusChangedCallback.Reset();
+   // Move the focus towards clockwise
+   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::COUNTER_CLOCKWISE) == true);
+   // Confirm whether focus is moved to button1
+   DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button2);
+   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
+   focusChangedCallback.Reset();
    // Create a 1x1 table view and try to move focus inside it
    TableView tableView = TableView::New(1, 1);
    application.GetScene().Add(tableView);
@@@ -1967,8 -1983,6 +1991,8 @@@ int UtcDaliKeyboardFocusManagerEnableDe
    // button1 -- button2
    button1.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
    button2.SetProperty(Actor::Property::POSITION, Vector2(100.0f, 0.0f));
 +  button1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
 +  button2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
  
    // flush the queue and render once
    application.SendNotification();
    // Move the focus towards left, The focus move will success because the default algorithm is enabled.
    // [button1] -- button2
    DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
 -  // Confirm whether focus is moved to button2
 +  // Confirm whether focus is moved to button1
    DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
    DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
    DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button2);
    DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
    focusChangedCallback.Reset();
  
 +  // Clears focus.
 +  manager.ClearFocus();
 +  // There is no actor focused.
 +  // button1 -- button2
 +  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
 +
 +  // Move the focus towards right, The focus is on the actor closest to the top left of the window.
 +  // [button1] -- button2
 +  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
 +
 +  // Confirm whether focus is moved to button1
 +  DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
 +  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
 +  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor());
 +  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
 +  focusChangedCallback.Reset();
 +
 +
    END_TEST;
  }
  
@@@ -2125,3 -2121,64 +2149,64 @@@ int UtcDaliKeyboardFocusManagerCheckWhe
  
    END_TEST;
  }
+ int UtcDaliKeyboardFocusManagerChangeFocusDirectionByCustomWheelEvent(void)
+ {
+   ToolkitTestApplication application;
+   tet_infoline(" UtcDaliKeyboardFocusManagerChangeFocusDirectionByCustomWheelEvent");
+   Dali::Integration::Scene scene = application.GetScene();
+   KeyboardFocusManager manager = KeyboardFocusManager::Get();
+   DALI_TEST_CHECK(manager);
+   bool focusChangedSignalVerified = false;
+   FocusChangedCallback focusChangedCallback(focusChangedSignalVerified);
+   manager.FocusChangedSignal().Connect( &focusChangedCallback, &FocusChangedCallback::Callback );
+   Integration::WheelEvent clockwiseEvent(Integration::WheelEvent::CUSTOM_WHEEL, 0, 0u, Vector2(0.0f, 0.0f), 1, 1000u);
+   Integration::WheelEvent counterClockwiseEvent(Integration::WheelEvent::CUSTOM_WHEEL, 0, 0u, Vector2(0.0f, 0.0f), -1, 1100u);
+   // Create the first button
+   PushButton first = PushButton::New();
+   first.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
+   scene.Add(first);
+   // Create the second button
+   PushButton second = PushButton::New();
+   second.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
+   scene.Add(second);
+    // set the navigation properties
+   first.SetProperty(Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::Value((int)second.GetProperty< int >( Actor::Property::ID )));
+   second.SetProperty(Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::Value((int)first.GetProperty< int >( Actor::Property::ID )));
+   // Set the focus to the first actor
+   DALI_TEST_CHECK(manager.SetCurrentFocusActor(first) == true);
+   DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
+   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor());
+   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == first);
+   focusChangedCallback.Reset();
+   // Send the clockwise wheel event to move the focus towards clockwise
+   application.ProcessEvent(clockwiseEvent);
+   DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second);
+   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == first);
+   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == second);
+   focusChangedCallback.Reset();
+   // Send the counter clockwise wheel event to move the focus towards count clockwise
+   application.ProcessEvent(counterClockwiseEvent);
+   DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
+   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == second);
+   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == first);
+   focusChangedCallback.Reset();
+   // Clear the focus
+   manager.ClearFocus();
+   END_TEST;
+ }
@@@ -201,6 -201,20 +201,20 @@@ enu
     * @note The representative Accessible object will not appear in the AT-SPI tree.
     */
    ACCESSIBILITY_HIDDEN,
+   /**
+    * @brief The actor ID of the clockwise focusable control.
+    * @details Name "clockwiseFocusableActorId", type Property::INTEGER.
+    *
+    */
+   CLOCKWISE_FOCUSABLE_ACTOR_ID,
+   /**
+    * @brief The actor ID of the conter-clockwise focusable control.
+    * @details Name "counterClockwiseFocusableActorId", type Property::INTEGER.
+    *
+    */
+   COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID,
  };
  
  } // namespace Property
@@@ -561,6 -575,25 +575,6 @@@ DALI_TOOLKIT_API Dali::Accessibility::S
   */
  DALI_TOOLKIT_API void NotifyAccessibilityStateChange(Toolkit::Control control, Dali::Accessibility::States states, bool recurse);
  
 -/**
 - * The method allows to set specific constructor for creating accessibility structure
 - *
 - * Thank to this method hierarchy of accessibility objects can be based on internal hierarchy of Actors.
 - * It prevents from necessity of keeping two trees synchronized.
 - * The method should be called inside OnInitialize method of all classes inheriting from Control.
 - *
 - * Possible usage can be as follows:
 - * @code
 - *   SetAccessibilityConstructor( []( Dali::Actor actor ) {
 -       return std::unique_ptr< Dali::Accessibility::Accessible >(
 -       new ControlAccessible( actor, Dali::Accessibility::Role::DIALOG, true ) );
 -      } );
 -  * @endcode
 -  *
 -  * param constructor callback creating Accessible object
 -  */
 -DALI_TOOLKIT_API void SetAccessibilityConstructor(Dali::Actor control, std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Dali::Actor)> constructor);
 -
  } // namespace DevelControl
  
  } // namespace Toolkit
@@@ -445,19 -445,6 +445,19 @@@ static bool IsShowingGeometryOnScreen(D
    return rect.width > 0 && rect.height > 0;
  }
  
 +Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
 +{
 +  auto control = Toolkit::Control::DownCast(actor);
 +  if (!control)
 +  {
 +    return nullptr;
 +  }
 +
 +  auto& controlImpl = Toolkit::Internal::GetImplementation(control);
 +
 +  return controlImpl.GetAccessibleObject();
 +}
 +
  } // unnamed namespace
  
  // clang-format off
@@@ -483,6 -470,8 +483,8 @@@ const PropertyRegistration Control::Imp
  const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes",        Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
  const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents",              Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS,              Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
  const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden",            Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN,             Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+ const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId",      Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID,     Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+ const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
  
  // clang-format on
  
@@@ -494,6 -483,8 +496,8 @@@ Control::Impl::Impl(Control& controlImp
    mRightFocusableActorId(-1),
    mUpFocusableActorId(-1),
    mDownFocusableActorId(-1),
+   mClockwiseFocusableActorId(-1),
+   mCounterClockwiseFocusableActorId(-1),
    mStyleName(""),
    mBackgroundColor(Color::TRANSPARENT),
    mStartingPinchScale(nullptr),
    mNeedToEmitResourceReady(false),
    mDispatchKeyEvents(true)
  {
 -  Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(
 -    [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
 -      return Control::Impl::GetAccessibilityObject(actor);
 -    });
 -
 -  mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
 -    return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::UNKNOWN));
 -  };
 +  Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
  }
  
  Control::Impl::~Impl()
@@@ -558,7 -556,13 +562,7 @@@ const Control::Impl& Control::Impl::Get
  
  void Control::Impl::CheckHighlightedObjectGeometry()
  {
 -  auto accessible = dynamic_cast<Dali::Toolkit::DevelControl::ControlAccessible*>(mAccessibilityObject.get());
 -  if(!accessible)
 -  {
 -    DALI_LOG_ERROR("accessible is not a pointer to a DevelControl::ControlAccessible type");
 -    return;
 -  }
 -
 +  auto accessible     = GetAccessibleObject();
    auto lastPosition   = accessible->GetLastPosition();
    auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
    auto rect = GetShowingGeometry(accessibleRect, accessible);
        // notify AT-clients on outgoing moves only
        if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
        {
 -        mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
 +        accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
        }
        break;
      }
@@@ -1358,7 -1362,7 +1362,7 @@@ void Control::Impl::SetProperty(BaseObj
          {
            controlImpl.mImpl->mAccessibilityHidden = hidden;
  
 -          auto* accessible = controlImpl.mImpl->GetAccessibilityObject();
 +          auto* accessible = controlImpl.GetAccessibleObject();
            auto* parent     = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
            if (parent)
            {
          }
          break;
        }
+       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
+       {
+         int focusId;
+         if(value.Get(focusId))
+         {
+           controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
+         }
+         break;
+       }
+       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
+       {
+         int focusId;
+         if(value.Get(focusId))
+         {
+           controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
+         }
+         break;
+       }
      }
    }
  }
@@@ -1527,6 -1549,18 +1549,18 @@@ Property::Value Control::Impl::GetPrope
          value = controlImpl.mImpl->mAccessibilityHidden;
          break;
        }
+       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
+       {
+         value = controlImpl.mImpl->mClockwiseFocusableActorId;
+         break;
+       }
+       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
+       {
+         value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
+         break;
+       }
      }
    }
  
@@@ -2051,14 -2085,27 +2085,14 @@@ void Control::Impl::OnIdleCallback(
    mIdleCallback = nullptr;
  }
  
 -Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
 +Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
  {
 -  if(!mAccessibilityObject)
 +  if(!mAccessibleObject)
    {
 -    mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
 +    mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
    }
 -  return mAccessibilityObject.get();
 -}
  
 -Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
 -{
 -  if(actor)
 -  {
 -    auto control = Dali::Toolkit::Control::DownCast(actor);
 -    if(control)
 -    {
 -      auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
 -      return controlImpl->mImpl->GetAccessibilityObject();
 -    }
 -  }
 -  return nullptr;
 +  return mAccessibleObject.get();
  }
  
  } // namespace Internal
@@@ -423,9 -423,20 +423,9 @@@ public
    void UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties);
  
    /**
 -   * @brief Gets the current control's accessible object.
 -   *
 -   * @return The handle to Accessible object
 -   */
 -  Dali::Accessibility::Accessible* GetAccessibilityObject();
 -
 -  /**
 -   * @brief Gets Accessible object handle.
 -   *
 -   * The method acquires Accessible handle from Actor object
 -   * @param  actor Actor object
 -   * @return The handle to Accessible object
 +   * @copydoc Dali::Toolkit::Internal::Control::GetAccessibleObject()
     */
 -  static Dali::Accessibility::Accessible* GetAccessibilityObject(Dali::Actor actor);
 +  Toolkit::DevelControl::ControlAccessible* GetAccessibleObject();
  
  private:
    /**
@@@ -500,6 -511,8 +500,8 @@@ public
    int mRightFocusableActorId; ///< Actor ID of Right focusable control.
    int mUpFocusableActorId;    ///< Actor ID of Up focusable control.
    int mDownFocusableActorId;  ///< Actor ID of Down focusable control.
+   int mClockwiseFocusableActorId;  ///< Actor ID of Clockwise focusable control.
+   int mCounterClockwiseFocusableActorId;  ///< Actor ID of Counter clockwise focusable control.
  
    RegisteredVisualContainer                 mVisuals; ///< Stores visuals needed by the control, non trivial type so std::vector used.
    std::string                               mStyleName;
    Dali::Accessibility::Role mAccessibilityRole = Dali::Accessibility::Role::UNKNOWN;
  
    std::map<Dali::Accessibility::RelationType, std::set<Accessibility::Accessible*>> mAccessibilityRelations;
 -  std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Actor)>            mAccessibilityConstructor;
 -  std::unique_ptr<Dali::Accessibility::Accessible>                                  mAccessibilityObject;
 +  std::unique_ptr<Toolkit::DevelControl::ControlAccessible>                         mAccessibleObject;
  
    // Gesture Detection
    PinchGestureDetector     mPinchGestureDetector;
    static const PropertyRegistration PROPERTY_21;
    static const PropertyRegistration PROPERTY_22;
    static const PropertyRegistration PROPERTY_23;
+   static const PropertyRegistration PROPERTY_24;
+   static const PropertyRegistration PROPERTY_25;
  
  private:
    // Accessibility - notification for highlighted object to check if it is showing.
@@@ -29,6 -29,7 +29,7 @@@
  #include <dali/public-api/animation/constraints.h>
  #include <dali/public-api/events/key-event.h>
  #include <dali/public-api/events/touch-event.h>
+ #include <dali/public-api/events/wheel-event.h>
  #include <dali/public-api/object/property-map.h>
  #include <dali/public-api/object/type-registry-helper.h>
  #include <dali/public-api/object/type-registry.h>
@@@ -145,7 -146,8 +146,8 @@@ void KeyboardFocusManager::OnAdaptorIni
      {
        (*iter).KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
        (*iter).TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouch);
-       (*iter).WheelEventGeneratedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWheelEvent);
+       (*iter).WheelEventGeneratedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnCustomWheelEvent);
+       (*iter).WheelEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWheelEvent);
        Dali::Window window = DevelWindow::DownCast(*iter);
        if(window)
        {
@@@ -162,7 -164,8 +164,8 @@@ void KeyboardFocusManager::OnSceneHolde
  {
    sceneHolder.KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
    sceneHolder.TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouch);
-   sceneHolder.WheelEventGeneratedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWheelEvent);
+   sceneHolder.WheelEventGeneratedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnCustomWheelEvent);
+   sceneHolder.WheelEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWheelEvent);
    Dali::Window window = DevelWindow::DownCast(sceneHolder);
    if(window)
    {
@@@ -420,7 -423,7 +423,7 @@@ Toolkit::Control KeyboardFocusManager::
    return Toolkit::Control::DownCast(parent);
  }
  
 -bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction)
 +bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction, const std::string& deviceName)
  {
    Actor currentFocusActor = GetCurrentFocusActor();
  
            index = Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID;
            break;
          }
+         case Toolkit::Control::KeyboardFocus::CLOCKWISE:
+         {
+           index = Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID;
+           break;
+         }
+         case Toolkit::Control::KeyboardFocus::COUNTER_CLOCKWISE:
+         {
+           index = Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID;
+           break;
+         }
          default:
            break;
        }
        if(mCustomAlgorithmInterface)
        {
          mIsWaitingKeyboardFocusChangeCommit = true;
 -        nextFocusableActor                  = mCustomAlgorithmInterface->GetNextFocusableActor(currentFocusActor, Actor(), direction);
 +        nextFocusableActor                  = mCustomAlgorithmInterface->GetNextFocusableActor(currentFocusActor, Actor(), direction, deviceName);
          mIsWaitingKeyboardFocusChangeCommit = false;
        }
        else if(!mPreFocusChangeSignal.Empty())
          nextFocusableActor                  = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction);
          mIsWaitingKeyboardFocusChangeCommit = false;
        }
 -      else if(mEnableDefaultAlgorithm && currentFocusActor)
 +      else if (mEnableDefaultAlgorithm)
        {
 -        // We should find it among the actors nearby.
 -        Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor);
 -        if(window)
 +        Layer rootLayer;
 +        if (currentFocusActor)
          {
 -          nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(window.GetRootLayer(), currentFocusActor, direction);
 +          // Find the window of the focused actor.
 +          Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor);
 +          if (window)
 +          {
 +            rootLayer = window.GetRootLayer();
 +          }
 +        }
 +        else
 +        {
 +          // Searches from the currently focused window.
 +          rootLayer = mCurrentFocusedWindow.GetHandle();
 +        }
 +        if (rootLayer)
 +        {
 +          // We should find it among the actors nearby.
 +          nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(rootLayer, currentFocusActor, direction);
          }
        }
      }
@@@ -785,8 -784,7 +798,8 @@@ Actor KeyboardFocusManager::GetFocusInd
  
  void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
  {
 -  std::string keyName = event.GetKeyName();
 +  const std::string& keyName = event.GetKeyName();
 +  const std::string& deviceName = event.GetDeviceName();
  
    if(mIsFocusIndicatorShown == UNKNOWN)
    {
        else
        {
          // Move the focus towards left
 -        MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
 +        MoveFocus(Toolkit::Control::KeyboardFocus::LEFT, deviceName);
        }
  
        isFocusStartableKey = true;
        else
        {
          // Move the focus towards right
 -        MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
 +        MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT, deviceName);
        }
  
        isFocusStartableKey = true;
        else
        {
          // Move the focus towards up
 -        MoveFocus(Toolkit::Control::KeyboardFocus::UP);
 +        MoveFocus(Toolkit::Control::KeyboardFocus::UP, deviceName);
        }
  
        isFocusStartableKey = true;
        else
        {
          // Move the focus towards down
 -        MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
 +        MoveFocus(Toolkit::Control::KeyboardFocus::DOWN, deviceName);
        }
  
        isFocusStartableKey = true;
        else
        {
          // Move the focus towards the previous page
 -        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
 +        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP, deviceName);
        }
  
        isFocusStartableKey = true;
        else
        {
          // Move the focus towards the next page
 -        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
 +        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN, deviceName);
        }
  
        isFocusStartableKey = true;
          if(!DoMoveFocusToNextFocusGroup(!event.IsShiftModifier()))
          {
            // If the focus group is not changed, Move the focus towards forward, "Shift-Tap" key moves the focus towards backward.
 -          MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::BACKWARD : Toolkit::Control::KeyboardFocus::FORWARD);
 +          MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::BACKWARD : Toolkit::Control::KeyboardFocus::FORWARD, deviceName);
          }
        }
  
      {
        // 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);
 +      MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT, deviceName);
      }
    }
  }
@@@ -1007,19 -1005,29 +1020,29 @@@ void KeyboardFocusManager::OnTouch(cons
    }
  }
  
- bool KeyboardFocusManager::OnWheelEvent(const WheelEvent& event)
+ void KeyboardFocusManager::OnWheelEvent(const WheelEvent& event)
+ {
+   if(event.GetType() == Dali::WheelEvent::CUSTOM_WHEEL)
+   {
+     Toolkit::Control::KeyboardFocus::Direction direction = (event.GetDelta() > 0) ? Toolkit::Control::KeyboardFocus::CLOCKWISE : Toolkit::Control::KeyboardFocus::COUNTER_CLOCKWISE;
+     // Move the focus
+     MoveFocus(direction);
+   }
+ }
+ bool KeyboardFocusManager::OnCustomWheelEvent(const WheelEvent& event)
  {
    bool consumed = false;
    Actor actor = GetCurrentFocusActor();
    if(actor)
    {
      // Notify the actor about the wheel event
-     consumed = EmitWheelSignals(actor, event);
+     consumed = EmitCustomWheelSignals(actor, event);
    }
    return consumed;
  }
  
- bool KeyboardFocusManager::EmitWheelSignals(Actor actor, const WheelEvent& event)
+ bool KeyboardFocusManager::EmitCustomWheelSignals(Actor actor, const WheelEvent& event)
  {
    bool consumed = false;
  
        if(parent &&
           (parent == oldParent))
        {
-         consumed = EmitWheelSignals(parent, event);
+         consumed = EmitCustomWheelSignals(parent, event);
        }
      }
    }
@@@ -90,7 -90,7 +90,7 @@@ public
    /**
     * @copydoc Toolkit::KeyboardFocusManager::MoveFocus
     */
 -  bool MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction);
 +  bool MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction, const std::string& deviceName = "");
  
    /**
     * @copydoc Toolkit::KeyboardFocusManager::ClearFocus
@@@ -295,7 -295,13 +295,13 @@@ private
     * Callback for the wheel event when the custom wheel event occurs.
     * @param[in] wheel The WheelEvent information
     */
-   bool OnWheelEvent(const WheelEvent& wheel);
+   bool OnCustomWheelEvent(const WheelEvent& wheel);
+   /**
+    * Callback for the wheel event when the wheel event occurs.
+    * @param[in] wheel The WheelEvent information
+    */
+   void OnWheelEvent(const WheelEvent& wheel);
  
    /**
     * Called when the window focus is changed.
     * @param[in]  event  The WheelEvent.
     * @return True if WheelEvent is consumed.
     */
-   bool EmitWheelSignals(Actor actor, const WheelEvent& event);
+   bool EmitCustomWheelSignals(Actor actor, const WheelEvent& event);
  
  private:
    // Undefined