2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "keyinput-focus-manager-impl.h"
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/integration-api/adaptor-framework/adaptor.h>
24 #include <dali/integration-api/adaptor-framework/scene-holder.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/devel-api/adaptor-framework/window-devel.h>
27 #include <dali/public-api/actors/layer.h>
28 #include <cstring> // for strcmp
31 #include <dali-toolkit/devel-api/controls/control-devel.h>
42 const char* const SIGNAL_KEY_INPUT_FOCUS_CHANGED = "keyInputFocusChanged";
46 KeyInputFocusManager::KeyInputFocusManager()
47 : mSlotDelegate(this),
48 mCurrentFocusControl(),
51 // Retrieve all the existing widnows
52 Dali::SceneHolderList sceneHolders = Adaptor::Get().GetSceneHolders();
53 for(auto iter = sceneHolders.begin(); iter != sceneHolders.end(); ++iter)
55 (*iter).KeyEventGeneratedSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnKeyEvent);
58 // Get notified when any new scene holder is created afterwards
59 Adaptor::Get().WindowCreatedSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnSceneHolderCreated);
62 KeyInputFocusManager::~KeyInputFocusManager()
66 void KeyInputFocusManager::OnSceneHolderCreated(Dali::Integration::SceneHolder& sceneHolder)
68 sceneHolder.KeyEventGeneratedSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnKeyEvent);
71 void KeyInputFocusManager::SetFocus(Toolkit::Control control)
79 if(control == mCurrentFocusControl)
81 // Control already has focus
85 control.OffSceneSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnFocusControlSceneDisconnection);
87 Dali::Toolkit::Control previousFocusControl = GetCurrentFocusControl();
89 // Set control to currentFocusControl
90 mCurrentFocusControl = control;
91 mCurrentWindowId = static_cast<uint32_t>(Integration::SceneHolder::Get(control).GetNativeId());
93 if(previousFocusControl)
95 // Notify the control that it has lost key input focus
96 GetImplementation(previousFocusControl).OnKeyInputFocusLost();
99 // Tell the new actor that it has gained focus.
100 GetImplementation(control).OnKeyInputFocusGained();
102 // Emit the signal to inform focus change to the application.
103 if(!mKeyInputFocusChangedSignal.Empty())
105 mKeyInputFocusChangedSignal.Emit(control, previousFocusControl);
109 void KeyInputFocusManager::RemoveFocus(Toolkit::Control control)
111 if(control && control == mCurrentFocusControl)
113 DALI_LOG_RELEASE_INFO("RemoveFocus id:(%d)\n", control.GetProperty<int32_t>(Dali::Actor::Property::ID));
114 control.OffSceneSignal().Disconnect(mSlotDelegate, &KeyInputFocusManager::OnFocusControlSceneDisconnection);
116 mCurrentFocusControl.Reset();
117 mCurrentWindowId = 0;
119 // Notify the control that it has lost key input focus
120 GetImplementation(control).OnKeyInputFocusLost();
124 Toolkit::Control KeyInputFocusManager::GetCurrentFocusControl() const
126 return mCurrentFocusControl;
129 uint32_t KeyInputFocusManager::GetCurrentWindowId() const
131 return mCurrentWindowId;
134 Toolkit::KeyInputFocusManager::KeyInputFocusChangedSignalType& KeyInputFocusManager::KeyInputFocusChangedSignal()
136 return mKeyInputFocusChangedSignal;
139 bool KeyInputFocusManager::OnKeyEvent(const KeyEvent& event)
141 bool consumed = false;
143 Toolkit::Control control = GetCurrentFocusControl();
146 // Key events that occur in windows other than the currently focused control are skipped.
147 uint32_t eventWindowId = event.GetWindowId();
148 if(eventWindowId > 0 && GetCurrentWindowId() != eventWindowId)
150 DALI_LOG_RELEASE_INFO("Current control window id %d, window ID where key event occurred %d : key event skip\n", GetCurrentWindowId(), eventWindowId);
154 Dali::Actor dispatch = control;
157 // If the DISPATCH_KEY_EVENTS is false, it cannot emit key event.
158 Toolkit::Control dispatchControl = Toolkit::Control::DownCast(dispatch);
159 if(dispatchControl && !dispatchControl.GetProperty<bool>(Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS))
163 dispatch = dispatch.GetParent();
166 // Notify the control about the key event
167 consumed = EmitKeyEventSignal(control, event);
173 bool KeyInputFocusManager::EmitKeyEventSignal(Toolkit::Control control, const KeyEvent& event)
175 bool consumed = false;
179 consumed = GetImplementation(control).EmitKeyEventSignal(event);
181 // if control doesn't consume KeyEvent, give KeyEvent to its parent.
184 Toolkit::Control parent = Toolkit::Control::DownCast(control.GetParent());
188 consumed = EmitKeyEventSignal(parent, event);
196 void KeyInputFocusManager::OnFocusControlSceneDisconnection(Dali::Actor actor)
198 RemoveFocus(Dali::Toolkit::Control::DownCast(actor));
201 bool KeyInputFocusManager::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
203 bool connected(true);
204 KeyInputFocusManager* manager = dynamic_cast<KeyInputFocusManager*>(object);
208 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_CHANGED))
210 manager->KeyInputFocusChangedSignal().Connect(tracker, functor);
214 // signalName does not match any signal
222 } // namespace Internal
224 } // namespace Toolkit