Resolved the AppWidgetLayer crash
[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 Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0/
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         , _isMainType(true)
274         , _needRender(true)
275         , __isWinObject(true)
276 {
277         _countOfLayer++;
278 }
279
280 _EflLayer::_EflLayer(bool isMainType)
281         : _pRootVisualElement(null)
282         , _pEvas(null)
283         , _pEcoreEvas(null)
284         , _pWindow(null)
285         , _pOnWindowDamagedHandler(null)
286         , _pOnWindowConfiguredHandler(null)
287         , _pOnWindowHideHandler(null)
288         , _pOnWindowShowHandler(null)
289         , _needEvasRender(0)
290         , _needShowStateChangeRequest(false)
291         , _isShow(false)
292         , _isVisibilityChangeInProgress(false)
293         , _needAsyncVisibilityChangeRequest(true)
294         , _isMainType(isMainType)
295         , _needRender(true)
296         , __isWinObject(true)
297 {
298         _countOfLayer++;
299 }
300
301 _EflLayer::~_EflLayer(void)
302 {
303         _countOfLayer--;
304 #ifdef VE_VSYNC_UPDATE
305         ecore_evas_manual_render_set(_pEcoreEvas, EINA_FALSE);
306
307         if(_countOfLayer <= 0)
308         {
309                 ecore_idle_enterer_del(__pOnIdleLoopIterator);
310                 __pOnIdleLoopIterator = null;
311
312         }
313 #ifdef _NEED_DAMAGE_HANDER_
314         if (_pOnWindowDamagedHandler)
315         {
316                 ecore_event_handler_del(_pOnWindowDamagedHandler);
317                 _pOnWindowDamagedHandler = null;
318         }
319
320         if (_pOnWindowConfiguredHandler)
321         {
322                 ecore_event_handler_del(_pOnWindowConfiguredHandler);
323                 _pOnWindowConfiguredHandler = null;
324         }
325         if (_pOnWindowHideHandler)
326         {
327                 ecore_event_handler_del(_pOnWindowHideHandler);
328                 _pOnWindowHideHandler = null;
329         }
330
331         if (_pOnWindowShowHandler)
332         {
333                 ecore_event_handler_del(_pOnWindowShowHandler);
334                 _pOnWindowShowHandler = null;
335         }
336 #endif
337
338 #endif
339
340
341         if (_pEcoreEvas)
342         {
343                 ecore_evas_callback_pre_render_set(_pEcoreEvas, null);
344                 ecore_evas_callback_post_render_set(_pEcoreEvas, null);
345                 _pEcoreEvas = null;
346         }
347
348         if (_pWindow)
349         {
350                 evas_object_del(_pWindow);
351         }
352         _pWindow = null;
353         _pEvas = null;
354
355 }
356
357 result
358 _EflLayer::OnConstructed(void)
359 {
360         //Ecore_X_Window window = 0;
361
362         if (_pWindow)
363         {
364                 return E_OBJ_ALREADY_EXIST;
365         }
366
367         if(_isMainType)
368         {
369                 _pWindow = elm_win_add(NULL, NULL, ELM_WIN_BASIC);
370         }
371         else
372         {
373                 _pWindow = elm_win_add(NULL, NULL, ELM_WIN_UTILITY);
374         }
375
376         SysTryReturnResult(NID_UI, _pWindow, E_SYSTEM, "A system error has been occurred.");
377
378         result r = Initialize(_pWindow);
379         if (r != E_SUCCESS)
380         {
381                 evas_object_del(_pWindow);
382                 return E_SYSTEM;
383         }
384
385         Ecore_X_Window window = (Ecore_X_Window) ecore_evas_window_get(_pEcoreEvas);
386         SysTryReturnResult(NID_UI, window != 0,E_SYSTEM, "A system error has been occurred.");
387
388 #ifdef VE_VSYNC_UPDATE
389         ecore_x_vsync_animator_tick_source_set(window);
390         ecore_evas_manual_render_set(_pEcoreEvas, EINA_TRUE);
391         ecore_evas_callback_pre_free_set(_pEcoreEvas, OnEcoreEvasFree);
392 #endif
393
394         ecore_x_netwm_window_type_set(window, ECORE_X_WINDOW_TYPE_NORMAL);
395         ecore_x_e_virtual_keyboard_state_set(window, (Ecore_X_Virtual_Keyboard_State)ELM_WIN_KEYBOARD_UNKNOWN);
396
397         return E_SUCCESS;
398 }
399
400
401 result
402 _EflLayer::Initialize(Evas_Object* pWindow)
403 {
404         const char* pType = null;
405
406         _pWindow = pWindow;
407         SysTryCatch(NID_UI, _pWindow, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred.");
408         _pEvas = evas_object_evas_get(_pWindow);
409         SysTryCatch(NID_UI, _pEvas, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred.");
410         _pEcoreEvas = ecore_evas_ecore_evas_get(_pEvas);
411         SysTryCatch(NID_UI, _pEcoreEvas, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred.");
412
413         pType = evas_object_type_get(_pWindow);
414         if (strcmp("elm_win", pType))
415         {
416                 __isWinObject = false;
417         }
418
419 // CHECK ME: Is this needed for GL mode?
420 #ifdef _NEED_DAMAGE_HANDER_
421         if(_pOnWindowDamagedHandler == null)
422         {
423                 _pOnWindowDamagedHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE, OnXWindowDamaged, this);
424         }
425
426         if (_pOnWindowConfiguredHandler == null)
427         {
428                 _pOnWindowConfiguredHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, OnXWindowConfigured, this);
429         }
430
431         if (_pOnWindowHideHandler == null)
432         {
433                 _pOnWindowHideHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, OnXWindowHidden, this);
434         }
435
436         if (_pOnWindowShowHandler == null)
437         {
438                 _pOnWindowShowHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, OnXWindowShown, this);
439         }
440
441 #endif
442
443 #ifdef VE_VSYNC_UPDATE
444         if(__pOnIdleLoopIterator == null)
445         {
446                 __pOnIdleLoopIterator = ecore_idle_enterer_add(OnIdleLoopIterate, null);
447         }
448 #else
449         ecore_evas_callback_pre_render_set(_pEcoreEvas, PreRenderCallback);
450         ecore_evas_callback_post_render_set(_pEcoreEvas, PostRenderCallback);
451 #endif
452
453         ecore_evas_data_set(_pEcoreEvas, "EflLayer", this);
454
455         return E_SUCCESS;
456
457 CATCH:
458         _pWindow = null;
459         _pEcoreEvas = null;
460         _pEvas = null;
461         _pRootVisualElement = null;
462         return E_SYSTEM;
463 }
464
465 result
466 _EflLayer::Configure(_RootVisualElement& rootElement)
467 {
468         _EflNode* pNode = dynamic_cast<_EflNode*>(rootElement.GetNativeNode());
469         if (pNode)
470         {
471                 _pRootVisualElement = &rootElement;
472
473                 return pNode->ReConstruct(*this);
474         }
475
476         return E_SYSTEM;
477 }
478
479 result
480 _EflLayer::SetBounds(const FloatRectangle& bounds)
481 {
482         if (_pWindow)
483         {
484                 evas_object_move(_pWindow, bounds.x, bounds.y);
485                 evas_object_resize(_pWindow, bounds.width, bounds.height);
486         }
487         return E_SUCCESS;
488 }
489
490 FloatRectangle
491 _EflLayer::GetBounds(void) const
492 {
493         if (_pWindow)
494         {
495                 int x = 0;
496                 int y = 0;
497                 int w = 0;
498                 int h = 0;
499
500                 evas_object_geometry_get(_pWindow, null, null, &w, &h);
501
502                 if (__isWinObject == true)
503                 {
504                         elm_win_screen_position_get(_pWindow, &x, &y);
505                 }
506
507                 return FloatRectangle(x, y, w, h);
508         }
509
510         return FloatRectangle();
511 }
512
513 result
514 _EflLayer::SetShowState(bool show)
515 {
516 #ifdef ECORE_EVAS_ASYNC_VISIBILITY_BUG_HACK
517         if (_isShow == show)
518         {
519                 return E_SUCCESS;
520         }
521
522         if (_needShowStateChangeRequest)
523         {
524                 // Show State is not applied yet. Need cancel the visibility change request.
525                 _needShowStateChangeRequest = false;
526                 PRINT("Cancel SetShowState request (%d)\n", show);
527         }
528         else
529         {
530                 _needShowStateChangeRequest = true;
531                 _DisplayManager::GetInstance()->AddWakeUpEvent();
532                 PRINT("SetShowState request (%d)\n", show);
533         }
534
535         _isShow = show;
536 #else
537         if (_pWindow)
538         {
539                 if (show)
540                 {
541                         evas_object_show(_pWindow);
542                 }
543                 else
544                 {
545                         evas_object_hide(_pWindow);
546                 }
547         }
548 #endif
549
550         return E_SUCCESS;
551 }
552
553 bool
554 _EflLayer::GetShowState(void) const
555 {
556         return _isShow;
557 }
558
559 void
560 _EflLayer::SetOpacity(float opacity)
561 {
562         if (!_pWindow)
563                 return;
564
565         if (opacity > 1.0f)
566         {
567                 opacity = 1.0f;
568         }
569         else if(opacity<0.0f)
570         {
571                 opacity = 0.0f;
572         }
573
574         if (_FloatCompare(opacity, 1.0f))
575         {
576 //              ecore_evas_alpha_set(_pEcoreEvas, EINA_FALSE);
577                 if (__isWinObject == true)
578                 {
579                         elm_win_alpha_set(_pWindow, EINA_FALSE);
580                 }
581
582                 int r,g,b,a;
583                 evas_object_color_get(_pWindow, &r, &g, &b, &a);
584                 evas_object_color_set(_pWindow, r, g, b, 255);
585
586         }
587         else if (opacity < 1.0f)
588         {
589
590 //              ecore_evas_alpha_set(_pEcoreEvas, EINA_TRUE);
591                 if (__isWinObject == true)
592                 {
593                         elm_win_alpha_set(_pWindow, EINA_TRUE);
594                 }
595
596                 int r,g,b,a;
597                 evas_object_color_get(_pWindow, &r, &g, &b, &a);
598                 a = opacity*255;
599                 evas_object_color_set(_pWindow, r, g, b, a);
600         }
601 }
602
603 float
604 _EflLayer::GetOpacity(void)
605 {
606         if (!_pWindow)
607                         return 0.0f;
608
609         int r,g,b,a;
610         evas_object_color_get(_pWindow, &r, &g, &b, &a);
611         if (a > 255)
612                 return 1.0f;
613
614         return a / 255.0f;
615
616 }
617
618 void
619 _EflLayer::Flush(void)
620 {
621         if (_pEcoreEvas)
622         {
623                 PRINT("Flush StateChange(%p) - is Pending(%d) \n",this , _isVisibilityChangeInProgress);
624
625                 if (_needShowStateChangeRequest && (!_needAsyncVisibilityChangeRequest || !_isVisibilityChangeInProgress))
626                 {
627                         if (_isShow)
628                         {
629                                 evas_object_show(_pWindow);
630
631                                 // QUICK-DIRTY HACK TO BE REMOVED !!!
632 #ifdef ECORE_EVAS_ASYNC_VISIBILITY_BUG_HACK
633                                 ecore_x_sync();
634                                 ecore_x_flush();
635                                 usleep(30 * 1000);
636
637                                 FloatRectangle bounds = GetBounds();
638                                 evas_damage_rectangle_add(_pEvas, 0, 0, (int)bounds.width, (int)bounds.height);
639 #endif
640
641                                 PRINT("evas_object_show(%p) \n", this);
642                         }
643                         else
644                         {
645                                 evas_object_hide(_pWindow);
646                                 PRINT("evas_object_hide(%p) \n", this);
647                         }
648
649 #ifdef _NEED_DAMAGE_HANDER_
650                         _isVisibilityChangeInProgress = true;
651 #endif
652                         _needShowStateChangeRequest = false;
653                 }
654
655                 if (_needEvasRender > 0)
656                 {
657                         _DisplayManager::GetInstance()->AddWakeUpEvent();
658                         _needEvasRender--;
659                 }
660                 FloatRectangle rect = GetBounds();
661                 if(!_needRender)
662                 {
663                         PRINT("_needRender = false bounds(%f %f %f %f)\n", rect.x, rect.y, rect.width, rect.height);
664                         return;
665                 }
666
667                 PRINT("ecore_evas_manual_render bounds(%f %f %f %f)\n", rect.x, rect.y, rect.width, rect.height);
668
669                 ecore_evas_manual_render(_pEcoreEvas);
670         }
671
672 #if 0
673         if (_pEvas)
674         {
675                 if(show)
676                 {
677                         evas_render_idle_flush(_pEvas);
678                 }
679                 else
680                 {
681                         evas_render(_pEvas);
682                 }
683         }
684 #endif
685 }
686
687
688 }}}             // Tizen::Ui::Animations
689