Conversion to Apache 2.0 license
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / focus-manager / keyinput-focus-manager-impl.cpp
1 /*
2  * Copyright (c) 2014 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 // INTERNAL INCLUDES
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/integration-api/debug.h>
24
25 namespace Dali
26 {
27
28 namespace Toolkit
29 {
30
31 namespace Internal
32 {
33
34 KeyInputFocusManager::KeyInputFocusManager()
35 : mSlotDelegate( this )
36 {
37   Stage::GetCurrent().KeyEventSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnKeyEvent);
38 }
39
40 KeyInputFocusManager::~KeyInputFocusManager()
41 {
42 }
43
44 void KeyInputFocusManager::SetFocus(Toolkit::Control control)
45 {
46   if(!control)
47   {
48    //No-op
49     return;
50   }
51
52   unsigned int actorID = control.GetId();
53
54   ActorQueueIterator pos = std::find( mFocusActorsQueue.begin(), mFocusActorsQueue.end(), actorID);
55
56   if((!mFocusActorsQueue.empty()) && (pos == mFocusActorsQueue.begin()))
57   {
58     //Actor allready in front, so No-op
59     return;
60   }
61
62   if(pos != mFocusActorsQueue.end())
63   {
64     //A previously focused actor wants to regain focus
65     mFocusActorsQueue.erase(pos);
66   }
67   else
68   {
69     control.OffStageSignal().Connect( mSlotDelegate, &KeyInputFocusManager::OnFocusActorStageDisconnection );
70   }
71
72   Dali::Toolkit::Control previousFocusControl;
73   if(!mFocusActorsQueue.empty())
74   {
75     previousFocusControl = Dali::Toolkit::Control::DownCast(Stage::GetCurrent().GetRootLayer().FindChildById(mFocusActorsQueue.front()));
76     if(previousFocusControl)
77     {
78       // Notify the control that it has lost key input focus
79       previousFocusControl.GetImplementation().OnKeyInputFocusLost();
80     }
81   }
82
83   mFocusActorsQueue.push_front(actorID);
84
85   // Tell the new actor that it has gained focus.
86   control.GetImplementation().OnKeyInputFocusGained();
87
88   // Emit the signal to inform focus change to the application.
89   if ( !mKeyInputFocusChangedSignalV2.Empty() )
90   {
91     mKeyInputFocusChangedSignalV2.Emit( control, previousFocusControl );
92   }
93 }
94
95 Toolkit::Control KeyInputFocusManager::GetCurrentFocusControl() const
96 {
97   Toolkit::Control currentFocusControl;
98
99   if(!mFocusActorsQueue.empty())
100   {
101     currentFocusControl = Dali::Toolkit::Control::DownCast(Stage::GetCurrent().GetRootLayer().FindChildById(mFocusActorsQueue.front()));
102   }
103
104   return currentFocusControl;
105 }
106
107 void KeyInputFocusManager::RemoveFocus(Toolkit::Control control)
108 {
109   if(control)
110   {
111     unsigned int actorId = control.GetId();
112     ActorQueueIterator pos = std::find( mFocusActorsQueue.begin(), mFocusActorsQueue.end(), actorId);
113
114     if(pos != mFocusActorsQueue.end())
115     {
116       control.OffStageSignal().Disconnect( mSlotDelegate, &KeyInputFocusManager::OnFocusActorStageDisconnection );
117
118       // Notify the control that it has lost key input focus
119       control.GetImplementation().OnKeyInputFocusLost();
120
121       if(pos == mFocusActorsQueue.begin())
122       {
123         Actor previousFocusActor;
124
125         mFocusActorsQueue.erase(pos);
126         if(!mFocusActorsQueue.empty())
127         {
128           previousFocusActor = Stage::GetCurrent().GetRootLayer().FindChildById(mFocusActorsQueue.front());
129         }
130
131         Dali::Toolkit::Control previouscontrol = Dali::Toolkit::Control::DownCast(previousFocusActor);
132         if(previouscontrol)
133         {
134           // Tell the new actor that it has gained focus.
135           previouscontrol.GetImplementation().OnKeyInputFocusGained();
136         }
137       }
138       else
139       {
140         //If the removed actor is not currently focused, then no need to emit signal.
141         mFocusActorsQueue.erase(pos);
142       }
143
144     }
145   }
146 }
147
148 bool KeyInputFocusManager::IsKeyboardListener(Toolkit::Control control) const
149 {
150   bool result = false;
151
152   if(!mFocusActorsQueue.empty())
153   {
154     unsigned int actorId = control.GetId();
155     ActorQueueConstIterator pos = std::find(mFocusActorsQueue.begin(), mFocusActorsQueue.end(), actorId);
156
157     if(pos != mFocusActorsQueue.end())
158     {
159       result = true;
160     }
161   }
162
163   return result;
164 }
165
166 Toolkit::KeyInputFocusManager::KeyInputFocusChangedSignalV2& KeyInputFocusManager::KeyInputFocusChangedSignal()
167 {
168   return mKeyInputFocusChangedSignalV2;
169 }
170
171 Toolkit::KeyInputFocusManager::UnhandledKeyEventSignalV2& KeyInputFocusManager::UnhandledKeyEventSignal()
172 {
173   return mUnhandledKeyEventSignalV2;
174 }
175
176 void KeyInputFocusManager::OnKeyEvent(const KeyEvent& event)
177 {
178   bool consumed = false;
179
180   ActorQueueIterator iter = mFocusActorsQueue.begin();
181
182   Layer rootLayer = Stage::GetCurrent().GetRootLayer();
183
184   while(!mFocusActorsQueue.empty() && !consumed && (iter != mFocusActorsQueue.end()))
185   {
186     Actor actor = rootLayer.FindChildById(*iter);
187     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
188     if(control)
189     {
190       // Notify the control about the key event
191       consumed = control.GetImplementation().EmitKeyEventSignal(event);
192     }
193     iter++;
194   }
195
196   if(!consumed)
197   {
198     // Emit signal to inform that a key event is not consumed.
199     if( !mUnhandledKeyEventSignalV2.Empty() )
200     {
201       mUnhandledKeyEventSignalV2.Emit(event);
202     }
203   }
204 }
205
206 void KeyInputFocusManager::OnFocusActorStageDisconnection( Dali::Actor actor )
207 {
208   RemoveFocus(Dali::Toolkit::Control::DownCast(actor));
209 }
210
211 bool KeyInputFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
212 {
213   Dali::BaseHandle handle( object );
214
215   bool connected( true );
216   KeyInputFocusManager* manager = dynamic_cast<KeyInputFocusManager*>(object);
217
218   if( Dali::Toolkit::KeyInputFocusManager::SIGNAL_KEY_INPUT_FOCUS_CHANGED == signalName )
219   {
220     manager->KeyInputFocusChangedSignal().Connect( tracker, functor );
221   }
222   else
223   {
224     // signalName does not match any signal
225     connected = false;
226   }
227
228   return connected;
229 }
230
231 } // namespace Internal
232
233 } // namespace Toolkit
234
235 } // namespace Dali