[Tizen] If the actor had focus when it was off scene, the focus is cleared. 58/314958/1
authorjoogab.yun <joogab.yun@samsung.com>
Wed, 17 Jul 2024 05:21:13 +0000 (14:21 +0900)
committerjoogab.yun <joogab.yun@samsung.com>
Wed, 24 Jul 2024 00:34:38 +0000 (09:34 +0900)
When the actor is off scene, the focus is not cleared.
So, when app re-add the actor and SetCurrentFocusActor, app do not receiving the FocusGained event.

Change-Id: Ic427362db70e77d482a458e4921ba5bcc7860632

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 4d0d54e..216b419 100644 (file)
@@ -473,11 +473,13 @@ int UtcDaliKeyboardFocusManagerMoveFocus(void)
   tableView.AddChild(third, TableView::CellPosition(1, 0));
   tableView.AddChild(fourth, TableView::CellPosition(1, 1));
 
+  focusChangedCallback.Reset();
+
   // 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 == second);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor());
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == first);
   focusChangedCallback.Reset();
 
@@ -1435,11 +1437,13 @@ int UtcDaliKeyboardFocusManagerMoveFocusTestStateChange(void)
   tableView.AddChild(third, TableView::CellPosition(1, 0));
   tableView.AddChild(fourth, TableView::CellPosition(1, 1));
 
+  focusChangedCallback.Reset();
+
   // 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 == second);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor());
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == first);
 
   DALI_TEST_EQUALS(first.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
@@ -2455,4 +2459,57 @@ int UtcDaliKeyboardFocusManagerKeyEventOtherWindow(void)
   DALI_TEST_CHECK(manager.GetCurrentFocusActor() == button1);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliKeyboardFocusManagerRemoveScene(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline(" UtcDaliKeyboardFocusManagerRemoveScene");
+
+  // Register Type
+  TypeInfo type;
+  type = TypeRegistry::Get().GetTypeInfo("KeyboardFocusManager");
+  DALI_TEST_CHECK(type);
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK(handle);
+
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  DALI_TEST_CHECK(manager);
+
+  bool                 focusChangedSignalVerified = false;
+  FocusChangedCallback focusChangedCallback(focusChangedSignalVerified);
+  manager.FocusChangedSignal().Connect(&focusChangedCallback, &FocusChangedCallback::Callback);
+
+  // Create the first actor and add it to the stage
+  Actor first = Actor::New();
+  first.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
+  application.GetScene().Add(first);
+
+  // Check that the focus is set on 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();
+
+  // Remove actor from scene
+  application.GetScene().Remove(first);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == first);
+  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == Actor());
+  focusChangedCallback.Reset();
+
+  // Add actor to scene
+  application.GetScene().Add(first);
+  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();
+
+  END_TEST;
+}
index e8a990f..b3d7f48 100644 (file)
@@ -247,6 +247,8 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
       actor.Add(GetFocusIndicatorActor());
     }
 
+    actor.OffSceneSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnSceneDisconnection);
+
     // Save the current focused actor
     mCurrentFocusActor = actor;
 
@@ -676,13 +678,12 @@ void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
   }
 }
 
-void KeyboardFocusManager::ClearFocus()
+void KeyboardFocusManager::ClearFocus(Actor actor)
 {
-  ClearFocusIndicator();
-  Actor actor = GetCurrentFocusActor();
   if(actor)
   {
     DALI_LOG_RELEASE_INFO("ClearFocus id:(%d)\n",  actor.GetProperty<int32_t>(Dali::Actor::Property::ID));
+    actor.OffSceneSignal().Disconnect(mSlotDelegate, &KeyboardFocusManager::OnSceneDisconnection);
     // Send notification for the change of focus actor
     if(!mFocusChangedSignal.Empty())
     {
@@ -699,9 +700,8 @@ void KeyboardFocusManager::ClearFocus()
   mCurrentFocusActor.Reset();
 }
 
-void KeyboardFocusManager::ClearFocusIndicator()
+void KeyboardFocusManager::ClearFocusIndicator(Actor actor)
 {
-  Actor actor = GetCurrentFocusActor();
   if(actor)
   {
     if(mFocusIndicatorActor)
@@ -712,6 +712,13 @@ void KeyboardFocusManager::ClearFocusIndicator()
   mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE;
 }
 
+void KeyboardFocusManager::ClearFocus()
+{
+  Actor actor = GetCurrentFocusActor();
+  ClearFocusIndicator(actor);
+  ClearFocus(actor);
+}
+
 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
 {
   mFocusGroupLoopEnabled = enabled;
@@ -1035,7 +1042,7 @@ void KeyboardFocusManager::OnTouch(const TouchEvent& touch)
     // If mClearFocusOnTouch is false, do not clear the focus indicator even if user touch the screen.
     if(mClearFocusOnTouch)
     {
-      ClearFocusIndicator();
+      ClearFocusIndicator(GetCurrentFocusActor());
     }
 
     // If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor
@@ -1216,6 +1223,16 @@ void KeyboardFocusManager::ResetFocusFinderRootActor()
   mFocusFinderRootActor.Reset();
 }
 
+void KeyboardFocusManager::OnSceneDisconnection(Dali::Actor actor)
+{
+  if(actor && actor == mCurrentFocusActor.GetHandle())
+  {
+    DALI_LOG_RELEASE_INFO("ClearFocus due to actor id:(%d) removed from scene\n", actor.GetProperty<int32_t>(Dali::Actor::Property::ID));
+    ClearFocusIndicator(actor);
+    ClearFocus(actor);
+  }
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 87e73f8..1d708d2 100644 (file)
@@ -333,16 +333,29 @@ private:
    */
   bool EmitCustomWheelSignals(Actor actor, const WheelEvent& event);
 
+   /**
+   * Clear the focus actor
+   * @param[in] actor Actor to be cleared of focus
+   */
+  void ClearFocus(Actor actor);
+
   /**
    * Clear the focus indicator actor.
+   * @param[in] actor Actor to be cleared of focus indicator.
    */
-  void ClearFocusIndicator();
+  void ClearFocusIndicator(Actor actor);
 
   /**
    * Gets the current native window id
    */
   uint32_t GetCurrentWindowId() const;
 
+  /**
+   * Signal handler called when a focused actor is removed from Scene.
+   * @param[in] actor The actor removed from the scene.
+   */
+  void OnSceneDisconnection(Dali::Actor actor);
+
 private:
   // Undefined
   KeyboardFocusManager(const KeyboardFocusManager&);