[dali_2.3.42] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyboard-focus-manager-impl.cpp
index f5d8d03..b9abe8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -130,7 +130,8 @@ KeyboardFocusManager::KeyboardFocusManager()
   mFocusGroupLoopEnabled(false),
   mIsWaitingKeyboardFocusChangeCommit(false),
   mClearFocusOnTouch(true),
-  mEnableDefaultAlgorithm(false)
+  mEnableDefaultAlgorithm(false),
+  mCurrentWindowId(0)
 {
   // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown.
 
@@ -183,8 +184,7 @@ void KeyboardFocusManager::GetConfigurationFromStyleManger()
   Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
   if(styleManager)
   {
-    const Property::Map& config               = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-    const auto           alwaysShowFocusValue = config.Find("alwaysShowFocus", Property::Type::BOOLEAN);
+    const auto alwaysShowFocusValue = Toolkit::DevelStyleManager::GetConfigurations(styleManager).Find("alwaysShowFocus", Property::Type::BOOLEAN);
 
     mAlwaysShowIndicator   = (alwaysShowFocusValue && alwaysShowFocusValue->Get<bool>()) ? ALWAYS_SHOW : NONE;
     mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE;
@@ -206,13 +206,16 @@ bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor)
 
 bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
 {
-  bool success = false;
+  bool                     success = false;
+  Integration::SceneHolder currentWindow;
 
   // Check whether the actor is in the stage and is keyboard focusable.
   if(actor &&
      actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) &&
      actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED) &&
-     actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+     actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) &&
+     (currentWindow = Integration::SceneHolder::Get(actor))) ///< Note : SceneHolder might not be valid even if actor is connected to scene.
+                                                             ///         (e.g. Adaptor Stopped, SceneHolder removed but Scene is still alive)
   {
     // If the parent's KEYBOARD_FOCUSABLE_CHILDREN is false, it cannot have focus.
     Actor parent = actor.GetParent();
@@ -234,11 +237,11 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
       return true;
     }
 
-    Integration::SceneHolder currentWindow = Integration::SceneHolder::Get(actor);
     if(currentWindow.GetRootLayer() != mCurrentFocusedWindow.GetHandle())
     {
       Layer rootLayer       = currentWindow.GetRootLayer();
       mCurrentFocusedWindow = rootLayer;
+      mCurrentWindowId      = static_cast<uint32_t>(currentWindow.GetNativeId());
     }
 
     if((mIsFocusIndicatorShown == SHOW) && (mEnableFocusIndicator == ENABLE))
@@ -246,6 +249,8 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
       actor.Add(GetFocusIndicatorActor());
     }
 
+    actor.OffSceneSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnSceneDisconnection);
+
     // Save the current focused actor
     mCurrentFocusActor = actor;
 
@@ -675,12 +680,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())
     {
@@ -697,9 +702,8 @@ void KeyboardFocusManager::ClearFocus()
   mCurrentFocusActor.Reset();
 }
 
-void KeyboardFocusManager::ClearFocusIndicator()
+void KeyboardFocusManager::ClearFocusIndicator(Actor actor)
 {
-  Actor actor = GetCurrentFocusActor();
   if(actor)
   {
     if(mFocusIndicatorActor)
@@ -710,6 +714,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;
@@ -799,8 +810,24 @@ Actor KeyboardFocusManager::GetFocusIndicatorActor()
   return mFocusIndicatorActor;
 }
 
+uint32_t KeyboardFocusManager::GetCurrentWindowId() const
+{
+  return mCurrentWindowId;
+}
+
 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 {
+  if(mCurrentFocusedWindow.GetHandle())
+  {
+    // If it is a key event that occurred in another window, it returns.
+    uint32_t eventWindowId = event.GetWindowId();
+    if(eventWindowId > 0 && GetCurrentWindowId() != eventWindowId)
+    {
+      DALI_LOG_RELEASE_INFO("CurrentFocusedWindow id %d, window ID where key event occurred %d : key event skip\n", GetCurrentWindowId(), eventWindowId);
+      return;
+    }
+  }
+
   const std::string& keyName    = event.GetKeyName();
   const std::string& deviceName = event.GetDeviceName();
 
@@ -1017,7 +1044,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
@@ -1088,6 +1115,7 @@ void KeyboardFocusManager::OnWindowFocusChanged(Window window, bool focusIn)
     // Change Current Focused Window
     Layer rootLayer       = window.GetRootLayer();
     mCurrentFocusedWindow = rootLayer;
+    mCurrentWindowId      = static_cast<uint32_t>(Integration::SceneHolder::Get(rootLayer).GetNativeId());
 
     // Get Current Focused Actor from window
     Actor currentFocusedActor = GetFocusActorFromCurrentWindow();
@@ -1197,6 +1225,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