Merge "Fix keypad enable logic" into tizen_2.1
[platform/framework/native/uifw.git] / src / ui / FUi_OrientationAgent.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 /**
19  * @file        FUi_OrientationAgent.cpp
20  * @brief       This is the implementation file for the _OrientationAgent class.
21  */
22
23 #include <unique_ptr.h>
24 #include <app.h>
25 #include <FBaseSysLog.h>
26 #include <FBaseColArrayList.h>
27 #include "FUi_OrientationAgent.h"
28 #include "FUi_ControlManager.h"
29 #include "FUi_ControlImplManager.h"
30 #include "FUi_PublicOrientationEvent.h"
31 #include "FUi_ControlImpl.h"
32 #include "FUi_Window.h"
33 #include "FUiCtrl_FormImpl.h"
34 #include "FUiCtrl_FrameImpl.h"
35 #include "FUiCtrl_Frame.h"
36 #include "FUiCtrl_Form.h"
37 #include "FUi_EcoreEvasMgr.h"
38 #include "FUi_EcoreEvas.h"
39 #include "FUi_ControlManager.h"
40 #include "FUi_UiNotificationEvent.h"
41 #include "FUi_UiEventManager.h"
42
43 using namespace std;
44 using namespace Tizen::Base;
45 using namespace Tizen::Base::Collection;
46 using namespace Tizen::Base::Runtime;
47 using namespace Tizen::Ui::Controls;
48 using namespace Tizen::Graphics;
49
50 namespace Tizen { namespace Ui {
51
52 const String _REQUEST_ORIENTATION_EVENT = L"RequestOrientationEvent";
53
54 _OrientationAgent*
55 _OrientationAgent::CreateInstanceN(Control& publicControl)
56 {
57         _OrientationAgent* pAgent = new (std::nothrow) _OrientationAgent(publicControl);
58         SysTryReturn(NID_UI, pAgent, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
59
60         result r = GetLastResult();
61         SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
62
63         SetLastResult(E_SUCCESS);
64
65         return pAgent;
66
67 CATCH:
68         delete pAgent;
69         return null;
70 }
71
72 _OrientationAgent::_OrientationAgent(Control& publicControl)
73         : __publicControl(publicControl)
74         , __pPublicEvent(null)
75         , __mode(ORIENTATION_PORTRAIT)
76         , __status(ORIENTATION_STATUS_PORTRAIT)
77         , __firePublicEvent(false)
78         , __statusChanged(false)
79         , __updateStatus(true)
80 #if defined(WINDOW_BASE_ROTATE)
81         , __draw(false)
82 #endif
83 {
84         _PublicOrientationEvent* pPublicEvent = _PublicOrientationEvent::CreateInstanceN(publicControl);
85
86         result r = GetLastResult();
87         SysTryReturnVoidResult(NID_UI, pPublicEvent, r, "[%s] Propagating.", GetErrorMessage(r));
88
89         __pPublicEvent = pPublicEvent;
90
91         SetLastResult(E_SUCCESS);
92 }
93
94 _OrientationAgent::~_OrientationAgent(void)
95 {
96         if (__pPublicEvent)
97         {
98                 delete __pPublicEvent;
99                 __pPublicEvent = null;
100         }
101 }
102
103 void
104 _OrientationAgent::AddListener(IOrientationEventListener& listener)
105 {
106         result r = __pPublicEvent->AddListener(listener);
107         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
108
109         SetLastResult(E_SUCCESS);
110 }
111
112 void
113 _OrientationAgent::RemoveListener(IOrientationEventListener& listener)
114 {
115         result r = __pPublicEvent->RemoveListener(listener);
116         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
117
118         SetLastResult(E_SUCCESS);
119 }
120
121 Orientation
122 _OrientationAgent::GetMode(void) const
123 {
124         return __mode;
125 }
126
127 OrientationStatus
128 _OrientationAgent::GetStatus(void) const
129 {
130         return __status;
131 }
132
133 void
134 _OrientationAgent::SetMode(Orientation mode)
135 {
136         SysTryReturnVoidResult(NID_UI, mode != ORIENTATION_NONE, E_INVALID_ARG, "[E_INVALID_ARG] A specified input parameter is invalid.");
137
138         SetLastResult(E_SUCCESS);
139
140         if (__mode == mode)
141         {
142                 return;
143         }
144
145         __mode = mode;
146         Update();
147 }
148
149 void
150 _OrientationAgent::Update(bool draw)
151 {
152 #if defined(WINDOW_BASE_ROTATE)
153         _ControlImplManager* pImplManager = _ControlImplManager::GetInstance();
154         SysAssert(pImplManager);
155
156         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
157         if (!pImpl)
158         {
159                 return;
160         }
161
162         // Set window rotation.
163         _Form* pForm = dynamic_cast<_Form*>(&(pImpl->GetCore()));
164         if (pForm)
165         {
166                 _Control* pParent = pForm->GetParent();
167                 if (pParent)
168                 {
169                         _Form* pCurrentForm = null;
170                         int childCount = pParent->GetChildCount();
171                         
172                         for (int i = childCount; i > 0; i--)
173                         {
174                                 _Control* pChild = pParent->GetChild(i - 1);
175                         
176                                 _Form* pChildForm = dynamic_cast<_Form*>(pChild);
177                                 if (pChildForm)
178                                 {
179                                         if (pChildForm->IsVisible())
180                                         {
181                                                 pCurrentForm = pChildForm;
182
183                                                 break;
184                                         }
185                                 }
186                         }
187
188                         // Current Form
189                         if (pCurrentForm == pForm)
190                         {
191                                 _Window* pWindow = pForm->GetRootWindow();
192                                 if (pWindow)
193                                 {
194                                         Rectangle bounds = pWindow->GetBounds();
195                                         SysLog(NID_UI, "[Window Manager Rotation][Window : 0x%x, %d, %d, %d, %d, Form] Set window rotation with mode(%d).", 
196                                                 pWindow->GetNativeHandle(), bounds.x, bounds.y, bounds.width, bounds.height, __mode);
197                                         SetRotation(*pWindow, __mode);
198                                 }
199
200                                 int owneeCount = pForm->GetOwneeCount();
201                                 for (int i = 0; i < owneeCount; i++)
202                                 {
203                                         _Window* pOwnee = pForm->GetOwnee(i);
204                         
205                                         if (pOwnee)
206                                         {
207                                                 SetRotation(*pOwnee, __mode);
208                                         }
209                                 }
210                         }
211                 }
212         }
213         else
214         {
215                 _Frame* pFrame = dynamic_cast<_Frame*>(&(pImpl->GetCore()));
216
217                 if (pFrame)
218                 {
219                         // Frame which has no forms
220                         int childCount = pFrame->GetChildCount();
221                         if (childCount == 0)
222                         {
223                                 Rectangle bounds = pFrame->GetBounds();
224                                 SysLog(NID_UI, "[Window Manager Rotation][Window : 0x%x, %d, %d, %d, %d, Frame] Set window rotation with mode(%d).", 
225                                         pFrame->GetNativeHandle(), bounds.x, bounds.y, bounds.width, bounds.height, __mode);
226                                 SetRotation(*pFrame, __mode);
227
228                                 int owneeCount = pFrame->GetOwneeCount();
229                                 
230                                 for (int i = 0; i < owneeCount; i++)
231                                 {
232                                         _Window* pOwnee = pFrame->GetOwnee(i);
233
234                                         if (pOwnee)
235                                         {
236                                                 SetRotation(*pOwnee, __mode);
237                                         }
238                                 }
239                         }
240                 }
241         }
242
243         __draw = draw;
244 #else           
245         _ControlImplManager* pImplManager = _ControlImplManager::GetInstance();
246         SysAssert(pImplManager);
247
248         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
249         if (!pImpl)
250         {
251                 return;
252         }
253
254         _EcoreEvas* pEcoreEvas = GetEcoreEvasMgr()->GetEcoreEvas();
255         if (!pEcoreEvas)
256         {
257                 return;
258         }
259
260         _Form* pForm = dynamic_cast<_Form*>(&(pImpl->GetCore()));
261         if (pForm)
262         {
263                 _Control* pParent = pForm->GetParent();
264
265                 if (pParent)
266                 {
267                         int index = pParent->GetChildIndex(*pForm);
268                         int childCount = pParent->GetChildCount();
269
270                         if (index == (childCount - 1))
271                         {
272                                 _Window* pWindow = pForm->GetRootWindow();
273                                 if (pWindow)
274                                 {
275                                         if ((__mode == ORIENTATION_AUTOMATIC) || (__mode == ORIENTATION_AUTOMATIC_FOUR_DIRECTION))
276                                         {
277                                                 pEcoreEvas->SetWindowOrientationEnabled(*pWindow, true);
278                                                 pWindow->SetOrientationEnabled(true);
279                                         }
280                                         else
281                                         {
282                                                 pEcoreEvas->SetWindowOrientationEnabled(*pWindow, false);
283                                                 pWindow->SetOrientationEnabled(false);
284                                         }
285                                 }
286                         }
287                 }
288         }
289         else
290         {
291                 _Frame* pFrame = dynamic_cast<_Frame*>(&(pImpl->GetCore()));
292                 if (pFrame)
293                 {
294                         int childCount = pFrame->GetChildCount();
295                         if (childCount == 0)
296                         {
297                                 _Window* pCurrentFrame = _ControlManager::GetInstance()->GetCurrentFrame();
298                                 if (pCurrentFrame == pFrame)
299                                 {
300                                         if ((__mode == ORIENTATION_AUTOMATIC) || (__mode == ORIENTATION_AUTOMATIC_FOUR_DIRECTION))
301                                         {
302                                                 pEcoreEvas->SetWindowOrientationEnabled(*pFrame, true);
303                                                 pFrame->SetOrientationEnabled(true);
304                                         }
305                                         else
306                                         {
307                                                 pEcoreEvas->SetWindowOrientationEnabled(*pFrame, false);
308                                                 pFrame->SetOrientationEnabled(false);
309                                         }
310                                 }
311                         }
312                 }
313         }
314
315         OrientationStatus status = pImplManager->GetOrientationStatus(__mode);
316
317         if (__updateStatus == true)
318         {
319                 __statusChanged = false;
320                 if (__status != status)
321                 {
322                         __statusChanged = true;
323                         __updateStatus = false;
324                 }
325         }
326
327         __status = status;
328
329         pEcoreEvas->AllowSetWindowBounds(false);
330         FireEvent(status);
331         pEcoreEvas->AllowSetWindowBounds(true);
332
333         // For the form to be made by Ui-Builder
334         if ((draw == true) && (__statusChanged == true))
335         {
336                 _ControlOrientation coreOrientation =
337                         (status == ORIENTATION_STATUS_PORTRAIT || status == ORIENTATION_STATUS_PORTRAIT_REVERSE) ?
338                         _CONTROL_ORIENTATION_PORTRAIT : _CONTROL_ORIENTATION_LANDSCAPE;
339
340                 Rectangle temp;
341                 bool exist = pImpl->GetBuilderBounds(coreOrientation, temp);
342                 if (exist)
343                 {
344                         pImpl->Invalidate(true);
345                 }
346         }
347
348         // Despite not changing status, it needs to rotate screen.
349         _ControlImpl* pControlImpl = _ControlImpl::GetInstance(__publicControl);
350         pImplManager->RotateScreen(pControlImpl, status);
351 #endif
352 }
353
354 #if defined(WINDOW_BASE_ROTATE)
355 void
356 _OrientationAgent::UpdateOrientation(void)
357 {
358         _EcoreEvas* pEcoreEvas = GetEcoreEvasMgr()->GetEcoreEvas();
359         if (!pEcoreEvas)
360         {
361                 return;
362         }
363
364         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
365         if (!pImpl)
366         {
367                 return;
368         }
369
370         int rotation = pEcoreEvas->GetWindowRotation(*(pImpl->GetCore().GetRootWindow()));
371
372         // Update evas objects.
373         OrientationStatus status = ORIENTATION_STATUS_NONE;
374         switch (rotation)
375         {
376         case 0:
377                 status = ORIENTATION_STATUS_PORTRAIT;
378                 break;
379         case 270:
380                 status = ORIENTATION_STATUS_LANDSCAPE;
381                 break;
382         case 180:
383                 status = ORIENTATION_STATUS_PORTRAIT_REVERSE;
384                 break;
385         case 90:
386                 status = ORIENTATION_STATUS_LANDSCAPE_REVERSE;
387                 break;
388         default:
389                 break;
390         }
391
392         if (__updateStatus == true)
393         {
394                 __statusChanged = false;
395                 if (__status != status)
396                 {
397                         __statusChanged = true;
398                         __updateStatus = false;
399                 }
400         }
401
402         __status = status;
403
404         pEcoreEvas->AllowSetWindowBounds(false);
405         FireEvent(status);
406         pEcoreEvas->AllowSetWindowBounds(true);
407
408         // For the form to be made by Ui-Builder
409         if ((__draw == true) && (__statusChanged == true))
410         {
411                 _ControlOrientation coreOrientation =
412                         (status == ORIENTATION_STATUS_PORTRAIT || status == ORIENTATION_STATUS_PORTRAIT_REVERSE) ?
413                         _CONTROL_ORIENTATION_PORTRAIT : _CONTROL_ORIENTATION_LANDSCAPE;
414
415                 Rectangle temp;
416                 bool exist = pImpl->GetBuilderBounds(coreOrientation, temp);
417                 if (exist)
418                 {
419                         pImpl->Invalidate(true);
420                 }
421         }
422
423         _Window* pRootWindow = pImpl->GetCore().GetRootWindow();
424         if (pRootWindow)
425         {
426                 pEcoreEvas->UpdateWindowBounds(*pRootWindow);
427                 
428                 Rectangle bounds = pRootWindow->GetBounds();
429                 SysLog(NID_UI, "[Window Manager Rotation][Window : 0x%x, %d, %d, %d, %d] Update evas objects to %d degree.", 
430                         pRootWindow->GetNativeHandle(), bounds.x, bounds.y, bounds.width, bounds.height, rotation);
431         }
432 }
433 #endif
434
435 void
436 _OrientationAgent::RequestOrientationEvent(void)
437 {
438         ClearLastResult();
439
440         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
441         SysTryReturnVoidResult(NID_UI, pImpl, E_SYSTEM, "[E_SYSTEM] A system error occurred.");
442
443         unique_ptr<ArrayList> pEventArgs(new (std::nothrow) ArrayList());
444         SysTryReturnVoidResult(NID_UI, pEventArgs, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
445         pEventArgs->Construct();
446
447         unique_ptr<String> pString(new (std::nothrow) Tizen::Base::String(_REQUEST_ORIENTATION_EVENT));
448         SysTryReturnVoidResult(NID_UI, pString, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
449
450         pEventArgs->Add(*(pString.get()));
451         
452         _UiNotificationEvent event(pImpl->GetCore().GetHandle(), pEventArgs.get());
453
454         result r = _UiEventManager::GetInstance()->PostEvent(event);
455         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] A system error occurred.");
456
457         pString.release();
458         pEventArgs.release();
459 }
460
461 void
462 _OrientationAgent::FireOrientationEvent(void)
463 {
464         if (__firePublicEvent)
465         {
466                 return;
467         }
468
469         __firePublicEvent = true;
470
471         SysLog(NID_UI, "Fire the orientation event.");
472
473         if (__statusChanged)
474         {
475                 IEventArg* pArg = _PublicOrientationEvent::CreateOrientationEventArgN(*__pPublicEvent->GetSource(), __status);
476                 __pPublicEvent->Fire(*pArg);
477
478                 __updateStatus = true;
479         }
480 }
481
482 void
483 _OrientationAgent::FireEvent(OrientationStatus status)
484 {
485         ClearLastResult();
486
487         _ControlManager* pCoreManager = _ControlManager::GetInstance();
488         SysAssert(pCoreManager);
489
490         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
491         if (!pImpl)
492         {
493                 return;
494         }
495
496         _ControlOrientation coreOrientation =
497                 (status == ORIENTATION_STATUS_PORTRAIT || status == ORIENTATION_STATUS_PORTRAIT_REVERSE) ?
498                 _CONTROL_ORIENTATION_PORTRAIT : _CONTROL_ORIENTATION_LANDSCAPE;
499
500         _ControlImplManager* pImplManager = _ControlImplManager::GetInstance();
501         SysAssert(pImplManager);
502
503         // Core
504         pCoreManager->SetOrientation(coreOrientation);
505         pImplManager->SetOrientationStatus(status);
506         pImpl->GetCore().ChangeLayout(coreOrientation);
507
508 #if !defined(WINDOW_BASE_ROTATE)
509         // Ownee
510         int owneeCount = pImpl->GetCore().GetOwneeCount();
511         for (int i = 0; i < owneeCount; i++)
512         {
513                 _Window* pOwnee = pImpl->GetCore().GetOwnee(i);
514
515                 if (pOwnee)
516                 {
517                         pOwnee->ChangeLayout(coreOrientation);
518                 }
519         }
520 #endif
521
522         // Public
523         if (__firePublicEvent && __statusChanged)
524         {
525                 IEventArg* pArg = _PublicOrientationEvent::CreateOrientationEventArgN(*__pPublicEvent->GetSource(), status);
526                 __pPublicEvent->Fire(*pArg);
527
528                 __updateStatus = true;
529         }
530 }
531
532 #if defined(WINDOW_BASE_ROTATE)
533 void
534 _OrientationAgent::SetRotation(const _Window& window, Orientation orientation)
535 {
536         _EcoreEvas* pEcoreEvas = GetEcoreEvasMgr()->GetEcoreEvas();
537         if (!pEcoreEvas)
538         {
539                 return;
540         }
541
542         int deviceOrientation = app_get_device_orientation();
543         int windowRotation = pEcoreEvas->GetWindowRotation(window);
544
545         bool callback = true;
546
547         // Decide updating orientation forcibly.
548         switch (orientation)
549         {
550         case ORIENTATION_PORTRAIT:
551                 pEcoreEvas->SetWindowPreferredRotation(window, 0);
552                 
553                 if ((deviceOrientation == 0) || (windowRotation == 0))
554                 {
555                         callback = false;
556                 }
557                 
558                 break;
559         case ORIENTATION_LANDSCAPE:
560                 pEcoreEvas->SetWindowPreferredRotation(window, 270);
561                 
562                 if ((deviceOrientation == 270) || (windowRotation == 270))
563                 {
564                         callback = false;
565                 }
566                 
567                 break;
568         case ORIENTATION_PORTRAIT_REVERSE:
569                 pEcoreEvas->SetWindowPreferredRotation(window, 180);
570                 
571                 if ((deviceOrientation == 180) || (windowRotation == 180))
572                 {
573                         callback = false;
574                 }
575                 
576                 break;
577         case ORIENTATION_LANDSCAPE_REVERSE:
578                 pEcoreEvas->SetWindowPreferredRotation(window, 90);
579                 
580                 if ((deviceOrientation == 90) || (windowRotation == 90))
581                 {
582                         callback = false;
583                 }
584                 
585                 break;
586         case ORIENTATION_AUTOMATIC:
587                 {
588                         pEcoreEvas->SetWindowPreferredRotation(window, -1);
589
590                         int autoRotation[3] = {0, 90, 270};
591                         pEcoreEvas->SetWindowAvailabledRotation(window, autoRotation, 3);
592
593                         if (deviceOrientation == windowRotation)
594                         {
595                                 callback = false;
596                         }
597                         else
598                         {
599                                 if (deviceOrientation == 180)
600                                 {
601                                         callback = false;
602                                 }
603                         }
604                 }
605                 break;
606         case ORIENTATION_AUTOMATIC_FOUR_DIRECTION:
607                 {
608                         pEcoreEvas->SetWindowPreferredRotation(window, -1);
609
610                         int autoFourRotation[4] = {0, 90, 180, 270};
611                         pEcoreEvas->SetWindowAvailabledRotation(window, autoFourRotation, 4);
612
613                         if (deviceOrientation == windowRotation)
614                         {
615                                 callback = false;
616                         }
617                 }
618                 break;
619         default:
620                 break;
621         }
622
623         if (callback == false)
624         {
625                 UpdateOrientation();
626         }
627 }
628 #endif
629
630 }} // Tizen::Ui