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