add patch
[framework/osp/uifw.git] / src / ui / FUi_FocusManagerImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18 * @file             FUi_FocusManagerImpl.cpp
19 * @brief                This is the implementation file for _FocusManagerImpl class.
20 * @version              2.0
21 *
22 */
23
24 #include <Ecore.h>
25 #include <unique_ptr.h>
26 #include "FUi_FocusManagerImpl.h"
27 #include "FUi_ControlImpl.h"
28 #include "FUi_WindowImpl.h"
29 #include "FUi_ControlManager.h"
30 #include "FUiCtrl_Form.h"
31 #include "FUi_UiEventManager.h"
32 #include "FUi_ResourceManager.h"
33 #include "FUi_UiKeyEvent.h"
34 #include "FUi_Window.h"
35 #include "FUiCtrl_Frame.h"
36
37 using namespace std;
38 using namespace Tizen::Base::Collection;
39 using namespace Tizen::Graphics;
40 using namespace Tizen::Ui;
41 using namespace Tizen::Ui::Controls;
42 using namespace Tizen::Ui::Animations;
43
44 namespace Tizen { namespace Ui
45 {
46 ////////////////////////////////////////////////////////////////////////////////
47 /// _FocusManagerImpl class Lifecycle
48 _FocusManagerImpl* _FocusManagerImpl::__pInstance = null;
49
50 _FocusManagerImpl::_FocusManagerImpl(void)
51         : __pCurrentFocusUiControl(null)
52         , __isFocusMode(false)
53         , __focusDirection(FOCUS_DIRECTION_DOWNWARD)
54 {
55 #ifdef _FOCUS_UI_
56         _UiEventManager* pUiEventManager = _UiEventManager::GetInstance();
57         if (pUiEventManager)
58         {
59                 result r = pUiEventManager->AddPostKeyEventListener(*this);
60                 SysTryReturnVoidResult(NID_UI,  r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
61
62                 r = pUiEventManager->AddTouchEventListener(*this);
63                 SysTryReturnVoidResult(NID_UI,  r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
64         }
65 #endif
66 }
67
68
69 _FocusManagerImpl::~_FocusManagerImpl(void)
70 {
71         // NOTHING
72 }
73
74 void
75 _FocusManagerImpl::Initialize(void)
76 {
77         static pthread_once_t once_block = PTHREAD_ONCE_INIT;
78
79         if (__pInstance == null)
80         {
81                 pthread_once(&once_block, InitializeInstance);
82         }
83 }
84
85 _FocusManagerImpl*
86 _FocusManagerImpl::GetInstance(void)
87 {
88         return __pInstance;
89 }
90
91 void
92 _FocusManagerImpl::InitializeInstance(void)
93 {
94         ClearLastResult();
95
96         if (__pInstance == null)
97         {
98                 __pInstance = new (std::nothrow) _FocusManagerImpl;
99                 SysTryReturnVoidResult(NID_UI, __pInstance != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
100         }
101 }
102
103 void
104 _FocusManagerImpl::ReleaseInstance(void)
105 {
106         if (__pInstance)
107         {
108                 delete __pInstance;
109                 __pInstance = null;
110         }
111 }
112
113 ////////////////////////////////////////////////////////////////////////////////
114 /// _FocusManagerImpl class Operation
115
116 _ControlImpl*
117 _FocusManagerImpl::GetCurrentFocusOwner(void) const
118 {
119         _Control* pFocus = _ControlManager::GetInstance()->GetFocusControl();
120         if(pFocus == null)
121         {
122                 return null;
123         }
124
125         _ControlImpl* pFocusImpl = static_cast <_ControlImpl*>(pFocus->GetUserData());
126         SysAssert(pFocusImpl);
127
128         return pFocusImpl;
129 }
130
131
132 _WindowImpl*
133 _FocusManagerImpl::GetCurrentFocusedWindow(void) const
134 {
135         _Control* pFocus = _ControlManager::GetInstance()->GetFocusControl();
136         if(pFocus == null)
137         {
138                 return null;
139         }
140         _Window* pWindow = pFocus->GetRootWindow();
141         SysAssert(pWindow);
142
143         _WindowImpl* pWindowImpl = static_cast <_WindowImpl*>(static_cast <_ControlImpl*>(pWindow->GetUserData()));
144         SysAssert(pWindowImpl);
145
146         return pWindowImpl;
147 }
148
149 bool
150 _FocusManagerImpl::IsFocusModeStateEnabled(void) const
151 {
152         return __isFocusMode;
153 }
154
155 int
156 _FocusManagerImpl::GetNextIndex(int currentIndex, FocusDirection focusDirection, const IListT<_Control*>* pFocusControlList) const
157 {
158         int nextIndex = currentIndex;
159         if (focusDirection == FOCUS_DIRECTION_DOWNWARD)
160         {
161                 ++nextIndex;
162                 if (nextIndex == pFocusControlList->GetCount())
163                 {
164                         nextIndex = 0;
165                 }
166         }
167         else
168         {
169                 --nextIndex;
170                 if (nextIndex  < 0)
171                 {
172                         nextIndex = pFocusControlList->GetCount() - 1;
173                 }
174         }
175         return nextIndex;
176
177
178 }
179
180 bool
181 _FocusManagerImpl::IsFocusable(_Control* pControl) const
182 {
183         bool isFocusalbe = pControl->IsFocusable();
184         bool enableState = pControl->IsEnabled();
185         bool visibleState = pControl->IsVisible();
186         bool isNavigatable = pControl->IsFocusNavigateEnabled();
187         if (enableState  && visibleState  && isFocusalbe && isNavigatable)
188         {
189                 return true;
190         }
191         return false;
192 }
193
194 _Control*
195 _FocusManagerImpl::FindTraversalControlFromChild(_Control* pControl)
196 {
197         IListT<_Control*>* pFocusControlList =  null;
198         bool findNextFocusControl = false;
199
200         _Window* pTop = pControl->GetRootWindow();
201         if (pTop)
202         {
203                 pFocusControlList = pTop->GetFocusList();
204         }
205
206         if (pFocusControlList)
207         {
208                 unique_ptr<IEnumeratorT<_Control*> > pEnum (pFocusControlList->GetEnumeratorN());
209
210                 while (pEnum->MoveNext() == E_SUCCESS)
211                 {
212                         _Control* pEnumeratorControl = null;
213                         pEnum->GetCurrent(pEnumeratorControl);
214
215                         //Find current focused control
216                         if (pControl == pEnumeratorControl)
217                         {
218                                 findNextFocusControl = true;
219                         }
220                 }
221         }
222
223         if (findNextFocusControl == false)
224         {
225                 _Control* pParent = pControl->GetParent();
226                 if (pParent)
227                 {
228                         return FindTraversalControlFromChild(pParent);
229                 }
230         }
231
232         return pControl;
233 }
234
235 bool
236 _FocusManagerImpl::IsFocusControlListControl(_Control* pControl) const
237 {
238         IListT<_Control*>* pFocusControlList =  null;
239
240         _Window* pTop = pControl->GetRootWindow();
241         if (pTop)
242         {
243                 pFocusControlList = pTop->GetFocusList();
244         }
245
246         if (pFocusControlList)
247         {
248                 unique_ptr<IEnumeratorT<_Control*> > pEnum (pFocusControlList->GetEnumeratorN());
249                 while (pEnum->MoveNext() == E_SUCCESS)
250                 {
251                         _Control* pEnumeratorControl = null;
252                         pEnum->GetCurrent(pEnumeratorControl);
253
254                         //Find current focused control
255                         if (pControl == pEnumeratorControl)
256                         {
257                                 return true;
258                         }
259                 }
260         }
261
262         return false;
263 }
264
265 void
266 _FocusManagerImpl::StartFocusTraversal(_Control* pControl, FocusDirection focusDirection)
267 {
268         _Control* pOriginalControl = pControl;
269         _Window* pTop = pControl->GetRootWindow();
270         if (pTop == null)
271         {
272                 return;
273         }
274         bool isWindowEnabled = pTop->IsEnabled();
275         if (!isWindowEnabled)
276         {
277                 return;
278         }
279         _Control* pFocusTraversalControl = pTop->GetFocusTraversalControl(pControl);
280         if (pFocusTraversalControl)
281         {
282                 pControl = pFocusTraversalControl;
283         }
284         else
285         {
286                 _Control* pTraversalControl = FindTraversalControlFromChild(pControl);
287                 pTop->SetFocusTraversalControl(pTraversalControl, true);
288         }
289
290
291         bool focusMode = pControl->IsFocusModeStateEnabled();
292         if (__isFocusMode == false)
293         {
294                 __isFocusMode = true;
295                 if (pOriginalControl)
296                 {
297                         pOriginalControl->OnFocusModeStateChanged();
298                 }
299         }
300
301         if (focusMode == false && pControl->IsFocused())
302         {
303                 if (IsFocusable(pControl))
304                 {
305                         if (IsFocusControlListControl(pControl))
306                         {
307                                 pTop->SetFocusTraversalControl(pControl, true);
308                         }
309                         pControl->DrawFocus();
310                         return;
311                 }
312         }
313
314         if (focusDirection == FOCUS_DIRECTION_DOWNWARD)
315         {
316                 _Control* pFocusControl =  pControl->GetNextFocus();
317                 if (pFocusControl)
318                 {
319                         pFocusControl->SetFocused();
320                         pFocusControl->DrawFocus();
321                         pTop->SetFocusTraversalControl(pFocusControl, true);
322                         return;
323                 }
324         }
325         else
326         {
327                 _Control* pFocusControl =  pControl->GetPreviousFocus();
328                 if (pFocusControl)
329                 {
330                         pFocusControl->SetFocused();
331                         pFocusControl->DrawFocus();
332                         pTop->SetFocusTraversalControl(pFocusControl, true);
333                         return;
334                 }
335         }
336
337         IListT<_Control*>* pFocusControlList =  null;
338
339         pFocusControlList = pTop->GetFocusList();
340
341         if (pFocusControlList)
342         {
343                 unique_ptr<IEnumeratorT<_Control*> > pEnum (pFocusControlList->GetEnumeratorN());
344                 SysTryReturnVoidResult(NID_UI_CTRL, pEnum, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
345                 int index = 0;
346                 bool findNextFocusControl = false;
347                 _Control* pNextFocusControl = null;
348                 int count = 0;
349                 int loopCount = pFocusControlList->GetCount() + 1;
350                 while (pEnum->MoveNext() == E_SUCCESS)
351                 {
352                         _Control* pEnumeratorControl = null;
353                         pEnum->GetCurrent(pEnumeratorControl);
354
355                         //Find current focused control
356                         if (pControl == pEnumeratorControl)
357                         {
358                         //Find next focusable control.
359                         index = GetNextIndex(index, focusDirection, pFocusControlList);
360                         count ++;
361                                 while (pFocusControlList->GetAt(index, pNextFocusControl) == E_SUCCESS)
362                                 {
363                                         
364                                         if (IsFocusable(pNextFocusControl))
365                                         {
366                                                 if (pNextFocusControl != pControl)
367                                                 {
368                                                     pNextFocusControl->SetFocused();
369                                                 }
370                                                 else
371                                                 {
372                                                         pTop->SetFocusControl(pNextFocusControl, true);
373                                                 }
374                                                 findNextFocusControl = true;
375                                                 break;
376                                         }
377                                         else
378                                         {
379                                                 count ++;
380                                                 if (loopCount == count) 
381                                                 {
382                                                         return;
383                                                 }
384                                                 index = GetNextIndex(index, focusDirection, pFocusControlList);
385                                         }
386
387                                 }
388                         }
389
390                         if (findNextFocusControl == true)
391                         {
392                                 break;
393                         }
394
395                         index ++;
396                 }
397
398                 pTop->SetFocusTraversalControl(pNextFocusControl, true);
399                 if (pNextFocusControl && findNextFocusControl == true)
400                 {
401                         _Control* pParentControl =  pNextFocusControl->GetParent();
402                         if (pParentControl)
403                         {
404                                 pParentControl->OnChildControlFocusMoved(*pNextFocusControl);
405                                 while(pParentControl)
406                                 {
407                                         pParentControl->OnDescendantControlFocusMoved(*pNextFocusControl);
408                                         pParentControl = pParentControl->GetParent();
409                                 }
410                         }
411                         pNextFocusControl->DrawFocus();
412                 }
413         }
414 }
415
416 bool
417 _FocusManagerImpl::OnKeyPressed(const _Control& source, const _KeyInfo& keyInfo)
418 {
419         Ecore_X_Window rootWindow = ecore_x_window_root_first_get();
420         Ecore_X_Atom keyboardExist = ecore_x_atom_get("X External Keyboard Exist");
421         unsigned int keyboardNumber = 0;
422         int ret = ecore_x_window_prop_card32_get(rootWindow, keyboardExist, &keyboardNumber, 1);
423         if (keyboardNumber == 0)
424         {
425                 return false;
426         }
427         _KeyCode keyCode = keyInfo.GetKeyCode();
428         __focusDirection = FOCUS_DIRECTION_DOWNWARD;
429         _Control* pControl = const_cast<_Control*> (&source);
430
431         switch(keyCode)
432         {
433         case _KEY_TAB :
434                 {
435                         if (keyInfo.GetKeyModifier() & _KEY_MODIFIER_SHIFT)
436                         {
437                                 __focusDirection = FOCUS_DIRECTION_UPWARD;
438                         }                       
439                         break;
440                 }
441         case _KEY_UP :
442                 {
443                         __focusDirection = FOCUS_DIRECTION_UPWARD;
444                         break;
445                 }
446         case _KEY_DOWN :
447                 {
448                         __focusDirection = FOCUS_DIRECTION_DOWNWARD;
449                         break;
450                 }
451         default :
452                 {
453                         return false;
454                 }       
455         }
456         StartFocusTraversal(pControl, __focusDirection);        
457         return false;
458 }
459
460 bool _FocusManagerImpl::IsForwardDirection(void) const
461 {
462         if (__focusDirection == FOCUS_DIRECTION_DOWNWARD)
463         {
464                 return true;
465         }
466         return false;
467 }
468
469 bool
470 _FocusManagerImpl::OnKeyReleased(const _Control& source, const _KeyInfo& keyInfo)
471 {
472         return false;
473 }
474
475 bool
476 _FocusManagerImpl::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
477 {
478         _Control* pSourceControl = const_cast<_Control*>(&source);
479         __isFocusMode = false;
480
481         _Window* pTop = source.GetRootWindow();
482         if (pTop)
483         {
484                 _Control* pControl = pTop->GetFocusControl(pSourceControl);
485                 if (pControl)
486                 {
487                         pControl->OnFocusModeStateChanged();
488                         pControl->RemoveFocusRing();
489                 }
490         }
491
492         return false;
493 }
494
495 bool
496 _FocusManagerImpl::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
497 {
498         return false;
499 }
500
501 bool
502 _FocusManagerImpl:: OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
503 {
504         return false;
505 }
506
507 bool
508 _FocusManagerImpl::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
509 {
510         return false;
511 }
512 } } //Tizen::Ui
513