Revert "Fix GetHeightForWidth for text controller"
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyinput-focus-manager-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "keyinput-focus-manager-impl.h"
20
21 // EXTERNAL INCLUDES
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/public-api/actors/layer.h>
27 #include <cstring> // for strcmp
28
29 // INTERNAL INCLUDES
30 #include <dali-toolkit/devel-api/controls/control-devel.h>
31
32 namespace Dali
33 {
34 namespace Toolkit
35 {
36 namespace Internal
37 {
38 namespace
39 {
40 // Signals
41
42 const char* const SIGNAL_KEY_INPUT_FOCUS_CHANGED = "keyInputFocusChanged";
43
44 } // namespace
45
46 KeyInputFocusManager::KeyInputFocusManager()
47 : mSlotDelegate(this),
48   mCurrentFocusControl()
49 {
50   // Retrieve all the existing widnows
51   Dali::SceneHolderList sceneHolders = Adaptor::Get().GetSceneHolders();
52   for(auto iter = sceneHolders.begin(); iter != sceneHolders.end(); ++iter)
53   {
54     (*iter).KeyEventGeneratedSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnKeyEvent);
55   }
56
57   // Get notified when any new scene holder is created afterwards
58   Adaptor::Get().WindowCreatedSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnSceneHolderCreated);
59 }
60
61 KeyInputFocusManager::~KeyInputFocusManager()
62 {
63 }
64
65 void KeyInputFocusManager::OnSceneHolderCreated(Dali::Integration::SceneHolder& sceneHolder)
66 {
67   sceneHolder.KeyEventGeneratedSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnKeyEvent);
68 }
69
70 void KeyInputFocusManager::SetFocus(Toolkit::Control control)
71 {
72   if(!control)
73   {
74     // No-op
75     return;
76   }
77
78   if(control == mCurrentFocusControl)
79   {
80     // Control already has focus
81     return;
82   }
83
84   control.OffSceneSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnFocusControlSceneDisconnection);
85
86   Dali::Toolkit::Control previousFocusControl = GetCurrentFocusControl();
87
88   // Set control to currentFocusControl
89   mCurrentFocusControl = control;
90
91   if(previousFocusControl)
92   {
93     // Notify the control that it has lost key input focus
94     GetImplementation(previousFocusControl).OnKeyInputFocusLost();
95   }
96
97   // Tell the new actor that it has gained focus.
98   GetImplementation(control).OnKeyInputFocusGained();
99
100   // Emit the signal to inform focus change to the application.
101   if(!mKeyInputFocusChangedSignal.Empty())
102   {
103     mKeyInputFocusChangedSignal.Emit(control, previousFocusControl);
104   }
105 }
106
107 void KeyInputFocusManager::RemoveFocus(Toolkit::Control control)
108 {
109   if(control == mCurrentFocusControl)
110   {
111     control.OffSceneSignal().Disconnect(mSlotDelegate, &KeyInputFocusManager::OnFocusControlSceneDisconnection);
112
113     mCurrentFocusControl.Reset();
114
115     // Notify the control that it has lost key input focus
116     GetImplementation(control).OnKeyInputFocusLost();
117   }
118 }
119
120 Toolkit::Control KeyInputFocusManager::GetCurrentFocusControl() const
121 {
122   return mCurrentFocusControl;
123 }
124
125 Toolkit::KeyInputFocusManager::KeyInputFocusChangedSignalType& KeyInputFocusManager::KeyInputFocusChangedSignal()
126 {
127   return mKeyInputFocusChangedSignal;
128 }
129
130 bool KeyInputFocusManager::OnKeyEvent(const KeyEvent& event)
131 {
132   bool consumed = false;
133
134   Toolkit::Control control = GetCurrentFocusControl();
135   if(control)
136   {
137     Dali::Actor dispatch = control;
138     while(dispatch)
139     {
140       // If the DISPATCH_KEY_EVENTS is false, it cannot emit key event.
141       Toolkit::Control dispatchControl = Toolkit::Control::DownCast(dispatch);
142       if(dispatchControl && !dispatchControl.GetProperty<bool>(Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS))
143       {
144         return true;
145       }
146       dispatch = dispatch.GetParent();
147     }
148
149     // Notify the control about the key event
150     consumed = EmitKeyEventSignal(control, event);
151   }
152
153   return consumed;
154 }
155
156 bool KeyInputFocusManager::EmitKeyEventSignal(Toolkit::Control control, const KeyEvent& event)
157 {
158   bool consumed = false;
159
160   if(control)
161   {
162     consumed = GetImplementation(control).EmitKeyEventSignal(event);
163
164     // if control doesn't consume KeyEvent, give KeyEvent to its parent.
165     if(!consumed)
166     {
167       Toolkit::Control parent = Toolkit::Control::DownCast(control.GetParent());
168
169       if(parent)
170       {
171         consumed = EmitKeyEventSignal(parent, event);
172       }
173     }
174   }
175
176   return consumed;
177 }
178
179 void KeyInputFocusManager::OnFocusControlSceneDisconnection(Dali::Actor actor)
180 {
181   RemoveFocus(Dali::Toolkit::Control::DownCast(actor));
182 }
183
184 bool KeyInputFocusManager::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
185 {
186   bool                  connected(true);
187   KeyInputFocusManager* manager = dynamic_cast<KeyInputFocusManager*>(object);
188
189   if(manager)
190   {
191     if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_CHANGED))
192     {
193       manager->KeyInputFocusChangedSignal().Connect(tracker, functor);
194     }
195     else
196     {
197       // signalName does not match any signal
198       connected = false;
199     }
200   }
201
202   return connected;
203 }
204
205 } // namespace Internal
206
207 } // namespace Toolkit
208
209 } // namespace Dali