[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 fb67a4b6ab540520d8692530d6c18a600f490498..8075dbee7b7ea52f1a1e764a21ee647851c12dfb 100644 (file)
@@ -119,6 +119,8 @@ public:
 
   Dali::Integration::SceneHolder::WheelEventSignalType& WheelEventSignal();
 
+  Dali::Integration::SceneHolder::WheelEventGeneratedSignalType& WheelEventGeneratedSignal();
+
   Integration::Scene GetScene();
 
   Dali::RenderSurfaceInterface& GetRenderSurface();
index e18809a1554f771834595749104fb010b4ca0258..8bcb3c07b161d45bd42fca603120df622c8f1ecc 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 b8cc1bcbcd17bc58be183cdcdec734fc95acaf7f..9fc2763f64ab7896dffa79825a4f8b72966e5f86 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 d102f6a22d5c65a6463d1cfbacd085a47663644b..0d4e219eb076a05045b06dc60be0ebeb2b93b502 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 6d0e8af630bfa91f0df7fb4de28c087ecc10580f..4780331339be6d0577334c5ccca33d4a71ecab0e 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
 {
@@ -2035,5 +2064,47 @@ int UtcDaliKeyboardFocusManagerWithKeyboardFocusableChildren(void)
   DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == true);
   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 cc80372dc23c7a2f43fbd2f227ce9b1d8af42905..4afb39a01a6ade2f8d0d90798c9e59b1e54066b6 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 8212a79913dd86cfcca06547ff3d9758cf805dce..783e3f56c539d3db5c8dc6b11ca9d8fbd1d98372 100644 (file)
@@ -291,6 +291,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
@@ -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&);