[Tizen] For custom wheel events, event propagation starts from the focused actor. 46/271546/1 accepted/tizen/6.5/unified/20220223.132705 submit/tizen_6.5/20220223.022356
authorjoogab.yun <joogab.yun@samsung.com>
Wed, 26 Jan 2022 06:59:56 +0000 (15:59 +0900)
committerjoogab.yun <joogab.yun@samsung.com>
Wed, 23 Feb 2022 01:12:20 +0000 (10:12 +0900)
Previously, RotaryEvents could always be received only by window.
Now, User can receive Rotary Events in focused View as well.
It is also possible to propagate events to the parent view.

If there is no focused View, the window will receive the event.

This only applies to Rotary Event(CustomWheel type).

Change-Id: Ifc2f180246bb282efeb5094f970f38b0b76d8dad

automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder-impl.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-window.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-window.h
automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h

index fb67a4b..8075dbe 100644 (file)
@@ -119,6 +119,8 @@ public:
 
   Dali::Integration::SceneHolder::WheelEventSignalType& WheelEventSignal();
 
+  Dali::Integration::SceneHolder::WheelEventGeneratedSignalType& WheelEventGeneratedSignal();
+
   Integration::Scene GetScene();
 
   Dali::RenderSurfaceInterface& GetRenderSurface();
index e18809a..8bcb3c0 100644 (file)
@@ -115,6 +115,11 @@ Dali::Integration::SceneHolder::WheelEventSignalType& SceneHolder::WheelEventSig
   return mScene.WheelEventSignal();
 }
 
+Dali::Integration::SceneHolder::WheelEventGeneratedSignalType& SceneHolder::WheelEventGeneratedSignal()
+{
+  return mScene.WheelEventGeneratedSignal();
+}
+
 Integration::Scene SceneHolder::GetScene()
 {
   return mScene;
@@ -235,6 +240,11 @@ SceneHolder::WheelEventSignalType& SceneHolder::WheelEventSignal()
   return GetImplementation( *this ).WheelEventSignal();
 }
 
+SceneHolder::WheelEventGeneratedSignalType& SceneHolder::WheelEventGeneratedSignal()
+{
+  return GetImplementation( *this ).WheelEventGeneratedSignal();
+}
+
 } // Integration
 
 } // Dali
index b8cc1bc..9fc2763 100644 (file)
@@ -272,6 +272,11 @@ WheelEventSignalType& WheelEventSignal( Window window )
   return GetImplementation( window ).WheelEventSignal();
 }
 
+WheelEventGeneratedSignalType& WheelEventGeneratedSignal( Window window )
+{
+  return GetImplementation( window ).WheelEventGeneratedSignal();
+}
+
 VisibilityChangedSignalType& VisibilityChangedSignal( Window window )
 {
   return GetImplementation( window ).mVisibilityChangedSignal;
index d102f6a..0d4e219 100644 (file)
@@ -95,6 +95,7 @@ namespace DevelWindow
 typedef Signal< void () > EventProcessingFinishedSignalType;
 typedef Signal< bool (const KeyEvent&) > KeyEventGeneratedSignalType;
 typedef Signal< void (const WheelEvent&) > WheelEventSignalType;
+typedef Signal< bool (const WheelEvent&) > WheelEventGeneratedSignalType;
 typedef Signal< void ( Window, bool ) > VisibilityChangedSignalType;
 
 Dali::Window Get( Actor actor );
@@ -107,6 +108,7 @@ void AddFramePresentedCallback( Window window, std::unique_ptr< CallbackBase > c
 EventProcessingFinishedSignalType& EventProcessingFinishedSignal( Window window );
 KeyEventGeneratedSignalType& KeyEventGeneratedSignal( Dali::Window window );
 WheelEventSignalType& WheelEventSignal( Window window );
+WheelEventGeneratedSignalType& WheelEventGeneratedSignal( Dali::Window window );
 VisibilityChangedSignalType& VisibilityChangedSignal( Window window );
 }
 
index 6d0e8af..4780331 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/integration-api/events/key-event-integ.h>
 #include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali-toolkit/devel-api/focus-manager/keyboard-focus-manager-devel.h>
@@ -247,6 +248,34 @@ public:
   bool mIsCalled;
 };
 
+class WheelEventCallback : public Dali::ConnectionTracker
+{
+public:
+  /**
+   * Constructor
+   * @param[in]  returnValue  Set return value of WheelEvent callback.
+   * */
+  WheelEventCallback( bool consumed )
+  : mConsumed( consumed ),
+    mIsCalled( false )
+  {
+  }
+
+  bool Callback( Actor actor, const WheelEvent& wheelEvent )
+  {
+    mIsCalled = true;
+    return mConsumed;
+  }
+
+  void Callback( const WheelEvent& wheelEvent )
+  {
+    mIsCalled = true;
+  }
+
+  bool mConsumed;
+  bool mIsCalled;
+};
+
 // Used to connect to signals via the ConnectSignal Handle method
 struct CallbackFunctor
 {
@@ -2036,4 +2065,46 @@ int UtcDaliKeyboardFocusManagerWithKeyboardFocusableChildren(void)
   DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second);
 
   END_TEST;
