Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / animations / FUiAnim_EflLayer.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        FUiAnim_EflLayer.cpp
20  * @brief       This file contains implementation of _EflLayer class
21  *
22  * This file contains implementation _EflLayer class.
23  */
24
25 #include <X11/Xlib.h>
26 #include <Ecore_X.h>
27 #include <Elementary.h>
28
29 #include <FBaseErrors.h>
30 #include <FBaseSysLog.h>
31
32 #include <FGrpFloatRectangle.h>
33 #include "FUiAnim_NativeLayer.h"
34 #include "FUiAnim_EflLayer.h"
35 #include "FUiAnim_EflNode.h"
36 #include "FUiAnim_RootVisualElement.h"
37 #include "FUiAnim_AnimationManager.h"
38 #include "FUiAnim_DisplayManager.h"
39 #include "FUi_Math.h"
40
41
42 using namespace Tizen;
43 using namespace Tizen::Graphics;
44 using namespace Tizen::Ui;
45 using namespace Tizen::Ui::Animations;
46
47 #define _NEED_DAMAGE_HANDER_
48
49 //#define PRINT printf
50 #define PRINT(...)
51
52
53
54
55 namespace
56 {
57 #define __UNUSED__
58 #ifdef VE_VSYNC_UPDATE
59
60 Ecore_Idle_Enterer* __pOnIdleLoopIterator = null;
61
62
63 //static const double fpsLimitInterval = 1.0 / 55.0;
64
65 Eina_Bool
66 OnIdleLoopIterate(void* pData)
67 {
68         _DisplayManager* pDisplayManager = _DisplayManager::GetInstance();
69
70 //      PRINT("OnIdleLoopIterate()\n");
71
72
73         if (!pDisplayManager)
74         {
75                 return ECORE_CALLBACK_CANCEL; // for remove callback
76         }
77
78         Tizen::Ui::Animations::_AnimationManager* pAnimationManager = Tizen::Ui::Animations::_AnimationManager::GetInstance();
79
80         if (!pAnimationManager)
81         {
82                 return ECORE_CALLBACK_CANCEL; // for remove callback
83         }
84
85         //CHECK ME : how about the performance?
86 //      double currentTime = ecore_time_get();
87 //      static double prevFlushTime = 0;
88
89 //      if (currentTime - prevFlushTime >= fpsLimitInterval * 0.99)
90         {
91                 pAnimationManager->ProcessAnimationTick();
92
93 //              prevFlushTime = currentTime;
94
95                 pDisplayManager->RenderAll();
96
97                 pDisplayManager->Flush();
98         }
99
100         return ECORE_CALLBACK_RENEW;
101 }
102
103 // WARNING: Without this, idle-enterer will be called after evas destroyed which may cause crash while accessing ecore-evas.
104 void
105 OnEcoreEvasFree(Ecore_Evas* pEcoreEvas)
106 {
107         ecore_evas_manual_render_set(pEcoreEvas, EINA_FALSE);
108 }
109 #endif
110
111
112 #ifdef _NEED_DAMAGE_HANDER_
113
114 Eina_Bool
115 OnXWindowDamaged(void* pData __UNUSED__, int type __UNUSED__, void* pEventInfo)
116 {
117 #if 1
118         _Ecore_X_Event_Window_Damage* pEvent = (_Ecore_X_Event_Window_Damage*)pEventInfo;
119
120         if (pData)
121         {
122                 _EflLayer* pLayer = (_EflLayer*)pData;
123
124                 if (pLayer->GetEvas() && pLayer->GetEcoreEvas() && pEvent->win == ecore_evas_window_get(pLayer->GetEcoreEvas()))
125                 {
126                         FloatRectangle bounds = pLayer->GetBounds();
127
128                         evas_damage_rectangle_add(pLayer->GetEvas(), 0, 0, (int)bounds.width, (int)bounds.height);
129                         pLayer->SetEvasRenderNeeded();
130
131                         _DisplayManager::GetInstance()->AddWakeUpEvent();
132
133                         PRINT("OnXWindowDamaged(%p)[%d,%d,%d,%d]------------\n", pLayer->GetEvas(), pEvent->x, pEvent->y, pEvent->w, pEvent->h);
134                 }
135         }
136 #endif
137         return EINA_TRUE;
138 }
139
140 Eina_Bool
141 OnXWindowConfigured(void* pData, int type, void* pEventInfo)
142 {
143 #if 0
144         _Ecore_X_Event_Window_Configure* pEvent = (_Ecore_X_Event_Window_Configure*)pEventInfo;
145
146         if (pData)
147         {
148                 _EflLayer* pLayer = (_EflLayer*)pData;
149
150                 if (pLayer->GetEvas() && pLayer->GetEcoreEvas() && pEvent->win == ecore_evas_window_get(pLayer->GetEcoreEvas()))
151                 {
152                         FloatRectangle bounds = pLayer->GetBounds();
153
154                         evas_damage_rectangle_add(pLayer->GetEvas(), 0, 0, (int)bounds.width, (int)bounds.height);
155                         pLayer->SetEvasRenderNeeded();
156
157                         _DisplayManager::GetInstance()->AddWakeUpEvent();
158
159                         PRINT("OnXWindowConfigured(%p)[%d,%d,%d,%d]------------\n", pLayer->GetEvas(), pEvent->x, pEvent->y, pEvent->w, pEvent->h);
160                 }
161         }
162 #endif
163
164         return EINA_TRUE;
165 }
166
167 Eina_Bool
168 OnXWindowHidden(void* pData, int type, void* pEventInfo)
169 {
170         _Ecore_X_Event_Window_Hide* pEvent = (_Ecore_X_Event_Window_Hide*)pEventInfo;
171
172         if (!pData)
173         {
174                 return EINA_TRUE;
175         }
176
177         _EflLayer* pLayer = (_EflLayer*)pData;
178         PRINT("############ Hidden (%p, 0x%x) \n" , pLayer, pEvent->win);
179
180         if (pLayer->GetEvas() && pLayer->GetEcoreEvas() && pEvent->win == ecore_evas_window_get(pLayer->GetEcoreEvas()))
181         {
182                 PRINT("############ Hidden (%p) -> EventDone() \n" , pData);
183                 pLayer->SetVisibilityChangeCompleted();
184                 _DisplayManager::GetInstance()->AddWakeUpEvent();
185         }
186
187         return EINA_TRUE;
188 }
189
190 Eina_Bool
191 OnXWindowShown(void* pData, int type, void* pEventInfo)
192 {
193         _Ecore_X_Event_Window_Show* pEvent = (_Ecore_X_Event_Window_Show*)pEventInfo;
194
195         if (!pData)
196         {
197                 return EINA_TRUE;
198         }
199
200         _EflLayer* pLayer = (_EflLayer*)pData;
201         PRINT("############ Shown (%p, 0x%x) \n" , pLayer, pEvent->win);
202
203         if (pLayer->GetEvas() && pLayer->GetEcoreEvas() && pEvent->win == ecore_evas_window_get(pLayer->GetEcoreEvas()))
204         {
205                 PRINT("############ Shown (%p) -> EventDone() \n" , pData);
206
207                 FloatRectangle bounds = pLayer->GetBounds();
208
209                 evas_damage_rectangle_add(pLayer->GetEvas(), 0, 0, (int)bounds.width, (int)bounds.height);
210
211                 pLayer->SetVisibilityChangeCompleted();
212                 _DisplayManager::GetInstance()->AddWakeUpEvent();
213         }
214
215         return EINA_TRUE;
216 }
217
218 #endif
219
220 void
221 PreRenderCallback(Ecore_Evas* ee)
222 {
223         _EflLayer* pEflLayer = (_EflLayer*)ecore_evas_data_get(ee, "EflLayer");
224
225         if (pEflLayer && pEflLayer->GetRootVisualElement())
226         {
227 #ifndef VE_VSYNC_UPDATE
228                 static double loopTime = 0;
229                 double prevLoopTime = loopTime;
230                 loopTime = ecore_loop_time_get();
231                 if (loopTime != prevLoopTime)
232                 {
233                         _AnimationManager::GetInstance()->ProcessAnimationTick();
234                 }
235 #endif
236
237                 _DisplayManager::GetInstance()->Render(*pEflLayer->GetRootVisualElement());
238         }
239 }
240
241 void
242 PostRenderCallback(Ecore_Evas* ee)
243 {
244         _EflLayer* pEflLayer = (_EflLayer*)ecore_evas_data_get(ee, "EflLayer");
245
246         if (pEflLayer && pEflLayer->GetRootVisualElement())
247         {
248                 _DisplayManager::GetInstance()->PostRender(*pEflLayer->GetRootVisualElement());
249         }
250 }
251
252 }
253
254 namespace Tizen { namespace Ui { namespace Animations
255 {
256
257 int _EflLayer::_countOfLayer = 0;
258
259 _EflLayer::_EflLayer(void)
260         : _pRootVisualElement(null)
261         , _pEvas(null)
262         , _pEcoreEvas(null)
263         , _pWindow(null)
264         , _pOnWindowDamagedHandler(null)
265         , _pOnWindowConfiguredHandler(null)
266         , _pOnWindowHideHandler(null)
267         , _pOnWindowShowHandler(null)
268         , _needEvasRender(0)
269         , _needShowStateChangeRequest(false)
270         , _isShow(false)
271         , _isVisibilityChangeInProgress(false)
272         , _needAsyncVisibilityChangeRequest(true)
273 {
274         _countOfLayer++;
275 }
276
277
278 _EflLayer::~_EflLayer(void)
279 {
280         _countOfLayer--;
281 #ifdef VE_VSYNC_UPDATE
282         ecore_evas_manual_render_set(_pEcoreEvas, EINA_FALSE);
283
284         if(_countOfLayer <= 0)
285         {
286                 ecore_idle_enterer_del(__pOnIdleLoopIterator);
287                 __pOnIdleLoopIterator = null;
288
289         }
290 #ifdef _NEED_DAMAGE_HANDER_
291         if (_pOnWindowDamagedHandler)
292         {
293                 ecore_event_handler_del(_pOnWindowDamagedHandler);
294                 _pOnWindowDamagedHandler = null;
295         }
296
297         if (_pOnWindowConfiguredHandler)
298         {
299                 ecore_event_handler_del(_pOnWindowConfiguredHandler);
300                 _pOnWindowConfiguredHandler = null;
301         }
302         if (_pOnWindowHideHandler)
303         {
304                 ecore_event_handler_del(_pOnWindowHideHandler);
305                 _pOnWindowHideHandler = null;
306         }
307
308         if (_pOnWindowShowHandler)
309         {
310                 ecore_event_handler_del(_pOnWindowShowHandler);
311                 _pOnWindowShowHandler = null;
312         }
313 #endif
314
315 #endif
316
317
318         if (_pEcoreEvas)
319         {
320                 ecore_evas_callback_pre_render_set(_pEcoreEvas, null);
321                 ecore_evas_callback_post_render_set(_pEcoreEvas, null);
322                 _pEcoreEvas = null;
323         }
324
325         if (_pWindow)
326         {
327                 evas_object_del(_pWindow);
328         }
329         _pWindow = null;
330         _pEvas = null;
331
332 }
333
334 result
335 _EflLayer::OnConstructed(void)
336 {
337         //Ecore_X_Window window = 0;
338
339         if (_pWindow)
340         {
341                 return E_OBJ_ALREADY_EXIST;
342         }
343
344         _pWindow = elm_win_add(NULL, NULL, ELM_WIN_BASIC);
345
346         SysTryReturnResult(NID_UI, _pWindow, E_SYSTEM, "A system error has been occurred.");
347
348         result r = Initialize(_pWindow);
349         if (r != E_SUCCESS)
350         {
351                 evas_object_del(_pWindow);
352                 return E_SYSTEM;
353         }
354
355         Ecore_X_Window window = (Ecore_X_Window) ecore_evas_window_get(_pEcoreEvas);
356         SysTryReturnResult(NID_UI, window != 0,E_SYSTEM, "A system error has been occurred.");
357
358 #ifdef VE_VSYNC_UPDATE
359         ecore_x_vsync_animator_tick_source_set(window);
360         ecore_evas_manual_render_set(_pEcoreEvas, EINA_TRUE);
361         ecore_evas_callback_pre_free_set(_pEcoreEvas, OnEcoreEvasFree);
362 #endif
363
364         ecore_x_netwm_window_type_set(window, ECORE_X_WINDOW_TYPE_NORMAL);
365         ecore_x_e_virtual_keyboard_state_set(window, (Ecore_X_Virtual_Keyboard_State)ELM_WIN_KEYBOARD_UNKNOWN);
366
367         return E_SUCCESS;
368 }
369
370
371 result
372 _EflLayer::Initialize(Evas_Object* pWindow)
373 {
374         _pWindow = pWindow;
375         SysTryCatch(NID_UI, _pWindow, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred.");
376         _pEvas = evas_object_evas_get(_pWindow);
377         SysTryCatch(NID_UI, _pEvas, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred.");
378         _pEcoreEvas = ecore_evas_ecore_evas_get(_pEvas);
379         SysTryCatch(NID_UI, _pEcoreEvas, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred.");
380
381 // CHECK ME: Is this needed for GL mode?
382 #ifdef _NEED_DAMAGE_HANDER_
383         if(_pOnWindowDamagedHandler == null)
384         {
385                 _pOnWindowDamagedHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE, OnXWindowDamaged, this);
386         }
387
388         if (_pOnWindowConfiguredHandler == null)
389         {
390                 _pOnWindowConfiguredHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, OnXWindowConfigured, this);
391         }
392
393         if (_pOnWindowHideHandler == null)
394         {
395                 _pOnWindowHideHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, OnXWindowHidden, this);
396         }
397
398         if (_pOnWindowShowHandler == null)
399         {
400                 _pOnWindowShowHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, OnXWindowShown, this);
401         }
402
403 #endif
404
405 #ifdef VE_VSYNC_UPDATE
406         if(__pOnIdleLoopIterator == null)
407         {
408                 __pOnIdleLoopIterator = ecore_idle_enterer_add(OnIdleLoopIterate, null);
409         }
410 #else
411         ecore_evas_callback_pre_render_set(_pEcoreEvas, PreRenderCallback);
412         ecore_evas_callback_post_render_set(_pEcoreEvas, PostRenderCallback);
413 #endif
414
415         ecore_evas_data_set(_pEcoreEvas, "EflLayer", this);
416
417         return E_SUCCESS;
418
419 CATCH:
420         _pWindow = null;
421         _pEcoreEvas = null;
422         _pEvas = null;
423         _pRootVisualElement = null;
424         return E_SYSTEM;
425 }
426
427 result
428 _EflLayer::Configure(_RootVisualElement& rootElement)
429 {
430         _EflNode* pNode = dynamic_cast<_EflNode*>(rootElement.GetNativeNode());
431         if (pNode)
432         {
433                 _pRootVisualElement = &rootElement;
434
435                 return pNode->ReConstruct(*this);
436         }
437
438         return E_SYSTEM;
439 }
440
441 result
442 _EflLayer::SetBounds(const FloatRectangle& bounds)
443 {
444         if (_pWindow)
445         {
446                 evas_object_move(_pWindow, bounds.x, bounds.y);
447                 evas_object_resize(_pWindow, bounds.width, bounds.height);
448         }
449         return E_SUCCESS;
450 }
451
452 FloatRectangle
453 _EflLayer::GetBounds(void) const
454 {
455         if (_pWindow)
456         {
457                 int x = 0;
458                 int y = 0;
459                 int w = 0;
460                 int h = 0;
461                 evas_object_geometry_get(_pWindow, &x, &y, &w, &h);
462
463                 return FloatRectangle(x, y, w, h);
464         }
465
466         return FloatRectangle();
467 }
468
469 result
470 _EflLayer::SetShowState(bool show)
471 {
472 #ifdef ECORE_EVAS_ASYNC_VISIBILITY_BUG_HACK
473         if (_isShow == show)
474         {
475                 return E_SUCCESS;
476         }
477
478         if (_needShowStateChangeRequest)
479         {
480                 // Show State is not applied yet. Need cancel the visibility change request.
481                 _needShowStateChangeRequest = false;
482                 PRINT("Cancel SetShowState request (%d)\n", show);
483         }
484         else
485         {
486                 _needShowStateChangeRequest = true;
487                 _DisplayManager::GetInstance()->AddWakeUpEvent();
488                 PRINT("SetShowState request (%d)\n", show);
489         }
490
491         _isShow = show;
492 #else
493         if (_pWindow)
494         {
495                 if (show)
496                 {
497                         evas_object_show(_pWindow);
498                 }
499                 else
500                 {
501                         evas_object_hide(_pWindow);
502                 }
503         }
504 #endif
505
506         return E_SUCCESS;
507 }
508
509 bool
510 _EflLayer::GetShowState(void) const
511 {
512         return _isShow;
513 }
514
515 void
516 _EflLayer::SetOpacity(float opacity)
517 {
518         if (!_pWindow)
519                 return;
520
521         if (opacity > 1.0f)
522         {
523                 opacity = 1.0f;
524         }
525         else if(opacity<0.0f)
526         {
527                 opacity = 0.0f;
528         }
529
530         if (_FloatCompare(opacity, 1.0f))
531         {
532                 ecore_evas_alpha_set(_pEcoreEvas, EINA_FALSE);
533                 int r,g,b,a;
534                 evas_object_color_get(_pWindow, &r, &g, &b, &a);
535                 evas_object_color_set(_pWindow, r, g, b, 255);
536
537         }
538         else if (opacity < 1.0f)
539         {
540
541                 ecore_evas_alpha_set(_pEcoreEvas, EINA_TRUE);
542
543                 int r,g,b,a;
544                 evas_object_color_get(_pWindow, &r, &g, &b, &a);
545                 a = opacity*255;
546                 evas_object_color_set(_pWindow, r, g, b, a);
547         }
548 }
549
550 float
551 _EflLayer::GetOpacity(void)
552 {
553         if (!_pWindow)
554                         return 0.0f;
555
556         int r,g,b,a;
557         evas_object_color_get(_pWindow, &r, &g, &b, &a);
558         if (a > 255)
559                 return 1.0f;
560
561         return a / 255.0f;
562
563 }
564
565 void
566 _EflLayer::Flush(void)
567 {
568         if (_pEcoreEvas)
569         {
570                 PRINT("Flush StateChange(%p) - is Pending(%d) \n",this , _isVisibilityChangeInProgress);
571
572                 if (_needShowStateChangeRequest && (!_needAsyncVisibilityChangeRequest || !_isVisibilityChangeInProgress))
573                 {
574                         if (_isShow)
575                         {
576                                 evas_object_show(_pWindow);
577
578                                 // QUICK-DIRTY HACK TO BE REMOVED !!!
579 #ifdef ECORE_EVAS_ASYNC_VISIBILITY_BUG_HACK
580                                 ecore_x_sync();
581                                 ecore_x_flush();
582                                 usleep(30 * 1000);
583
584                                 FloatRectangle bounds = GetBounds();
585                                 evas_damage_rectangle_add(_pEvas, 0, 0, (int)bounds.width, (int)bounds.height);
586 #endif
587
588                                 PRINT("evas_object_show(%p) \n", this);
589                         }
590                         else
591                         {
592                                 evas_object_hide(_pWindow);
593                                 PRINT("evas_object_hide(%p) \n", this);
594                         }
595
596                         _isVisibilityChangeInProgress = true;
597                         _needShowStateChangeRequest = false;
598                 }
599
600                 if (_needEvasRender > 0)
601                 {
602                         _DisplayManager::GetInstance()->AddWakeUpEvent();
603                         _needEvasRender--;
604                 }
605
606
607                 ecore_evas_manual_render(_pEcoreEvas);
608         }
609
610 #if 0
611         if (_pEvas)
612         {
613                 if(show)
614                 {
615                         evas_render_idle_flush(_pEvas);
616                 }
617                 else
618                 {
619                         evas_render(_pEvas);
620                 }
621         }
622 #endif
623 }
624
625
626 }}}             // Tizen::Ui::Animations
627