Fork for IVI: mesa fixing
[profile/ivi/uifw.git] / src / ui / FUi_ModalLoopManager.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  * @file                FUi_ModalLoopManager.cpp
19  * @brief               This is the implementation file for the _ModalLoopManager class.
20  */
21
22 #include <new>
23 #include <pthread.h>
24 #include <FBaseSysLog.h>
25 #include <FBaseRtTimer.h>
26 #include "FUi_ModalLoopManager.h"
27 #include "FUi_EcoreEvasMgr.h"
28
29 using namespace Tizen::Base::Runtime;
30 using namespace Tizen::Ui;
31
32 namespace Tizen { namespace Ui
33 {
34
35 _ModalLoopManager::_ModalLoopManager(void)
36         : __pTimerInfoList(null)
37         , __nestedMainLoop(0)
38         , __lastExitCode(-1)
39 {
40         __pTimerInfoList = new (std::nothrow) TimerInfoList;
41         SysAssert(__pTimerInfoList);
42         __pTimerInfoList->Construct();
43 }
44
45 _ModalLoopManager::~_ModalLoopManager(void)
46 {
47         if (__pTimerInfoList)
48         {
49                 _TimerInfo timerInfo;
50                 const int count = __pTimerInfoList->GetCount();
51                 for (int i = 0; i < count; i++)
52                 {
53                         timerInfo.pTimer = null;
54                         __pTimerInfoList->GetAt(i, timerInfo);
55                         if (timerInfo.pTimer)
56                         {
57                                 delete timerInfo.pTimer;
58                         }
59                 }
60                 __pTimerInfoList->RemoveAll();
61                 delete __pTimerInfoList;
62                 __pTimerInfoList = null;
63         }
64
65         if (__nestedMainLoop > 0)
66         {
67                 SysLog(NID_UI, "[ModalLoopManager] The count of nested main loops is: %d", __nestedMainLoop);
68         }
69 }
70
71 int
72 _ModalLoopManager::BeginMainLoop(void)
73 {
74         __nestedMainLoop++;
75         ::GetEcoreEvasMgr()->BeginMainLoop();
76
77         return __nestedMainLoop;
78 }
79
80 int
81 _ModalLoopManager::BeginMainLoop(unsigned long timeOut, int exitCode)
82 {
83         result r = E_SUCCESS;
84         Timer* pTimer = null;
85
86         if (timeOut > 0l)
87         {
88                 pTimer = new (std::nothrow) Timer;
89                 SysTryReturn(NID_UI, pTimer != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Unable to create Timer.");
90
91                 r = pTimer->Construct(*this);
92                 SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
93
94                 r = pTimer->Start(timeOut);
95                 SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
96
97                 _TimerInfo timerInfo;
98                 timerInfo.loopId = __nestedMainLoop + 1;
99                 timerInfo.pTimer = pTimer;
100                 timerInfo.exitCode = exitCode;
101                 timerInfo.expired = false;
102                 r = __pTimerInfoList->Add(timerInfo);
103                 SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
104         }
105
106         return BeginMainLoop();
107
108 CATCH:
109         delete pTimer;
110         return -1;
111 }
112
113 int
114 _ModalLoopManager::EndMainLoop(int exitCode, bool endAllLoops)
115 {
116         if (__nestedMainLoop == 0)
117         {
118                 return __nestedMainLoop;
119         }
120
121         __lastExitCode = exitCode;
122
123         _TimerInfo timerInfo;
124         int timerCount = 0;
125         int loopCount = endAllLoops ? __nestedMainLoop : 1;
126         while (loopCount--)
127         {
128                 timerCount = __pTimerInfoList->GetCount();
129                 if (timerCount > 0)
130                 {
131                         __pTimerInfoList->GetAt(timerCount - 1, timerInfo);
132                         if (timerInfo.loopId == __nestedMainLoop)
133                         {
134                                 timerInfo.pTimer->Cancel();
135                                 delete timerInfo.pTimer;
136                                 __pTimerInfoList->RemoveAt(timerCount - 1);
137                         }
138                 }
139                 timerCount = __pTimerInfoList->GetCount();
140                 if (timerCount > 0)
141                 {
142                         __pTimerInfoList->GetAt(timerCount - 1, timerInfo);
143                         if ((timerInfo.loopId == __nestedMainLoop - 1) && (timerInfo.expired == true))
144                         {
145                                 __lastExitCode = -2;
146                         }
147                 }
148                 ::GetEcoreEvasMgr()->EndMainLoop();
149                 __nestedMainLoop--;
150         }
151
152         return __nestedMainLoop;
153 }
154
155 int
156 _ModalLoopManager::GetLastExitCode(void)
157 {
158         return __lastExitCode;
159 }
160
161 void
162 _ModalLoopManager::OnTimerExpired(Timer& timer)
163 {
164         const int count = __pTimerInfoList->GetCount();
165         int pos = -1;
166         int i = count -1;
167         _TimerInfo timerInfo;
168
169         while (i >= 0)
170         {
171                 __pTimerInfoList->GetAt(i, timerInfo);
172
173                 if (timerInfo.pTimer == &timer)
174                 {
175                         pos = timerInfo.loopId;
176                         timerInfo.expired = true;
177                         __pTimerInfoList->SetAt(timerInfo, i);
178                         break;
179                 }
180                 i--;
181         }
182
183         if (pos == __nestedMainLoop)
184         {
185                 _ModalLoopManager::GetInstance()->EndMainLoop(timerInfo.exitCode, false);
186         }
187 }
188
189 _ModalLoopManager* _ModalLoopManager::__pInstance = null;
190
191 void
192 _ModalLoopManager::Initialize(void)
193 {
194   static _ModalLoopManager instance;
195   __pInstance = &instance;
196 }
197
198 _ModalLoopManager*
199 _ModalLoopManager::GetInstance(void)
200 {
201   static pthread_once_t once_block = PTHREAD_ONCE_INIT;
202
203   if (!__pInstance)
204   {
205     pthread_once(&once_block, Initialize);
206   }
207
208   return __pInstance;
209 }
210
211 _ModalLoopManager::_TimerInfo::_TimerInfo(void)
212         : loopId(-1)
213         , pTimer(null)
214         , exitCode(-1)
215         , expired(false)
216 {
217 }
218
219 _ModalLoopManager::_TimerInfo::~_TimerInfo(void)
220 {
221 }
222
223 bool
224 _ModalLoopManager::_TimerInfo::operator==(const _ModalLoopManager::_TimerInfo& rhs) const
225 {
226         return ((loopId == rhs.loopId) && (pTimer == rhs.pTimer) && (exitCode == rhs.exitCode) && (expired == rhs.expired));
227 }
228
229 bool _ModalLoopManager::_TimerInfo::operator!=(const _ModalLoopManager::_TimerInfo& rhs) const
230 {
231         return ((loopId != rhs.loopId) || (pTimer != rhs.pTimer) || (exitCode != rhs.exitCode) || (expired != rhs.expired));
232 }
233
234 _ModalLoopManager::_TimerInfo&
235 _ModalLoopManager::_TimerInfo::operator=(const _ModalLoopManager::_TimerInfo& rhs)
236 {
237         loopId = rhs.loopId;
238         pTimer = rhs.pTimer;
239         exitCode = rhs.exitCode;
240         expired = rhs.expired;
241
242         return *this;
243 }
244
245 }} // Tizen::Ui