Merge "Changes needed for https://review.tizen.org/gerrit/#/c/191202/" into devel...
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / common / callback-manager-ecore.cpp
1 /*
2  * Copyright (c) 2018 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 <dali/internal/system/common/callback-manager-ecore.h>
20
21 // EXTERNAL INCLUDES
22 // Ecore is littered with C style cast
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wold-style-cast"
25 #include <Ecore.h>
26
27 #include <dali/integration-api/debug.h>
28
29 // INTERNAL INCLUDES
30
31
32 namespace Dali
33 {
34
35 namespace Internal
36 {
37
38 namespace Adaptor
39 {
40
41 /**
42  * Structure contains the callback function and control options
43  */
44 struct CallbackData
45 {
46
47   /**
48    * Constructor
49    */
50   CallbackData( CallbackBase* callback, bool hasReturnValue )
51   :  mCallback( callback ),
52      mRemoveFromContainerFunction( NULL ),
53      mIdler( NULL ),
54      mIdleEnterer( NULL ),
55      mHasReturnValue( hasReturnValue )
56   {
57   }
58   /**
59    * Destructor
60    */
61   ~CallbackData()
62   {
63     delete mCallback;
64     delete mRemoveFromContainerFunction;
65   }
66
67   CallbackBase*                   mCallback;       ///< call back
68   CallbackBase*                   mRemoveFromContainerFunction; ///< Called to remove the callbackdata from the callback container
69   Ecore_Idler*                    mIdler;          ///< ecore idler
70   Ecore_Idle_Enterer*             mIdleEnterer;    ///< ecore idle enterer
71   bool                            mHasReturnValue; ///< true if the callback function has a return value.
72 };
73
74 namespace
75 {
76
77 /**
78  * Called from the main thread while idle.
79  */
80 Eina_Bool IdleCallback(void *data)
81 {
82   Eina_Bool ret = ECORE_CALLBACK_CANCEL;    // CALLBACK Cancel will delete the idler so we don't need to call ecore_idler_del
83   CallbackData *callbackData = static_cast< CallbackData * >( data );
84
85   if( callbackData->mHasReturnValue )
86   {
87     // run the function
88     bool retValue = CallbackBase::ExecuteReturn< bool >( *callbackData->mCallback );
89     if( retValue )
90     {
91       // keep the callback
92       ret = ECORE_CALLBACK_RENEW;
93     }
94     else
95     {
96       // remove callback data from the container
97       CallbackBase::Execute( *callbackData->mRemoveFromContainerFunction, callbackData );
98
99       // delete our data
100       delete callbackData;
101     }
102   }
103   else
104   {
105     // remove callback data from the container
106     CallbackBase::Execute( *callbackData->mRemoveFromContainerFunction, callbackData );
107
108     // run the function
109     CallbackBase::Execute( *callbackData->mCallback );
110
111     // delete our data
112     delete callbackData;
113   }
114
115   return ret;
116 }
117
118 } // unnamed namespace
119
120 EcoreCallbackManager::EcoreCallbackManager()
121 :mRunning(false)
122 {
123 }
124
125
126 void EcoreCallbackManager::Start()
127 {
128   DALI_ASSERT_DEBUG( mRunning == false );
129
130   mRunning = true;
131 }
132
133 void EcoreCallbackManager::Stop()
134 {
135   // make sure we're not called twice
136   DALI_ASSERT_DEBUG( mRunning == true );
137
138   RemoveAllCallbacks();
139
140   mRunning = false;
141
142 }
143
144 bool EcoreCallbackManager::AddIdleCallback( CallbackBase* callback, bool hasReturnValue )
145 {
146   if( !mRunning )
147   {
148     return false;
149   }
150
151   CallbackData* callbackData = new CallbackData( callback, hasReturnValue );
152
153   callbackData->mRemoveFromContainerFunction =  MakeCallback( this, &EcoreCallbackManager::RemoveCallbackFromContainer );
154
155   // add the call back to the container
156   mCallbackContainer.push_front(callbackData);
157
158   // add the idler
159   callbackData->mIdler = ecore_idler_add( IdleCallback, callbackData);
160
161   DALI_ASSERT_ALWAYS( ( callbackData->mIdler != NULL ) && "Idle method not created" );
162
163   return true;
164 }
165
166 void EcoreCallbackManager::RemoveIdleCallback( CallbackBase* callback )
167 {
168   for( CallbackList::iterator it = mCallbackContainer.begin(),
169          endIt = mCallbackContainer.end();
170        it != endIt;
171        ++it )
172   {
173     CallbackData* data = *it;
174
175     if( data->mCallback == callback )
176     {
177       // remove callback data from the container.
178       CallbackBase::Execute( *data->mRemoveFromContainerFunction, data );
179
180       ecore_idler_del( data->mIdler );
181     }
182   }
183 }
184
185 bool EcoreCallbackManager::AddIdleEntererCallback( CallbackBase* callback )
186 {
187   if( !mRunning )
188   {
189     return false;
190   }
191
192   CallbackData* callbackData = new CallbackData( callback, true );
193
194   callbackData->mRemoveFromContainerFunction = MakeCallback( this, &EcoreCallbackManager::RemoveCallbackFromContainer );
195
196   // add the call back to the container
197   mCallbackContainer.push_front( callbackData );
198
199   // add the idler
200   callbackData->mIdleEnterer = ecore_idle_enterer_add( IdleCallback, callbackData );
201
202   DALI_ASSERT_ALWAYS( ( callbackData->mIdleEnterer != NULL ) && "Idle method not created" );
203
204   return true;
205 }
206
207 void EcoreCallbackManager::RemoveIdleEntererCallback( CallbackBase* callback )
208 {
209   for( CallbackList::iterator it = mCallbackContainer.begin(),
210          endIt = mCallbackContainer.end();
211        it != endIt;
212        ++it )
213   {
214     CallbackData* data = *it;
215
216     if( data->mCallback == callback )
217     {
218       // remove callback data from the container.
219       CallbackBase::Execute( *data->mRemoveFromContainerFunction, data );
220
221       ecore_idle_enterer_del( data->mIdleEnterer );
222     }
223   }
224 }
225
226 void EcoreCallbackManager::RemoveCallbackFromContainer(CallbackData *callbackData)
227 {
228   mCallbackContainer.remove(callbackData);
229 }
230
231 void EcoreCallbackManager::RemoveAllCallbacks()
232 {
233   // always called from main thread
234   for( CallbackList::iterator  iter =  mCallbackContainer.begin(); iter != mCallbackContainer.end(); ++iter)
235   {
236     CallbackData* data = (*iter);
237
238     if( data->mIdler )
239     {
240       ecore_idler_del( data->mIdler );
241     }
242     else if( data->mIdleEnterer )
243     {
244       ecore_idle_enterer_del( data->mIdleEnterer );
245     }
246
247     delete data;
248   }
249   mCallbackContainer.clear();
250 }
251
252 // Creates a concrete interface for CallbackManager
253 CallbackManager* CallbackManager::New()
254 {
255   return new EcoreCallbackManager;
256 }
257
258 } // namespace Adaptor
259
260 } // namespace Internal
261
262 } // namespace Dali
263
264 #pragma GCC diagnostic pop