Fix wrong log formats
[platform/core/appfw/ui-gadget-1.git] / src / manager.c
1 /*
2  *  UI Gadget
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <glib.h>
27 #include <Elementary.h>
28
29 #ifndef UG_WAYLAND
30 #include <X11/Xatom.h>
31 #include <X11/Xutil.h>
32 #include <Ecore_X.h>
33 #else
34 #include <Ecore_Wayland.h>
35 #endif
36
37 #include <Ecore.h>
38
39 #include "ug.h"
40 #include "ug-manager.h"
41 #include "ug-engine.h"
42 #include "ug-dbg.h"
43
44 #define Idle_Cb Ecore_Cb
45
46 #define ugman_idler_add(func, data)  \
47         ecore_job_add((Ecore_Cb) func, (void *)data);
48
49 #ifdef ENABLE_UG_CREATE_CB
50 typedef void (*fn_ug_trace_cb)(char *ug, char *mem, char *parent, void *user_data);
51 fn_ug_trace_cb g_create_cb;
52 void *g_create_cb_user_data;
53 #endif
54
55 struct ug_manager {
56         ui_gadget_h root;
57         ui_gadget_h fv_top;
58         GSList *fv_list;
59
60         void *win;
61
62 #ifndef UG_WAYLAND
63         Window win_id;
64         Display *disp;
65 #endif
66
67         enum ug_option base_opt;
68         enum ug_event last_rotate_evt;
69
70         int walking;
71
72         int is_initted:1;
73         int is_landscape:1;
74         int destroy_all:1;
75
76         struct ug_engine *engine;
77 };
78
79 static struct ug_manager ug_man;
80
81 static inline void job_start(void);
82 static inline void job_end(void);
83
84 static int ug_relation_add(ui_gadget_h p, ui_gadget_h c)
85 {
86         c->parent = p;
87         /* prepend element to avoid the inefficiency,
88                 which is to traverse the entire list to find the end*/
89         p->children = g_slist_prepend(p->children, c);
90
91         return 0;
92 }
93
94 static int ug_relation_del(ui_gadget_h ug)
95 {
96         ui_gadget_h p;
97
98         p = ug->parent;
99         if (!p) {
100                 _WRN("ug_relation_del failed: no parent");
101                 return -1;
102         }
103
104         if (p->children)
105                 p->children = g_slist_remove(p->children, ug);
106
107         if (ug->children) {
108                 g_slist_free(ug->children);
109                 ug->children = NULL;
110         }
111
112         ug->parent = NULL;
113
114         return 0;
115 }
116
117 static int ug_fvlist_add(ui_gadget_h c)
118 {
119         ug_man.fv_list = g_slist_prepend(ug_man.fv_list, c);
120         ug_man.fv_top = c;
121
122         return 0;
123 }
124
125 static int ug_fvlist_del(ui_gadget_h c)
126 {
127         ui_gadget_h t;
128
129         ug_man.fv_list = g_slist_remove(ug_man.fv_list, c);
130
131         /* update fullview top ug*/
132         t = g_slist_nth_data(ug_man.fv_list, 0);
133         ug_man.fv_top = t;
134
135         return 0;
136 }
137
138 #ifndef UG_WAYLAND
139 static int __ug_x_get_window_property(Display *dpy, Window win, Atom atom,
140                                           Atom type, unsigned int *val,
141                                           unsigned int len)
142 {
143         unsigned char *prop_ret;
144         Atom type_ret;
145         unsigned long bytes_after;
146         unsigned long  num_ret;
147         int format_ret;
148         unsigned int i;
149         int num;
150
151         prop_ret = NULL;
152         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
153                                type, &type_ret, &format_ret, &num_ret,
154                                &bytes_after, &prop_ret) != Success)
155                 return -1;
156
157         if (type_ret != type || format_ret != 32)
158                 num = -1;
159         else if (num_ret == 0 || !prop_ret)
160                 num = 0;
161         else {
162                 if (num_ret < len)
163                         len = num_ret;
164                 for (i = 0; i < len; i++)
165                         val[i] = ((unsigned long *)prop_ret)[i];
166                 num = len;
167         }
168
169         if (prop_ret)
170                 XFree(prop_ret);
171
172         return num;
173 }
174 #endif
175
176 #ifndef UG_WAYLAND
177 static enum ug_event __ug_x_rotation_get(Display *dpy, Window win)
178 {
179         Window active_win;
180         Window root_win;
181         int rotation = -1;
182         int ret = -1;
183         enum ug_event func_ret;
184
185         Atom atom_active_win;
186         Atom atom_win_rotate_angle;
187
188         root_win = XDefaultRootWindow(dpy);
189
190         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
191         ret = __ug_x_get_window_property(dpy, root_win, atom_active_win,
192                                              XA_WINDOW,
193                                              (unsigned int *)&active_win, 1);
194         if (ret < 0) {
195                 func_ret = UG_EVENT_ROTATE_PORTRAIT;
196                 goto func_out;
197         }
198
199         atom_win_rotate_angle =
200                 XInternAtom(dpy, "_E_ILLUME_ROTATE_ROOT_ANGLE", False);
201         ret = __ug_x_get_window_property(dpy, root_win,
202                                           atom_win_rotate_angle, XA_CARDINAL,
203                                           (unsigned int *)&rotation, 1);
204
205         _DBG("x_rotation_get / ret(%d),degree(%d)", ret, rotation);
206
207         if (ret == -1)
208                 func_ret = UG_EVENT_ROTATE_PORTRAIT;
209         else {
210                 switch (rotation) {
211                 case 0:
212                         func_ret = UG_EVENT_ROTATE_PORTRAIT;
213                         break;
214                 case 90:
215                         func_ret = UG_EVENT_ROTATE_LANDSCAPE_UPSIDEDOWN;
216                         break;
217                 case 180:
218                         func_ret = UG_EVENT_ROTATE_PORTRAIT_UPSIDEDOWN;
219                         break;
220                 case 270:
221                         func_ret = UG_EVENT_ROTATE_LANDSCAPE;
222                         break;
223                 default:
224                         func_ret = UG_EVENT_ROTATE_PORTRAIT;
225                         break;
226                 }
227         }
228
229 func_out:
230         return func_ret;
231 }
232 #endif
233
234 static enum ug_event __ug_evas_rotation_get(Evas_Object *win)
235 {
236
237         int angle = elm_win_rotation_get(win);
238         enum ug_event func_ret;
239
240         _DBG("win angle : %d", angle);
241
242         switch (angle) {
243         case 0:
244                 func_ret = UG_EVENT_ROTATE_PORTRAIT;
245                 break;
246         case 90:
247                 func_ret = UG_EVENT_ROTATE_LANDSCAPE_UPSIDEDOWN;
248                 break;
249         case 180:
250                 func_ret = UG_EVENT_ROTATE_PORTRAIT_UPSIDEDOWN;
251                 break;
252         case 270:
253                 func_ret = UG_EVENT_ROTATE_LANDSCAPE;
254                 break;
255         default:
256                 func_ret = UG_EVENT_ROTATE_PORTRAIT;
257                 break;
258         }
259         return func_ret;
260 }
261
262 static void ugman_tree_dump(ui_gadget_h ug)
263 {
264         static int i;
265         int lv;
266         const char *name;
267         GSList *child;
268         ui_gadget_h c;
269
270         if (!ug)
271                 return;
272
273         name = ug->name;
274         if (ug == ug_man.root) {
275                 i = 0;
276                 _DBG("============== TREE_DUMP =============");
277                 _DBG("ROOT: Manager");
278                 name = "Manager";
279         }
280
281         child = ug->children;
282         if (!child)
283                 return;
284
285         i++;
286         lv = i;
287
288         while (child) {
289                 c = child->data;
290                 _DBG("[%d] %s [%c] (mem : %s) (ug : %p) (PARENT:  %s)",
291                      lv,
292                      c && c->name ? c->name : "NO CHILD INFO FIXIT!!!",
293                      c && c->mode == UG_MODE_FULLVIEW ? 'F' : 'f',
294                          c->module->addr, c, name);
295                 ugman_tree_dump(c);
296                 child = g_slist_next(child);
297         }
298 }
299
300 static int ugman_ug_free(ui_gadget_h ug)
301 {
302         if (!ug) {
303                 _ERR("ug free failed: Invalid ug");
304                 errno = EINVAL;
305                 return -1;
306         }
307
308         if (ug->module)
309                 ug_module_unload(ug->module);
310
311         if (ug->name) {
312                 free((void *)ug->name);
313                 ug->name = NULL;
314         }
315         if (ug->app_control) {
316                 app_control_destroy(ug->app_control);
317                 ug->app_control = NULL;
318         }
319         free(ug);
320         ug = NULL;
321         return 0;
322 }
323
324
325 static int ugman_ug_find(ui_gadget_h p, ui_gadget_h ug)
326 {
327         GSList *child = NULL;
328
329         if (!p || !ug)
330                 return 0;
331         child = p->children;
332
333         while (child) {
334                 if (child->data == ug)
335                         return 1;
336                 if (ugman_ug_find(child->data, ug))
337                         return 1;
338                 child = g_slist_next(child);
339         }
340
341         return 0;
342 }
343
344 static void ugman_ug_start(void *data)
345 {
346         ui_gadget_h ug = data;
347         struct ug_module_ops *ops = NULL;
348
349         if (!ug) {
350                 _ERR("ug is null");
351                 return;
352         } else if (ug->state != UG_STATE_CREATED) {
353                 _DBG("start cb will be not invoked because ug(%p) state(%d) is not created", ug, ug->state);
354                 return;
355         }
356
357         _DBG("ug=%p", ug);
358
359         ug->state = UG_STATE_RUNNING;
360
361         if (ug->module)
362                 ops = &ug->module->ops;
363
364         if (ops && ops->start)
365                 ops->start(ug, ug->app_control, ops->priv);
366
367         return;
368 }
369
370 static int ugman_ug_pause(void *data)
371 {
372         ui_gadget_h ug = data;
373         struct ug_module_ops *ops = NULL;
374         GSList *child = NULL;
375
376         if (!ug_man.is_initted) {
377                 _ERR("ugman_pause failed: manager is not initted");
378                 return -1;
379         }
380
381         if (!ug_man.root) {
382                 _WRN("ugman_pause failed: no root");
383                 return -1;
384         }
385
386         if (ug_man.destroy_all == 1) {
387                 _WRN("ugman_pause skipped : app is termanating with ug_destory_all");
388                 return -1;
389         }
390
391         if ((data != ug_man.root) && (!ugman_ug_find(ug_man.root, data))) {
392                 _WRN("ugman_pause skipped : invalid ug(%p)", data);
393                 return -1;
394         }
395
396         job_start();
397
398         if (!ug) {
399                 _WRN("ug pointer is null");
400                 goto end;
401         }
402
403         if (ug->children) {
404                 child = ug->children;
405                 while (child) {
406                         ugman_ug_pause(child->data);
407                         child = g_slist_next(child);
408                 }
409         }
410
411         if (ug->state != UG_STATE_RUNNING) {
412                 if (ug != ug_man.root)
413                         _WRN("ug(%p)->state : %d", ug, ug->state);
414                 goto end;
415         }
416
417         if (ug->module)
418                 ops = &ug->module->ops;
419
420         if (ops && ops->pause) {
421                 _DBG("call ug(%p) pause cb", ug);
422                 ops->pause(ug, ug->app_control, ops->priv);
423         }
424
425         ug->state = UG_STATE_STOPPED;
426
427  end:
428         job_end();
429         return 0;
430 }
431
432 static int ugman_ug_resume(void *data)
433 {
434         ui_gadget_h ug = data;
435         struct ug_module_ops *ops = NULL;
436         GSList *child = NULL;
437
438         if (!ug_man.is_initted) {
439                 _ERR("ugman_resume failed: manager is not initted");
440                 return -1;
441         }
442
443         if (!ug_man.root) {
444                 _WRN("ugman_resume failed: no root");
445                 return -1;
446         }
447
448         if (ug_man.destroy_all == 1) {
449                 _WRN("ugman_resume skipped : app is termanating with ug_destory_all");
450                 return -1;
451         }
452
453         if ((data != ug_man.root) && (!ugman_ug_find(ug_man.root, data))) {
454                 _WRN("ugman_resume skipped : invalid ug(%p)", data);
455                 return -1;
456         }
457
458         job_start();
459
460         if (!ug) {
461                 _WRN("ug pointer is null");
462                 goto end;
463         }
464
465         if (ug->children) {
466                 child = ug->children;
467                 while (child) {
468                         ugman_ug_resume(child->data);
469                         child = g_slist_next(child);
470                 }
471         }
472
473         if (ug->state != UG_STATE_STOPPED) {
474                 if (ug != ug_man.root)
475                         _WRN("ug(%p)->state : %d", ug, ug->state);
476         }
477
478         switch (ug->state) {
479         case UG_STATE_CREATED:
480                 ugman_ug_start(ug);
481                 goto end;
482         case UG_STATE_STOPPED:
483                 break;
484         default:
485                 goto end;
486         }
487
488         if (ug->module)
489                 ops = &ug->module->ops;
490
491         if (ops && ops->resume) {
492                 _DBG("call ug(%p) resume cb", ug);
493                 ops->resume(ug, ug->app_control, ops->priv);
494         }
495
496         ug->state = UG_STATE_RUNNING;
497
498  end:
499         job_end();
500         return 0;
501 }
502
503 #ifdef UG_WAYLAND
504 static void _ugman_enable_indicator(Evas_Object *win, int enable)
505 {
506         Ecore_Wl_Window *wlwin = elm_win_wl_window_get(win);
507
508         if (enable == 1)
509                 ecore_wl_window_indicator_state_set(wlwin, ECORE_WL_INDICATOR_STATE_ON);
510         else
511                 ecore_wl_window_indicator_state_set(wlwin, ECORE_WL_INDICATOR_STATE_OFF);
512 }
513
514 static int _ugman_get_indicator_state(Evas_Object *win)
515 {
516         Ecore_Wl_Window *wlwin = elm_win_wl_window_get(win);
517         Ecore_Wl_Indicator_State state;
518         int ret;
519
520         state = ecore_wl_window_indicator_state_get(wlwin);
521         if (state == ECORE_WL_INDICATOR_STATE_OFF)
522                 ret = 0;
523         else if (state == ECORE_WL_INDICATOR_STATE_ON)
524                 ret = 1;
525         else
526                 ret = -1;
527
528         return ret;
529 }
530 #endif
531
532 static int ugman_indicator_update(enum ug_option opt, enum ug_event event)
533 {
534 #ifndef UG_WAYLAND
535         _ERR("controlling indicator is disabled");
536 #else
537         int enable;
538         int cur_state;
539
540         cur_state = _ugman_get_indicator_state(ug_man.win);
541
542         _DBG("indicator update opt(%d) cur_state(%d)", opt, cur_state);
543
544         switch (opt) {
545 #ifndef ENABLE_UG_HANDLE_INDICATOR_HIDE
546         case UG_OPT_INDICATOR_ENABLE:
547         case UG_OPT_INDICATOR_PORTRAIT_ONLY:
548         case UG_OPT_INDICATOR_LANDSCAPE_ONLY:
549         case UG_OPT_INDICATOR_DISABLE:
550                 enable = 1;
551                 break;
552 #else
553         case UG_OPT_INDICATOR_ENABLE:
554                 if (event == UG_EVENT_NONE)
555                         enable = 1;
556                 else
557                         enable = cur_state ? 1 : 0;
558                 break;
559         case UG_OPT_INDICATOR_PORTRAIT_ONLY:
560                 enable = ug_man.is_landscape ? 0 : 1;
561                 break;
562         case UG_OPT_INDICATOR_LANDSCAPE_ONLY:
563                 enable = ug_man.is_landscape ? 1 : 0;
564                 break;
565         case UG_OPT_INDICATOR_DISABLE:
566                 enable = 0;
567                 break;
568 #endif
569         case UG_OPT_INDICATOR_MANUAL:
570                 return 0;
571         default:
572                 _ERR("update failed: Invalid opt(%d)", opt);
573                 return -1;
574         }
575
576         if (cur_state != enable) {
577                 _DBG("set indicator status as %d", enable);
578                 _ugman_enable_indicator(ug_man.win, enable);
579         }
580
581 #endif
582         return 0;
583 }
584
585 static int ugman_ug_getopt(ui_gadget_h ug)
586 {
587         if (!ug)
588                 return -1;
589
590         /* Indicator Option */
591         if (ug->mode == UG_MODE_FULLVIEW)
592                 ugman_indicator_update(ug->opt, UG_EVENT_NONE);
593
594         return 0;
595 }
596
597 static int ugman_ug_event(ui_gadget_h ug, enum ug_event event)
598 {
599         struct ug_module_ops *ops = NULL;
600         GSList *child = NULL;
601
602         if (!ug)
603                 return 0;
604
605         if (ug->children) {
606                 child = ug->children;
607                 while (child) {
608                         ugman_ug_event(child->data, event);
609                         child = g_slist_next(child);
610                 }
611         }
612
613         if (ug->module)
614                 ops = &ug->module->ops;
615
616         _DBG("ug_event_cb : ug(%p) / event(%d)", ug, event);
617
618         if (ops && ops->event)
619                 ops->event(ug, event, ug->app_control, ops->priv);
620
621         return 0;
622 }
623
624 static int ugman_ug_destroy(void *data)
625 {
626         ui_gadget_h ug = data;
627         struct ug_module_ops *ops = NULL;
628         struct ug_cbs *cbs;
629
630         job_start();
631
632         if (!ug)
633                 goto end;
634
635         _DBG("ug(%p) state(%d)", ug, ug->state);
636
637         switch (ug->state) {
638         case UG_STATE_CREATED:
639         case UG_STATE_RUNNING:
640         case UG_STATE_STOPPED:
641         case UG_STATE_DESTROYING:
642         case UG_STATE_PENDING_DESTROY:
643                 break;
644         default:
645                 _WRN("ug(%p) state is already destroyed", ug);
646                 goto end;
647         }
648
649         ug->state = UG_STATE_DESTROYED;
650
651         if ((ug != ug_man.root) && (ug->layout) &&
652                 (ug->mode == UG_MODE_FULLVIEW) &&
653                 (ug->layout_state != UG_LAYOUT_DESTROY)) {
654                 /* ug_destroy_all case */
655                 struct ug_engine_ops *eng_ops = NULL;
656
657                 if (ug_man.engine)
658                         eng_ops = &ug_man.engine->ops;
659
660                 if (eng_ops && eng_ops->destroy)
661                         eng_ops->destroy(ug, NULL, NULL);
662         }
663
664         if (ug->module)
665                 ops = &ug->module->ops;
666
667         if (ops && ops->destroy) {
668                 _DBG("ug(%p) module destory cb call", ug);
669                 ops->destroy(ug, ug->app_control, ops->priv);
670         }
671
672         cbs = &ug->cbs;
673         if (cbs && cbs->end_cb) {
674                 _DBG("ug(%p) end cb will be invoked", ug);
675                 cbs->end_cb(ug, cbs->priv);
676         }
677
678         if ((ug->parent) && (ug->parent->state == UG_STATE_PENDING_DESTROY)) {
679                 if ((ug->parent->children) && (g_slist_length(ug->parent->children) == 1)) {
680                         _WRN("pended parent ug(%p) destroy job is added to loop", ug->parent);
681                         ugman_idler_add((Idle_Cb)ugman_ug_destroy, ug->parent);
682                 } else {
683                         _WRN("pended parent ug(%p) will be destroyed after another children is destroyed", ug->parent);
684                 }
685         } else {
686                 if (ug->parent)
687                         _DBG("ug parent(%p) state(%d)", ug->parent, ug->parent->state);
688                 else
689                         _WRN("ug parent is null");
690         }
691
692         if (ug != ug_man.root)
693                 ug_relation_del(ug);
694
695         if (ug->mode == UG_MODE_FULLVIEW) {
696                 if (ug_man.fv_top == ug) {
697                         ug_fvlist_del(ug);
698                         if (!ug_man.destroy_all)
699                                 ugman_ug_getopt(ug_man.fv_top);
700                 } else {
701                         ug_fvlist_del(ug);
702                 }
703         }
704
705         _DBG("free ug(%p)", ug);
706         ugman_ug_free(ug);
707
708         if (ug_man.root == ug)
709                 ug_man.root = NULL;
710
711         ugman_tree_dump(ug_man.root);
712  end:
713         job_end();
714
715         return 0;
716 }
717
718 static void ug_hide_end_cb(void *data)
719 {
720         ui_gadget_h ug = data;
721         if (ug->children) {
722                 _WRN("child ug is still destroying. parent ug(%p) will be destroyed later", ug);
723                 ug->state = UG_STATE_PENDING_DESTROY;
724         } else {
725                 ugman_idler_add((Idle_Cb)ugman_ug_destroy, (void *)ug);
726         }
727 }
728
729 static int ugman_ug_create(void *data)
730 {
731         ui_gadget_h ug = data;
732         struct ug_module_ops *ops = NULL;
733         struct ug_cbs *cbs;
734         struct ug_engine_ops *eng_ops = NULL;
735         void *conformant = NULL;
736
737
738         if (!ug || ug->state != UG_STATE_READY) {
739                 _ERR("ug(%p) input param error", ug);
740                 return -1;
741         }
742
743         ug->state = UG_STATE_CREATED;
744
745         if (ug->module)
746                 ops = &ug->module->ops;
747
748         if (ug_man.engine)
749                 eng_ops = &ug_man.engine->ops;
750
751         if (ops && ops->create) {
752                 ug->layout = ops->create(ug, ug->mode, ug->app_control, ops->priv);
753                 if (!ug->layout) {
754                         _ERR("ug(%p) layout is null", ug);
755                         return -1;
756                 }
757                 if (ug->mode == UG_MODE_FULLVIEW) {
758                         if (eng_ops && eng_ops->create) {
759                                 conformant = eng_ops->create(ug_man.win, ug, ugman_ug_start);
760                                 if (!conformant) {
761                                         _ERR("conformant(%p) error. ug(%p) destory cb is invoked.",
762                                                         conformant, ug);
763                                         ops->destroy(ug, ug->app_control, ops->priv);
764                                         return -1;
765                                 }
766                         }
767                 }
768                 cbs = &ug->cbs;
769
770                 if (cbs && cbs->layout_cb)
771                         cbs->layout_cb(ug, ug->mode, cbs->priv);
772
773                 _DBG("after caller layout cb call");
774                 ugman_indicator_update(ug->opt, UG_EVENT_NONE);
775         }
776
777         if (ug_man.last_rotate_evt == UG_EVENT_NONE) {
778 #ifndef UG_WAYLAND
779                 ug_man.last_rotate_evt = __ug_x_rotation_get(ug_man.disp, ug_man.win_id);
780 #else
781                 ug_man.last_rotate_evt = __ug_evas_rotation_get((Evas_Object *)ug_man.win);
782 #endif
783         }
784         ugman_ug_event(ug, ug_man.last_rotate_evt);
785
786         if (ug->mode == UG_MODE_FRAMEVIEW)
787                 ugman_ug_start(ug);
788
789         ugman_tree_dump(ug_man.root);
790
791 #ifdef ENABLE_UG_CREATE_CB
792         if (g_create_cb) {
793                 ui_gadget_h parent = ug->parent;
794
795                 _DBG("invoke trace create cb(%p)", g_create_cb);
796
797                 g_create_cb((char *)ug->name,
798                                 ug->module ? (char *)ug->module->addr : NULL,
799                                 parent ? (char *)parent->name : NULL,
800                                 g_create_cb_user_data);
801         }
802 #endif
803
804
805         return 0;
806 }
807
808 static ui_gadget_h ugman_root_ug_create(void)
809 {
810         ui_gadget_h ug;
811
812         ug = calloc(1, sizeof(struct ui_gadget_s));
813         if (!ug) {
814                 _ERR("ug root create failed: Memory allocation failed");
815                 return NULL;
816         }
817
818         ug->mode = UG_MODE_FULLVIEW;
819         ug->state = UG_STATE_RUNNING;
820         ug->children = NULL;
821
822         return ug;
823 }
824
825 int ugman_ug_add(ui_gadget_h parent, ui_gadget_h ug)
826 {
827         if (!ug_man.is_initted) {
828                 _ERR("failed: manager is not initialized");
829                 return -1;
830         }
831
832         if (!ug_man.root) {
833                 if (parent) {
834                         _ERR("failed: parent has to be NULL w/o root");
835                         errno = EINVAL;
836                         return -1;
837                 }
838
839                 ug_man.root = ugman_root_ug_create();
840                 if (!ug_man.root) {
841                         _ERR("failed : ug root create fail");
842                         return -1;
843                 }
844                 ug_man.root->opt = ug_man.base_opt;
845                 ug_man.root->layout = ug_man.win;
846                 ug_fvlist_add(ug_man.root);
847         }
848
849         if (!parent) {
850                 parent = ug_man.root;
851         } else {
852                 switch (parent->state) {
853                 case UG_STATE_DESTROYING:
854                 case UG_STATE_PENDING_DESTROY:
855                 case UG_STATE_DESTROYED:
856                         _WRN("parent(%p) state(%d) error", parent, parent->state);
857                         return -1;
858                 default:;
859                 }
860         }
861
862         if (ug_relation_add(parent, ug)) {
863                 _ERR("failed : ug_relation_add fail");
864                 return -1;
865         }
866
867         if (ugman_ug_create(ug) == -1) {
868                 _ERR("failed : ugman_ug_create fail");
869                 ug_relation_del(ug);
870                 return -1;
871         }
872         if (ug->mode == UG_MODE_FULLVIEW)
873                 ug_fvlist_add(ug);
874
875         return 0;
876 }
877
878 ui_gadget_h ugman_ug_load(ui_gadget_h parent,
879                                 const char *name,
880                                 enum ug_mode mode,
881                                 app_control_h app_control, struct ug_cbs *cbs)
882 {
883         int r;
884         ui_gadget_h ug;
885
886         ug = calloc(1, sizeof(struct ui_gadget_s));
887         if (!ug) {
888                 _ERR("ug_create() failed: Memory allocation failed");
889                 return NULL;
890         }
891
892         ug->module = ug_module_load(name);
893         if (!ug->module) {
894                 _ERR("ug_create() failed: Module loading failed");
895                 goto load_fail;
896         }
897
898         ug->name = strdup(name);
899
900         ug->mode = mode;
901         app_control_clone(&ug->app_control, app_control);
902         ug->opt = ug->module->ops.opt;
903         ug->state = UG_STATE_READY;
904         ug->children = NULL;
905
906         if (cbs)
907                 memcpy(&ug->cbs, cbs, sizeof(struct ug_cbs));
908
909         r = ugman_ug_add(parent, ug);
910         if (r) {
911                 _ERR("ugman ug add failed");
912                 goto load_fail;
913         }
914
915         return ug;
916
917  load_fail:
918         ugman_ug_free(ug);
919         return NULL;
920 }
921
922 int ugman_ug_destroying(ui_gadget_h ug)
923 {
924         struct ug_module_ops *ops = NULL;
925
926         _DBG("ugman_ug_destroying start ug(%p)", ug);
927
928         if (!ug || !ugman_ug_exist(ug)) {
929                 _ERR("ugman_ug_destroying failed: Invalid ug");
930                 errno = EINVAL;
931                 return -1;
932         }
933
934         switch (ug->state) {
935         case UG_STATE_DESTROYING:
936         case UG_STATE_PENDING_DESTROY:
937         case UG_STATE_DESTROYED:
938                 _WRN("ug(%p) state(%d) is already on destroying", ug, ug->state);
939                 return 0;
940         default:
941                 break;
942         }
943
944         ug->destroy_me = 1;
945         ug->state = UG_STATE_DESTROYING;
946
947         if (ug->module)
948                 ops = &ug->module->ops;
949
950         if (ops && ops->destroying)
951                 ops->destroying(ug, ug->app_control, ops->priv);
952
953         return 0;
954 }
955
956 int ugman_ug_del(ui_gadget_h ug)
957 {
958         struct ug_engine_ops *eng_ops = NULL;
959
960         _DBG("ugman_ug_del start ug(%p)", ug);
961
962         if (!ug || !ugman_ug_exist(ug)) {
963                 _ERR("ugman_ug_del failed: Invalid ug");
964                 errno = EINVAL;
965                 return -1;
966         }
967
968         switch (ug->state) {
969         case UG_STATE_DESTROYING:
970         case UG_STATE_PENDING_DESTROY:
971         case UG_STATE_DESTROYED:
972                 _WRN("ug(%p) state(%d) is already on destroying", ug, ug->state);
973                 return 0;
974         default:
975                 break;
976         }
977
978         if (ug->destroy_me) {
979                 _WRN("ugman_ug_del failed: ug is alreay on destroying");
980                 return -1;
981         }
982
983         if (!ug_man.is_initted) {
984                 _WRN("ugman_ug_del failed: manager is not initialized");
985                 return -1;
986         }
987
988         if (!ug_man.root) {
989                 _ERR("ugman_ug_del failed: no root");
990                 return -1;
991         }
992
993         if (ug->children) {
994                 GSList *child, *trail;
995
996                 child = ug->children;
997                 _DBG("ugman_ug_del ug(%p) has child(%p)", ug, child->data);
998                 while (child) {
999                         trail = g_slist_next(child);
1000                         ugman_ug_del(child->data);
1001                         child = trail;
1002                 }
1003         }
1004
1005         ugman_ug_destroying(ug);
1006
1007         /* pre call for indicator update time issue */
1008         bool is_update = false;
1009         ui_gadget_h t = NULL;
1010         if (ug_man.fv_top == ug) {
1011                 is_update = true;
1012                 t = g_slist_nth_data(ug_man.fv_list, 1);
1013         } else {
1014                 if (ug->children) {
1015                         GSList *child;
1016                         child = g_slist_last(ug->children);
1017                         if (ug_man.fv_top == (ui_gadget_h)child->data) {
1018                                 is_update = true;
1019                                 t = g_slist_nth_data(ug_man.fv_list,
1020                                         g_slist_index(ug_man.fv_list, (gconstpointer)ug) + 1);
1021                         }
1022                 }
1023         }
1024
1025         if ((is_update) && (t))
1026                 ugman_ug_getopt(t);
1027
1028         if (ug_man.engine)
1029                 eng_ops = &ug_man.engine->ops;
1030
1031         if (ug->mode == UG_MODE_FULLVIEW) {
1032                 if (eng_ops && eng_ops->destroy)
1033                         eng_ops->destroy(ug, ug_man.fv_top, ug_hide_end_cb);
1034                 else
1035                         ugman_idler_add((Idle_Cb)ugman_ug_destroy, ug);
1036         } else {
1037                 _DBG("ug(%p) mode is frameview", ug);
1038                 ug_hide_end_cb(ug);
1039         }
1040
1041         _DBG("ugman_ug_del(%p) end", ug);
1042
1043         return 0;
1044 }
1045
1046
1047 int ugman_ug_del_child(ui_gadget_h ug)
1048 {
1049         GSList *child, *trail;
1050
1051         if (ug->children) {
1052                 child = ug->children;
1053                 _DBG("ug destroy all. ug(%p) has child(%p)", ug, child->data);
1054                 while (child) {
1055                         trail = g_slist_next(child);
1056                         ugman_ug_del_child(child->data);
1057                         child = trail;
1058                 }
1059         }
1060
1061         ugman_ug_destroy(ug);
1062
1063         return 0;
1064 }
1065
1066 static void ugman_ug_unset_content(void)
1067 {
1068         struct ug_engine_ops *eng_ops = NULL;
1069
1070         if (ug_man.engine) {
1071                 eng_ops = &ug_man.engine->ops;
1072         } else {
1073                 _WRN("ui engine is not loaded");
1074                 return;
1075         }
1076
1077         if (eng_ops && eng_ops->create)
1078                 eng_ops->request(ug_man.win, NULL, UG_UI_REQ_UNSET_CONTENT);
1079         else
1080                 _WRN("ui engine is not loaded");
1081
1082         return;
1083 }
1084
1085 int ugman_ug_del_all(void)
1086 {
1087         /*  Terminate */
1088         if (!ug_man.is_initted) {
1089                 _ERR("ugman_ug_del_all failed: manager is not initialized");
1090                 return -1;
1091         }
1092
1093         if (!ug_man.root) {
1094                 _ERR("ugman_ug_del_all failed: no root");
1095                 return -1;
1096         }
1097
1098         _DBG("ug_del_all. root(%p) walking(%d) ", ug_man.root, ug_man.walking);
1099
1100         if (ug_man.walking > 0) {
1101                 ug_man.destroy_all = 1;
1102         } else {
1103                 ugman_ug_unset_content();
1104                 ugman_ug_del_child(ug_man.root);
1105         }
1106
1107         return 0;
1108 }
1109
1110 #ifndef UG_WAYLAND
1111 int ugman_init(Display *disp, Window xid, void *win, enum ug_option opt)
1112 {
1113         ug_man.win = win;
1114         ug_man.disp = disp;
1115         ug_man.win_id = xid;
1116         ug_man.base_opt = opt;
1117         ug_man.last_rotate_evt = UG_EVENT_NONE;
1118
1119         if (!ug_man.is_initted)
1120                 ug_man.engine = ug_engine_load();
1121
1122         ug_man.is_initted = 1;
1123
1124         return 0;
1125 }
1126 #else
1127 int ugman_init(void *win, enum ug_option opt)
1128 {
1129         ug_man.win = win;
1130         ug_man.base_opt = opt;
1131         ug_man.last_rotate_evt = UG_EVENT_NONE;
1132
1133         if (!ug_man.is_initted)
1134                 ug_man.engine = ug_engine_load();
1135
1136         ug_man.is_initted = 1;
1137
1138         return 0;
1139 }
1140 #endif
1141
1142 int ugman_init_efl(Evas_Object *win, enum ug_option opt)
1143 {
1144 #ifndef UG_WAYLAND
1145         Ecore_X_Window xwin = elm_win_xwindow_get(win);
1146         if (xwin)
1147                 return ugman_init((Display *)ecore_x_display_get(), xwin, win, opt);
1148 #else
1149         return ugman_init(win, opt);
1150 #endif
1151         return -1;
1152 }
1153
1154 int ugman_resume(void)
1155 {
1156         /* RESUME */
1157         if (!ug_man.is_initted) {
1158                 _ERR("ugman_resume failed: manager is not initialized");
1159                 return -1;
1160         }
1161
1162         if (!ug_man.root) {
1163                 _WRN("ugman_resume failed: no root");
1164                 return -1;
1165         }
1166
1167         if (ug_man.destroy_all == 1) {
1168                 _WRN("ugman_resume skip : app is termanating with ug_destory_all");
1169                 return 0;
1170         }
1171
1172         _DBG("ugman_resume called");
1173
1174         ugman_idler_add((Idle_Cb)ugman_ug_resume, ug_man.root);
1175
1176         return 0;
1177 }
1178
1179 int ugman_resume_ug(ui_gadget_h ug)
1180 {
1181         if (!ug_man.is_initted) {
1182                 _ERR("ugman_pause_ug failed: manager is not initialized");
1183                 return -1;
1184         }
1185
1186         if (!ug_man.root || !ug) {
1187                 _WRN("ugman_pause_ug failed: no root");
1188                 return -1;
1189         }
1190
1191         _DBG("ugman_resume_ug called");
1192
1193         ugman_idler_add((Idle_Cb)ugman_ug_resume, ug);
1194
1195         return 0;
1196 }
1197
1198 int ugman_pause(void)
1199 {
1200         /* PAUSE (Background) */
1201         if (!ug_man.is_initted) {
1202                 _ERR("ugman_pause failed: manager is not initialized");
1203                 return -1;
1204         }
1205
1206         if (!ug_man.root) {
1207                 _WRN("ugman_pause failed: no root");
1208                 return -1;
1209         }
1210
1211         if (ug_man.destroy_all == 1) {
1212                 _WRN("ugman_pause skip : app is termanating with ug_destory_all");
1213                 return 0;
1214         }
1215
1216         _DBG("ugman_pause called");
1217
1218         ugman_idler_add((Idle_Cb)ugman_ug_pause, ug_man.root);
1219
1220         return 0;
1221 }
1222
1223 int ugman_pause_ug(ui_gadget_h ug)
1224 {
1225         if (!ug_man.is_initted) {
1226                 _ERR("ugman_pause_ug failed: manager is not initialized");
1227                 return -1;
1228         }
1229
1230         if (!ug_man.root || !ug) {
1231                 _WRN("ugman_pause_ug failed: no root");
1232                 return -1;
1233         }
1234
1235         _DBG("ugman_pause_ug called");
1236
1237         ugman_idler_add((Idle_Cb)ugman_ug_pause, ug);
1238
1239         return 0;
1240 }
1241
1242 static int ugman_send_event_pre(void *data)
1243 {
1244         job_start();
1245
1246         ugman_ug_event(ug_man.root, (enum ug_event)data);
1247
1248         job_end();
1249
1250         return 0;
1251 }
1252
1253 int ugman_send_event(enum ug_event event)
1254 {
1255         int is_rotation = 1;
1256
1257         /* Propagate event */
1258         if (!ug_man.is_initted) {
1259                 _ERR("ugman_send_event failed: manager is not initialized");
1260                 return -1;
1261         }
1262
1263         if (!ug_man.root) {
1264                 _WRN("ugman_send_event failed: no root");
1265                 return -1;
1266         }
1267
1268         /* In case of rotation, indicator state has to be updated */
1269         switch (event) {
1270         case UG_EVENT_ROTATE_PORTRAIT:
1271         case UG_EVENT_ROTATE_PORTRAIT_UPSIDEDOWN:
1272                 ug_man.last_rotate_evt = event;
1273                 ug_man.is_landscape = 0;
1274                 break;
1275         case UG_EVENT_ROTATE_LANDSCAPE:
1276         case UG_EVENT_ROTATE_LANDSCAPE_UPSIDEDOWN:
1277                 ug_man.last_rotate_evt = event;
1278                 ug_man.is_landscape = 1;
1279                 break;
1280         default:
1281                 is_rotation = 0;
1282         }
1283
1284         ugman_idler_add((Idle_Cb)ugman_send_event_pre, (void *)event);
1285
1286         if (is_rotation && ug_man.fv_top)
1287                 ugman_indicator_update(ug_man.fv_top->opt, event);
1288
1289         return 0;
1290 }
1291
1292 static int ugman_send_key_event_to_ug(ui_gadget_h ug,
1293                                       enum ug_key_event event)
1294 {
1295         struct ug_module_ops *ops = NULL;
1296
1297         if (!ug)
1298                 return -1;
1299
1300         if (ug->module)
1301                 ops = &ug->module->ops;
1302         else
1303                 return -1;
1304
1305         if (ops && ops->key_event)
1306                 ops->key_event(ug, event, ug->app_control, ops->priv);
1307
1308         return 0;
1309 }
1310
1311 int ugman_send_key_event(enum ug_key_event event)
1312 {
1313         if (!ug_man.is_initted) {
1314                 _ERR("ugman_send_key_event failed: manager is not initialized");
1315                 return -1;
1316         }
1317
1318         if (!ug_man.fv_top || !ugman_ug_exist(ug_man.fv_top)
1319             || ug_man.fv_top->state == UG_STATE_DESTROYED) {
1320                 _ERR("ugman_send_key_event failed: full view top UG is invalid");
1321                 return -1;
1322         }
1323
1324         return ugman_send_key_event_to_ug(ug_man.fv_top, event);
1325 }
1326
1327 int ugman_send_message(ui_gadget_h ug, app_control_h msg)
1328 {
1329         struct ug_module_ops *ops = NULL;
1330         if (!ug || !ugman_ug_exist(ug) || ug->state == UG_STATE_DESTROYED) {
1331                 _ERR("ugman_send_message failed: Invalid ug(%p)", ug);
1332                 errno = EINVAL;
1333                 return -1;
1334         }
1335
1336         if (!msg) {
1337                 _ERR("ugman_send_message failed: Invalid msg");
1338                 errno = EINVAL;
1339                 return -1;
1340         }
1341
1342         if (ug->module)
1343                 ops = &ug->module->ops;
1344
1345         if (ops && ops->message)
1346                 ops->message(ug, msg, ug->app_control, ops->priv);
1347
1348         return 0;
1349 }
1350
1351 void *ugman_get_window(void)
1352 {
1353         return ug_man.win;
1354 }
1355
1356 void *ugman_get_conformant(void)
1357 {
1358         struct ug_engine_ops *eng_ops = NULL;
1359         void* ret = NULL;
1360
1361         if (ug_man.engine) {
1362                 eng_ops = &ug_man.engine->ops;
1363         } else {
1364                 _WRN("ui engine is not loaded");
1365                 return NULL;
1366         }
1367
1368         if (eng_ops && eng_ops->create)
1369                 ret = eng_ops->request(ug_man.win, NULL, UG_UI_REQ_GET_CONFORMANT);
1370         else
1371                 _WRN("ui engine is not loaded");
1372
1373         return ret;
1374 }
1375
1376 static inline void job_start(void)
1377 {
1378         ug_man.walking++;
1379 }
1380
1381 static inline void job_end(void)
1382 {
1383         ug_man.walking--;
1384
1385         if (!ug_man.walking && ug_man.destroy_all) {
1386                 ug_man.destroy_all = 0;
1387                 if (ug_man.root) {
1388                         _DBG("ug_destroy_all pneding job exist. ug_destroy_all begin");
1389                         ugman_ug_del_all();
1390                 }
1391         }
1392
1393         if (ug_man.walking < 0)
1394                 ug_man.walking = 0;
1395 }
1396
1397 int ugman_ug_exist(ui_gadget_h ug)
1398 {
1399         return ugman_ug_find(ug_man.root, ug);
1400 }
1401
1402 #ifdef ENABLE_UG_CREATE_CB
1403 int ugman_create_cb(void (*create_cb)(char *, char *, char *, void *), void *user_data)
1404 {
1405         if (create_cb == NULL) {
1406                 _DBG("disable trace create cb");
1407                 g_create_cb_user_data = NULL;
1408                 g_create_cb = NULL;
1409         } else {
1410                 _DBG("enable trace create cb(%p)", create_cb);
1411                 g_create_cb_user_data = user_data;
1412                 g_create_cb = create_cb;
1413         }
1414
1415         return 0;
1416 }
1417 #endif