+}
+
+int UtcDaliKeyboardFocusManagerCheckWheelEvent(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline( "UtcDaliKeyboardFocusManagerCheckWheelEvent" );
+  Dali::Integration::Scene scene = application.GetScene();
+
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  DALI_TEST_CHECK( ! manager.GetCurrentFocusActor() );
+
+  // Create the first actor and add it to the stage
+  Actor parent = Actor::New();
+  parent.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
+
+  Actor child = Actor::New();
+  child.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
+
+  parent.Add(child);
+  scene.Add(parent);
+
+  WheelEventCallback childCallback( false );
+  child.WheelEventSignal().Connect( &childCallback, &WheelEventCallback::Callback );
+
+  WheelEventCallback parentCallback( true );
+  parent.WheelEventSignal().Connect( &parentCallback, &WheelEventCallback::Callback );
+
+  WheelEventCallback sceneCallback( false );
+  scene.WheelEventSignal().Connect( &sceneCallback, &WheelEventCallback::Callback );
+
+  manager.SetCurrentFocusActor( child );
+
+  // Emit custom wheel event is comming to KeyboardFocusManager
+  Integration::WheelEvent event(Integration::WheelEvent::CUSTOM_WHEEL, 0, 0u, Vector2(0.0f, 0.0f), 1, 1000u);
+  application.ProcessEvent(event);
+
+  DALI_TEST_CHECK( childCallback.mIsCalled );
+  DALI_TEST_CHECK( parentCallback.mIsCalled );
+  DALI_TEST_CHECK( !sceneCallback.mIsCalled );
+
+  END_TEST;
 }
\ No newline at end of file
index cc80372..4afb39a 100644 (file)
@@ -145,6 +145,7 @@ void KeyboardFocusManager::OnAdaptorInit()
     {
       (*iter).KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
       (*iter).TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouch);
+      (*iter).WheelEventGeneratedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWheelEvent);
       Dali::Window window = DevelWindow::DownCast(*iter);
       if(window)
       {
@@ -161,6 +162,7 @@ void KeyboardFocusManager::OnSceneHolderCreated(Dali::Integration::SceneHolder&
 {
   sceneHolder.KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
   sceneHolder.TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouch);
+  sceneHolder.WheelEventGeneratedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWheelEvent);
   Dali::Window window = DevelWindow::DownCast(sceneHolder);
   if(window)
   {
@@ -1008,6 +1010,49 @@ void KeyboardFocusManager::OnTouch(const TouchEvent& touch)
   }
 }
 
+bool KeyboardFocusManager::OnWheelEvent(const WheelEvent& event)
+{
+  bool consumed = false;
+  Actor actor = GetCurrentFocusActor();
+  if(actor)
+  {
+    // Notify the actor about the wheel event
+    consumed = EmitWheelSignals(actor, event);
+  }
+  return consumed;
+}
+
+bool KeyboardFocusManager::EmitWheelSignals(Actor actor, const WheelEvent& event)
+{
+  bool consumed = false;
+
+  if(actor)
+  {
+    Dali::Actor oldParent(actor.GetParent());
+
+    // Only do the conversion and emit the signal if the actor's wheel signal has connections.
+    if(!actor.WheelEventSignal().Empty())
+    {
+      // Emit the signal to the parent
+      consumed = actor.WheelEventSignal().Emit(actor, event);
+    }
+    // if actor doesn't consume WheelEvent, give WheelEvent to its parent.
+    if(!consumed)
+    {
+      // The actor may have been removed/reparented during the signal callbacks.
+      Dali::Actor parent = actor.GetParent();
+
+      if(parent &&
+         (parent == oldParent))
+      {
+        consumed = EmitWheelSignals(parent, event);
+      }
+    }
+  }
+
+  return consumed;
+}
+
 void KeyboardFocusManager::OnWindowFocusChanged(Window window, bool focusIn)
 {
   if(focusIn && mCurrentFocusedWindow.GetHandle() != window.GetRootLayer())
index 8212a79..783e3f5 100644 (file)
@@ -292,6 +292,12 @@ private:
   void OnTouch(const TouchEvent& touch);
 
   /**
+   * Callback for the wheel event when the custom wheel event occurs.
+   * @param[in] wheel The WheelEvent information
+   */
+  bool OnWheelEvent(const WheelEvent& wheel);
+
+  /**
    * Called when the window focus is changed.
    * @param[in] window The window whose focus is changed
    * @param[in] focusIn Whether the focus is in/out
@@ -303,6 +309,14 @@ private:
    */
   Actor GetFocusActorFromCurrentWindow();
 
+  /**
+   * Recursively deliver events to the control and its parents, until the event is consumed or the stage is reached.
+   * @param[in]  actor  The actor got WheelEvent.
+   * @param[in]  event  The WheelEvent.
+   * @return True if WheelEvent is consumed.
+   */
+  bool EmitWheelSignals(Actor actor, const WheelEvent& event);
+
 private:
   // Undefined
   KeyboardFocusManager(const KeyboardFocusManager&);