Merge "Fix Window Manager Rotation" 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         , __tempStatus(ORIENTATION_STATUS_PORTRAIT)
78         , __firePublicEvent(false)
79         , __statusChanged(false)
80         , __updateStatus(true)
81 #if defined(WINDOW_BASE_ROTATE)
82         , __draw(false)
83 #endif
84 {
85         _PublicOrientationEvent* pPublicEvent = _PublicOrientationEvent::CreateInstanceN(publicControl);
86
87         result r = GetLastResult();
88         SysTryReturnVoidResult(NID_UI, pPublicEvent, r, "[%s] Propagating.", GetErrorMessage(r));
89
90         __pPublicEvent = pPublicEvent;
91
92         SetLastResult(E_SUCCESS);
93 }
94
95 _OrientationAgent::~_OrientationAgent(void)
96 {
97         if (__pPublicEvent)
98         {
99                 delete __pPublicEvent;
100                 __pPublicEvent = null;
101         }
102 }
103
104 void
105 _OrientationAgent::AddListener(IOrientationEventListener& listener)
106 {
107         result r = __pPublicEvent->AddListener(listener);
108         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
109
110         SetLastResult(E_SUCCESS);
111 }
112
113 void
114 _OrientationAgent::RemoveListener(IOrientationEventListener& listener)
115 {
116         result r = __pPublicEvent->RemoveListener(listener);
117         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
118
119         SetLastResult(E_SUCCESS);
120 }
121
122 Orientation
123 _OrientationAgent::GetMode(void) const
124 {
125         return __mode;
126 }
127
128 OrientationStatus
129 _OrientationAgent::GetStatus(void) const
130 {
131         return __status;
132 }
133
134 void
135 _OrientationAgent::SetMode(Orientation mode)
136 {
137         SysTryReturnVoidResult(NID_UI, mode != ORIENTATION_NONE, E_INVALID_ARG, "[E_INVALID_ARG] A specified input parameter is invalid.");
138
139         SetLastResult(E_SUCCESS);
140
141         if (__mode == mode)
142         {
143                 return;
144         }
145
146         __mode = mode;
147         Update();
148 }
149
150 void
151 _OrientationAgent::Update(bool draw)
152 {
153 #if defined(WINDOW_BASE_ROTATE)
154         // Update orientation status(Not Auto-mode)
155         // Request rotation to window manager -> async -> Update VEs
156         // Window(not rotation) -> sync -> UpdateVEs
157
158         _ControlImplManager* pImplManager = _ControlImplManager::GetInstance();
159         SysAssert(pImplManager);
160
161         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
162         if (!pImpl)
163         {
164                 return;
165         }
166
167         _EcoreEvas* pEcoreEvas = GetEcoreEvasMgr()->GetEcoreEvas();
168         if (!pEcoreEvas)
169         {
170                 return;
171         }
172
173         bool autoMode = false;
174
175         if ((__mode == ORIENTATION_AUTOMATIC) || (__mode == ORIENTATION_AUTOMATIC_FOUR_DIRECTION))
176         {
177                 autoMode = true;
178         }
179
180 //      if (autoMode == false)
181 //      {
182                 // [Sync]
183                 // Update orientation status
184                 // Update VEs
185                 // Fire orientation event
186                 // Rotate screen
187                 // Set preffered rotation
188
189                 OrientationStatus status = pImplManager->GetOrientationStatus(__mode);
190                 
191                 if (__updateStatus == true)
192                 {
193                         __statusChanged = false;
194                         if (__status != status)
195                         {
196                                 __statusChanged = true;
197                                 __updateStatus = false;
198                         }
199                 }
200                 
201                 __status = status;
202                 
203                 pEcoreEvas->AllowSetWindowBounds(false);
204                 FireEvent(status);
205                 pEcoreEvas->AllowSetWindowBounds(true);
206                 
207                 // For the form to be made by Ui-Builder
208                 if ((draw == true) && (__statusChanged == true))
209                 {
210                         _ControlOrientation coreOrientation =
211                                 (status == ORIENTATION_STATUS_PORTRAIT || status == ORIENTATION_STATUS_PORTRAIT_REVERSE) ?
212                                 _CONTROL_ORIENTATION_PORTRAIT : _CONTROL_ORIENTATION_LANDSCAPE;
213                 
214                         Rectangle temp;
215                         bool exist = pImpl->GetBuilderBounds(coreOrientation, temp);
216                         if (exist)
217                         {
218                                 pImpl->Invalidate(true);
219                         }
220                 }
221                 
222                 // Despite not changing status, it needs to rotate screen.
223                 _ControlImpl* pControlImpl = _ControlImpl::GetInstance(__publicControl);
224                 pImplManager->RotateScreen(pControlImpl, status);
225
226                 _Window* pRootWindow = pImpl->GetCore().GetRootWindow();
227                 if (pRootWindow)
228                 {
229                         SetRotation(*pRootWindow, __mode);
230                 }
231 //      }
232 //      else
233 //      {
234                 // [Async]
235                 // Set preffered rotation
236
237 //              _Window* pRootWindow = pImpl->GetCore().GetRootWindow();
238 //              if (pRootWindow)
239 //              {
240 //                      SetRotation(*pRootWindow, __mode);
241 //              }
242
243                 __draw = draw;
244 //      }
245 #else           
246         _ControlImplManager* pImplManager = _ControlImplManager::GetInstance();
247         SysAssert(pImplManager);
248
249         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
250         if (!pImpl)
251         {
252                 return;
253         }
254
255         _EcoreEvas* pEcoreEvas = GetEcoreEvasMgr()->GetEcoreEvas();
256         if (!pEcoreEvas)
257         {
258                 return;
259         }
260
261         _Form* pForm = dynamic_cast<_Form*>(&(pImpl->GetCore()));
262         if (pForm)
263         {
264                 _Control* pParent = pForm->GetParent();
265
266                 if (pParent)
267                 {
268                         int index = pParent->GetChildIndex(*pForm);
269                         int childCount = pParent->GetChildCount();
270
271                         if (index == (childCount - 1))
272                         {
273                                 _Window* pWindow = pForm->GetRootWindow();
274                                 if (pWindow)
275                                 {
276                                         if ((__mode == ORIENTATION_AUTOMATIC) || (__mode == ORIENTATION_AUTOMATIC_FOUR_DIRECTION))
277                                         {
278                                                 pEcoreEvas->SetWindowOrientationEnabled(*pWindow, true);
279                                                 pWindow->SetOrientationEnabled(true);
280                                         }
281                                         else
282                                         {
283                                                 pEcoreEvas->SetWindowOrientationEnabled(*pWindow, false);
284                                                 pWindow->SetOrientationEnabled(false);
285                                         }
286                                 }
287                         }
288                 }
289         }
290         else
291         {
292                 _Frame* pFrame = dynamic_cast<_Frame*>(&(pImpl->GetCore()));
293                 if (pFrame)
294                 {
295                         int childCount = pFrame->GetChildCount();
296                         if (childCount == 0)
297                         {
298                                 _Window* pCurrentFrame = _ControlManager::GetInstance()->GetCurrentFrame();
299                                 if (pCurrentFrame == pFrame)
300                                 {
301                                         if ((__mode == ORIENTATION_AUTOMATIC) || (__mode == ORIENTATION_AUTOMATIC_FOUR_DIRECTION))
302                                         {
303                                                 pEcoreEvas->SetWindowOrientationEnabled(*pFrame, true);
304                                                 pFrame->SetOrientationEnabled(true);
305                                         }
306                                         else
307                                         {
308                                                 pEcoreEvas->SetWindowOrientationEnabled(*pFrame, false);
309                                                 pFrame->SetOrientationEnabled(false);
310                                         }
311                                 }
312                         }
313                 }
314         }
315
316         OrientationStatus status = pImplManager->GetOrientationStatus(__mode);
317
318         if (__updateStatus == true)
319         {
320                 __statusChanged = false;
321                 if (__status != status)
322                 {
323                         __statusChanged = true;
324                         __updateStatus = false;
325                 }
326         }
327
328         __status = status;
329
330         pEcoreEvas->AllowSetWindowBounds(false);
331         FireEvent(status);
332         pEcoreEvas->AllowSetWindowBounds(true);
333
334         // For the form to be made by Ui-Builder
335         if ((draw == true) && (__statusChanged == true))
336         {
337                 _ControlOrientation coreOrientation =
338                         (status == ORIENTATION_STATUS_PORTRAIT || status == ORIENTATION_STATUS_PORTRAIT_REVERSE) ?
339                         _CONTROL_ORIENTATION_PORTRAIT : _CONTROL_ORIENTATION_LANDSCAPE;
340
341                 Rectangle temp;
342                 bool exist = pImpl->GetBuilderBounds(coreOrientation, temp);
343                 if (exist)
344                 {
345                         pImpl->Invalidate(true);
346                 }
347         }
348
349         // Despite not changing status, it needs to rotate screen.
350         _ControlImpl* pControlImpl = _ControlImpl::GetInstance(__publicControl);
351         pImplManager->RotateScreen(pControlImpl, status);
352 #endif
353 }
354
355 #if defined(WINDOW_BASE_ROTATE)
356 void
357 _OrientationAgent::UpdateOrientation(void)
358 {
359         // Get window rotation
360         // Update VEs
361         // Fire orientation event
362         // Update window bounds
363         // Invalidate
364
365         _EcoreEvas* pEcoreEvas = GetEcoreEvasMgr()->GetEcoreEvas();
366         if (!pEcoreEvas)
367         {
368                 return;
369         }
370
371         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
372         if (!pImpl)
373         {
374                 return;
375         }
376
377         _Window* pRootWindow = pImpl->GetCore().GetRootWindow();
378         if (!pRootWindow)
379         {
380                 return;
381         }
382
383         int rotation = pEcoreEvas->GetWindowRotation(*pRootWindow);
384         OrientationStatus status = ORIENTATION_STATUS_NONE;
385         switch (rotation)
386         {
387         case 0:
388                 status = ORIENTATION_STATUS_PORTRAIT;
389                 break;
390         case 270:
391                 status = ORIENTATION_STATUS_LANDSCAPE;
392                 break;
393         case 180:
394                 status = ORIENTATION_STATUS_PORTRAIT_REVERSE;
395                 break;
396         case 90:
397                 status = ORIENTATION_STATUS_LANDSCAPE_REVERSE;
398                 break;
399         default:
400                 break;
401         }
402
403         if (__updateStatus == true)
404         {
405                 __statusChanged = false;
406                 if (__status != status)
407                 {
408                         __statusChanged = true;
409                         __updateStatus = false;
410                 }
411         }
412
413         __status = status;
414
415         pEcoreEvas->AllowSetWindowBounds(false);
416         FireEvent(status);
417         pEcoreEvas->AllowSetWindowBounds(true);
418
419         // For the form to be made by Ui-Builder
420         if ((__draw == true) && (__statusChanged == true))
421         {
422                 _ControlOrientation coreOrientation =
423                         (status == ORIENTATION_STATUS_PORTRAIT || status == ORIENTATION_STATUS_PORTRAIT_REVERSE) ?
424                         _CONTROL_ORIENTATION_PORTRAIT : _CONTROL_ORIENTATION_LANDSCAPE;
425
426                 Rectangle temp;
427                 bool exist = pImpl->GetBuilderBounds(coreOrientation, temp);
428                 if (exist)
429                 {
430                         pImpl->Invalidate(true);
431                 }
432         }
433
434         pEcoreEvas->RotateWindow(*pRootWindow, rotation);
435
436         pImpl->Invalidate(true);
437
438         Rectangle bounds = pRootWindow->GetBounds();
439         SysLog(NID_UI, "[Window Manager Rotation][Window : 0x%x, rot = %d, %d, %d, %d, %d] Update Orientation.", pRootWindow->GetNativeHandle(), rotation, bounds.x, bounds.y, bounds.width, bounds.height);
440 }
441 #endif
442
443 void
444 _OrientationAgent::RequestOrientationEvent(void)
445 {
446         ClearLastResult();
447
448         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
449         SysTryReturnVoidResult(NID_UI, pImpl, E_SYSTEM, "[E_SYSTEM] A system error occurred.");
450
451         unique_ptr<ArrayList> pEventArgs(new (std::nothrow) ArrayList());
452         SysTryReturnVoidResult(NID_UI, pEventArgs, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
453         pEventArgs->Construct();
454
455         unique_ptr<String> pString(new (std::nothrow) Tizen::Base::String(_REQUEST_ORIENTATION_EVENT));
456         SysTryReturnVoidResult(NID_UI, pString, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
457
458         pEventArgs->Add(*(pString.get()));
459         
460         _UiNotificationEvent event(pImpl->GetCore().GetHandle(), pEventArgs.get());
461
462         result r = _UiEventManager::GetInstance()->PostEvent(event);
463         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] A system error occurred.");
464
465         pString.release();
466         pEventArgs.release();
467 }
468
469 void
470 _OrientationAgent::FireOrientationEvent(void)
471 {
472         if (__firePublicEvent)
473         {
474                 return;
475         }
476
477         __firePublicEvent = true;
478
479         SysLog(NID_UI, "Fire the orientation event.");
480
481         if (__statusChanged)
482         {
483                 IEventArg* pArg = _PublicOrientationEvent::CreateOrientationEventArgN(*__pPublicEvent->GetSource(), __status);
484                 __pPublicEvent->Fire(*pArg);
485
486                 _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
487                 if (pImpl)
488                 {
489                         _Window* pWindow = pImpl->GetCore().GetRootWindow();
490                         if (pWindow)
491                         {
492                                 SysLog(NID_UI, "[Window Manager Rotation][Window : 0x%x] Fire the public orientation event..", pWindow->GetNativeHandle());
493                         }
494                 }
495
496                 __updateStatus = true;
497         }
498 }
499
500 void
501 _OrientationAgent::FireEvent(OrientationStatus status)
502 {
503         ClearLastResult();
504
505         _ControlManager* pCoreManager = _ControlManager::GetInstance();
506         SysAssert(pCoreManager);
507
508         _ControlImpl* pImpl = _ControlImpl::GetInstance(__publicControl);
509         if (!pImpl)
510         {
511                 return;
512         }
513
514         _ControlOrientation coreOrientation =
515                 (status == ORIENTATION_STATUS_PORTRAIT || status == ORIENTATION_STATUS_PORTRAIT_REVERSE) ?
516                 _CONTROL_ORIENTATION_PORTRAIT : _CONTROL_ORIENTATION_LANDSCAPE;
517
518         _ControlImplManager* pImplManager = _ControlImplManager::GetInstance();
519         SysAssert(pImplManager);
520
521         // Core
522         pCoreManager->SetOrientation(coreOrientation);
523         pImplManager->SetOrientationStatus(status);
524         pImpl->GetCore().ChangeLayout(coreOrientation);
525
526 #if !defined(WINDOW_BASE_ROTATE)
527         // Ownee
528         int owneeCount = pImpl->GetCore().GetOwneeCount();
529         for (int i = 0; i < owneeCount; i++)
530         {
531                 _Window* pOwnee = pImpl->GetCore().GetOwnee(i);
532
533                 if (pOwnee)
534                 {
535                         pOwnee->ChangeLayout(coreOrientation);
536                 }
537         }
538 #endif
539
540         // Public
541         if (__firePublicEvent && __statusChanged)
542         {
543                 IEventArg* pArg = _PublicOrientationEvent::CreateOrientationEventArgN(*__pPublicEvent->GetSource(), status);
544                 __pPublicEvent->Fire(*pArg);
545
546                 __updateStatus = true;
547         }
548 }
549
550 #if defined(WINDOW_BASE_ROTATE)
551 void
552 _OrientationAgent::SetRotation(const _Window& window, Orientation orientation)
553 {
554         _EcoreEvas* pEcoreEvas = GetEcoreEvasMgr()->GetEcoreEvas();
555         if (!pEcoreEvas)
556         {
557                 return;
558         }
559
560         switch (orientation)
561         {
562         case ORIENTATION_PORTRAIT:
563                 pEcoreEvas->SetWindowPreferredRotation(window, 0);
564                 break;
565         case ORIENTATION_LANDSCAPE:
566                 pEcoreEvas->SetWindowPreferredRotation(window, 270);
567                 break;
568         case ORIENTATION_PORTRAIT_REVERSE:
569                 pEcoreEvas->SetWindowPreferredRotation(window, 180);
570                 break;
571         case ORIENTATION_LANDSCAPE_REVERSE:
572                 pEcoreEvas->SetWindowPreferredRotation(window, 90);
573                 break;
574         case ORIENTATION_AUTOMATIC:
575                 {
576                         pEcoreEvas->SetWindowPreferredRotation(window, -1);
577                         int autoRotation[3] = {0, 90, 270};
578                         pEcoreEvas->SetWindowAvailabledRotation(window, autoRotation, 3);
579                 }
580
581                 break;
582         case ORIENTATION_AUTOMATIC_FOUR_DIRECTION:
583                 {
584                         pEcoreEvas->SetWindowPreferredRotation(window, -1);
585                         int autoFourRotation[4] = {0, 90, 180, 270};
586                         pEcoreEvas->SetWindowAvailabledRotation(window, autoFourRotation, 4);
587                 }
588
589                 break;
590         default:
591                 break;
592         }
593 }
594 #endif
595
596 }} // Tizen::Ui