3b55df6fc233a93beb221993bcec4d6cc62c7da1
[platform/core/appfw/app-core.git] / src / ui_base / appcore_ui_base.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
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 #define _GNU_SOURCE
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <stdarg.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <linux/limits.h>
28
29 #include <Ecore_Wayland.h>
30 #include <wayland-client.h>
31 #include <wayland-tbm-client.h>
32 #include <tizen-extension-client-protocol.h>
33
34 #include <Ecore.h>
35 #include <glib-object.h>
36 #include <malloc.h>
37 #include <glib.h>
38 #include <gio/gio.h>
39 #include <stdbool.h>
40 #include <aul.h>
41 #include <aul_svc.h>
42 #include <bundle_internal.h>
43 #include <ttrace.h>
44
45 #include "appcore_base.h"
46 #include "appcore_ui_base.h"
47 #include "appcore_ui_base_private.h"
48 #include "appcore_ui_plugin.h"
49
50 enum app_state {
51         AS_NONE,
52         AS_CREATED,
53         AS_RUNNING,
54         AS_PAUSED,
55         AS_DYING,
56 };
57
58 typedef struct _appcore_ui_base_context {
59         appcore_ui_base_ops ops;
60         void *data;
61         int argc;
62         char **argv;
63         unsigned int hint;
64         char *below_app;
65         char *appid;
66         bool bg_state;
67
68         int state;
69         Ecore_Event_Handler *hshow;
70         Ecore_Event_Handler *hhide;
71         Ecore_Event_Handler *hvchange;
72         Ecore_Event_Handler *hlower;
73         Ecore_Event_Handler *hpvchange;
74 } appcore_ui_base_context;
75
76
77 static bool b_active = false;
78 static bool first_launch = true;
79
80 struct win_node {
81         unsigned int win;
82         unsigned int surf;
83         bool bfobscured;
84 };
85
86 static GSList *g_winnode_list;
87 static appcore_ui_base_context __context;
88 static struct wl_display *dsp;
89 static struct wl_registry *reg;
90 static struct tizen_policy *tz_policy;
91
92 static void __wl_listener_cb(void *data, struct wl_registry *reg,
93                 uint32_t id, const char *interface, uint32_t ver)
94 {
95         if (interface && !strcmp(interface, "tizen_policy")) {
96                 if (!tz_policy)
97                         tz_policy = wl_registry_bind(reg, id,
98                                         &tizen_policy_interface, 1);
99         }
100 }
101
102 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
103                 unsigned int id)
104 {
105         /* do nothing */
106 }
107
108 static const struct wl_registry_listener reg_listener = {
109         __wl_listener_cb,
110         __wl_listener_remove_cb
111 };
112
113 static Eina_Bool __stub_show_cb(void *data, int type, void *event)
114 {
115         if (__context.ops.window.show)
116                 __context.ops.window.show(type, event, __context.data);
117
118         return ECORE_CALLBACK_RENEW;
119 }
120
121 static Eina_Bool __stub_hide_cb(void *data, int type, void *event)
122 {
123         if (__context.ops.window.hide)
124                 __context.ops.window.hide(type, event, __context.data);
125
126         return ECORE_CALLBACK_RENEW;
127 }
128
129 static Eina_Bool __stub_visibility_cb(void *data, int type, void *event)
130 {
131         if (__context.ops.window.visibility)
132                 __context.ops.window.visibility(type, event, __context.data);
133
134         return ECORE_CALLBACK_RENEW;
135 }
136
137 static Eina_Bool __stub_lower_cb(void *data, int type, void *event)
138 {
139         if (__context.ops.window.lower)
140                 __context.ops.window.lower(type, event, __context.data);
141
142         return ECORE_CALLBACK_RENEW;
143 }
144
145 static Eina_Bool __stub_pre_visibility_cb(void *data, int type, void *event)
146 {
147         if (__context.ops.window.pre_visibility)
148                 __context.ops.window.pre_visibility(type, event, __context.data);
149
150         return ECORE_CALLBACK_RENEW;
151 }
152
153 static void __prepare_to_suspend(void)
154 {
155         int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
156
157         if (appcore_base_is_bg_allowed() && !appcore_base_is_suspended()) {
158                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
159                 appcore_base_toggle_suspended_state();
160         }
161 }
162
163 static void __exit_from_suspend(void)
164 {
165         int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
166
167         if (appcore_base_is_suspended()) {
168                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
169                 appcore_base_toggle_suspended_state();
170         }
171 }
172
173 static void __do_pause(void)
174 {
175         if (__context.state == AS_RUNNING) {
176                 if (__context.ops.pause) {
177                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
178                         __context.ops.pause(__context.data);
179                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
180                 }
181
182                 __context.state = AS_PAUSED;
183                 __prepare_to_suspend();
184         }
185         aul_status_update(STATUS_BG);
186 }
187
188 static void __do_resume(void)
189 {
190         if (__context.state == AS_PAUSED || __context.state == AS_CREATED) {
191                 __exit_from_suspend();
192                 if (__context.ops.resume) {
193                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", __context.appid);
194                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
195                         __context.ops.resume(__context.data);
196                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
197                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", __context.appid);
198                 }
199                 if ((__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) &&
200                                 __context.below_app) {
201                         aul_app_group_activate_below(__context.below_app);
202                         free(__context.below_app);
203                         __context.below_app = NULL;
204                 }
205                 __context.state = AS_RUNNING;
206         }
207
208         aul_status_update(STATUS_VISIBLE);
209 }
210
211 static GSList *__find_win(unsigned int win)
212 {
213         GSList *iter;
214         struct win_node *t;
215
216         for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
217                 t = iter->data;
218                 if (t && t->win == win)
219                         return iter;
220         }
221
222         return NULL;
223 }
224
225 static int __get_main_window(void)
226 {
227         struct win_node *entry = NULL;
228
229         if (g_winnode_list != NULL) {
230                 entry = g_winnode_list->data;
231                 return (unsigned int) entry->win;
232         }
233
234         return 0;
235 }
236
237 static int __get_main_surface(void)
238 {
239         struct win_node *entry = NULL;
240
241         if (g_winnode_list != NULL) {
242                 entry = g_winnode_list->data;
243                 return (unsigned int) entry->surf;
244         }
245
246         return 0;
247 }
248
249 static bool __add_win(unsigned int win, unsigned int surf)
250 {
251         struct win_node *t;
252         GSList *f;
253
254         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
255
256         f = __find_win(win);
257         if (f) {
258                 errno = ENOENT;
259                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
260                 return FALSE;
261         }
262
263         t = calloc(1, sizeof(struct win_node));
264         if (t == NULL)
265                 return FALSE;
266
267         t->win = win;
268         t->surf = surf;
269         t->bfobscured = FALSE;
270
271         g_winnode_list = g_slist_append(g_winnode_list, t);
272
273         return TRUE;
274 }
275
276 static bool __delete_win(unsigned int win)
277 {
278         GSList *f;
279
280         f = __find_win(win);
281         if (!f) {
282                 errno = ENOENT;
283                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
284                                 win);
285                 return FALSE;
286         }
287
288         free(f->data);
289         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
290
291         return TRUE;
292 }
293
294 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
295 {
296         GSList *f;
297         struct win_node *t;
298
299         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
300              bfobscured);
301
302         f = __find_win(win);
303         if (!f) {
304                 errno = ENOENT;
305                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
306                 return FALSE;
307         }
308
309         t = (struct win_node *)f->data;
310         t->win = win;
311         if (surf != 0)
312                 t->surf = surf;
313         t->bfobscured = bfobscured;
314
315         return TRUE;
316 }
317
318 static void __raise_win(void)
319 {
320         Ecore_Wl_Window *win;
321         unsigned int win_id;
322
323         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
324                 return;
325
326         win_id = __get_main_window();
327
328         _DBG("Raise window: %d", win_id);
329         win = ecore_wl_window_find(win_id);
330         ecore_wl_window_activate(win);
331 }
332
333 static void __pause_win(void)
334 {
335         Ecore_Wl_Window *win;
336         GSList *wlist = g_winnode_list;
337         struct win_node *entry = NULL;
338
339         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
340                 return;
341
342         _DBG("Pause window");
343
344         while (wlist) {
345                 entry = wlist->data;
346
347                 _DBG("Pause window: %d", entry->win);
348                 win = ecore_wl_window_find(entry->win);
349                 ecore_wl_window_iconified_set(win, EINA_TRUE);
350
351                 wlist = wlist->next;
352         }
353 }
354
355 static int __init_wl(void)
356 {
357         _DBG("initialize wayland");
358         dsp = wl_display_connect(NULL);
359         if (dsp == NULL) {
360                 _ERR("Failed to connect wl display");
361                 return -1;
362         }
363
364         reg = wl_display_get_registry(dsp);
365         if (reg == NULL) {
366                 _ERR("Failed to get registry");
367                 wl_display_disconnect(dsp);
368                 return -1;
369         }
370
371         wl_registry_add_listener(reg, &reg_listener, NULL);
372         wl_display_roundtrip(dsp);
373
374         if (!tz_policy) {
375                 _ERR("Failed to get tizen policy interface");
376                 wl_registry_destroy(reg);
377                 wl_display_disconnect(dsp);
378                 return -1;
379         }
380
381         return 0;
382 }
383
384 static void __finish_wl(void)
385 {
386         if (tz_policy) {
387                 tizen_policy_destroy(tz_policy);
388                 tz_policy = NULL;
389         }
390
391         if (reg) {
392                 wl_registry_destroy(reg);
393                 reg = NULL;
394         }
395
396         if (dsp) {
397                 wl_display_disconnect(dsp);
398                 dsp = NULL;
399         }
400 }
401
402 static void __set_bg_state(void)
403 {
404         if (!tz_policy && __init_wl() < 0)
405                 return;
406
407         tizen_policy_set_background_state(tz_policy, getpid());
408         wl_display_roundtrip(dsp);
409         __context.bg_state = true;
410         _DBG("bg state: %d", __context.bg_state);
411 }
412
413 static void __unset_bg_state(void)
414 {
415         if (!tz_policy)
416                 return;
417
418         tizen_policy_unset_background_state(tz_policy, getpid());
419         wl_display_roundtrip(dsp);
420         __context.bg_state = false;
421         _DBG("bg state: %d", __context.bg_state);
422 }
423
424 static void __do_start(bundle *b)
425 {
426         const char *bg_launch;
427         const char *below_app;
428
429         if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) {
430                 if (__context.below_app) {
431                         free(__context.below_app);
432                         __context.below_app = NULL;
433                 }
434
435                 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
436                 if (below_app)
437                         __context.below_app = strdup(below_app);
438         }
439
440         if (first_launch) {
441                 first_launch = FALSE;
442                 return;
443         }
444
445         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
446                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
447                 if (bg_launch && strcmp(bg_launch, "enable") == 0) {
448                         if (!__context.bg_state &&
449                                         __context.state != AS_RUNNING)
450                                 __set_bg_state();
451                 } else {
452                         if (__context.bg_state)
453                                 __unset_bg_state();
454                 }
455         }
456
457         if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL) {
458                 if (!__context.bg_state)
459                         __raise_win();
460         }
461 }
462
463 static int __is_legacy_lifecycle(void)
464 {
465         static int is_legacy = -1;
466         const char *api_version;
467
468         if (is_legacy != -1)
469                 return is_legacy;
470
471         api_version = getenv("TIZEN_API_VERSION");
472         if (api_version) {
473                 if (strverscmp("2.4", api_version) > 0 &&
474                                 strverscmp("2.2.1", api_version) < 0)
475                         is_legacy = 1;
476                 else
477                         is_legacy = 0;
478         } else {
479                 is_legacy = 0;
480         }
481
482         return is_legacy;
483 }
484
485 EXPORT_API int appcore_ui_base_on_receive(aul_type type, bundle *b)
486 {
487         if (__context.state == AS_DYING) {
488                 _ERR("Skip the event in dying state");
489                 return 0;
490         }
491
492         if (type == AUL_TERMINATE_BGAPP && __context.state != AS_PAUSED)
493                 return 0;
494
495         if (type == AUL_START)
496                 __exit_from_suspend();
497
498         appcore_base_on_receive(type, b);
499
500         switch (type) {
501         case AUL_START:
502                 __do_start(b);
503                 if (__context.hint & APPCORE_UI_BASE_HINT_LEGACY_CONTROL) {
504                         if (!__context.bg_state && __is_legacy_lifecycle()) {
505                                 _DBG("Legacy lifecycle");
506                                 __do_resume();
507                         }
508                 }
509                 break;
510         case AUL_RESUME:
511                 if (__context.bg_state)
512                         __unset_bg_state();
513                 __raise_win();
514                 break;
515         case AUL_TERMINATE:
516                 break;
517         case AUL_TERMINATE_BGAPP:
518                 _DBG("[APP %d] is paused. TERMINATE", getpid());
519                 __context.state = AS_DYING;
520                 aul_status_update(STATUS_DYING);
521                 if (__context.ops.base.exit)
522                         __context.ops.base.exit(__context.data);
523                 break;
524         case AUL_PAUSE:
525                 __pause_win();
526                 break;
527         default:
528                 break;
529         }
530
531         return 0;
532 }
533
534 static void __add_ecore_events(void)
535 {
536         __context.hshow = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW,
537                         __stub_show_cb, NULL);
538         if (!__context.hshow)
539                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_SHOW event");
540
541         __context.hhide = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE,
542                         __stub_hide_cb, NULL);
543         if (!__context.hhide)
544                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_HIDE event");
545
546         __context.hvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
547                         __stub_visibility_cb, NULL);
548         if (!__context.hvchange)
549                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE event");
550
551         __context.hlower = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER,
552                         __stub_lower_cb, NULL);
553         if (!__context.hlower)
554                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_LOWER event");
555
556         __context.hpvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE,
557                         __stub_pre_visibility_cb, NULL);
558         if (!__context.hpvchange)
559                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE event");
560 }
561
562 static void __del_ecore_events(void)
563 {
564         if (__context.hshow) {
565                 ecore_event_handler_del(__context.hshow);
566                 __context.hshow = NULL;
567         }
568
569         if (__context.hhide) {
570                 ecore_event_handler_del(__context.hhide);
571                 __context.hhide = NULL;
572         }
573
574         if (__context.hvchange) {
575                 ecore_event_handler_del(__context.hvchange);
576                 __context.hvchange = NULL;
577         }
578
579         if (__context.hlower) {
580                 ecore_event_handler_del(__context.hlower);
581                 __context.hlower = NULL;
582         }
583
584         if (__context.hpvchange) {
585                 ecore_event_handler_del(__context.hpvchange);
586                 __context.hpvchange = NULL;
587         }
588 }
589
590 EXPORT_API int appcore_ui_base_on_create(void)
591 {
592         __add_ecore_events();
593         appcore_base_on_create();
594         __context.state = AS_CREATED;
595         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]", __context.appid);
596
597         return 0;
598 }
599
600 EXPORT_API int appcore_ui_base_on_terminate(void)
601 {
602         if (__context.state == AS_RUNNING) {
603                 if (__context.ops.pause)
604                         __context.ops.pause(__context.data);
605         }
606
607         __context.state = AS_DYING;
608
609         appcore_base_on_terminate();
610
611         return 0;
612 }
613
614 EXPORT_API int appcore_ui_base_on_pause(void)
615 {
616         return 0;
617 }
618
619 EXPORT_API int appcore_ui_base_on_resume(void)
620 {
621         return 0;
622 }
623
624 EXPORT_API int appcore_ui_base_on_control(bundle *b)
625 {
626         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", __context.appid);
627         appcore_base_on_control(b);
628         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", __context.appid);
629
630         return 0;
631 }
632
633 static void __group_attach()
634 {
635         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
636                 return;
637
638         appcore_ui_base_group_add();
639 }
640
641 static void __group_lower()
642 {
643         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
644                 return;
645         appcore_ui_base_group_remove();
646 }
647
648 EXPORT_API void appcore_ui_base_group_add()
649 {
650         static bool attached = false;
651
652         _DBG("__group_attach");
653         if (attached)
654                 return;
655
656         int wid = __get_main_surface();
657         if (wid == 0) {
658                 _ERR("window wasn't ready");
659                 return;
660         }
661
662         aul_app_group_set_window(wid);
663         attached = true;
664 }
665
666 EXPORT_API void appcore_ui_base_group_remove()
667 {
668         int exit = 0;
669
670         _DBG("__group_lower");
671         aul_app_group_lower(&exit);
672         if (exit) {
673                 _DBG("__group_lower : sub-app!");
674                 if (__context.ops.base.exit)
675                         __context.ops.base.exit(__context.data);
676         }
677 }
678
679 EXPORT_API void appcore_ui_base_window_on_show(int type, void *event)
680 {
681         Ecore_Wl_Event_Window_Show *ev;
682
683         ev = event;
684         if (ev->parent_win != 0) {
685                 /* This is child window. Skip!!! */
686                 return;
687         }
688
689         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
690
691         if (!__find_win((unsigned int)ev->win))
692                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
693         else
694                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
695
696         if (ev->data[0] != 0)
697                 __group_attach();
698 }
699
700 static bool __check_visible(void)
701 {
702         GSList *iter = NULL;
703         struct win_node *entry = NULL;
704
705         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
706
707         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
708                 entry = iter->data;
709                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
710                 if (entry->bfobscured == FALSE)
711                         return true;
712         }
713
714         return false;
715 }
716
717 EXPORT_API void appcore_ui_base_window_on_hide(int type, void *event)
718 {
719         Ecore_Wl_Event_Window_Hide *ev;
720         int bvisibility;
721
722         ev = event;
723         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
724
725         if (__find_win((unsigned int)ev->win)) {
726                 __delete_win((unsigned int)ev->win);
727                 bvisibility = __check_visible();
728                 if (!bvisibility && b_active == TRUE) {
729                         _DBG(" Go to Pasue state \n");
730                         b_active = FALSE;
731                         __do_pause();
732                 }
733         }
734 }
735
736 EXPORT_API void appcore_ui_base_window_on_lower(int type, void *event)
737 {
738         Ecore_Wl_Event_Window_Lower *ev;
739
740         ev = event;
741         if (!ev)
742                 return;
743         _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
744         __group_lower();
745 }
746
747 EXPORT_API void appcore_ui_base_window_on_visibility(int type, void *event)
748 {
749         Ecore_Wl_Event_Window_Visibility_Change *ev;
750         int bvisibility;
751
752         ev = event;
753         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
754         bvisibility = __check_visible();
755
756         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
757
758         if (bvisibility && b_active == FALSE) {
759                 _DBG(" Go to Resume state\n");
760                 b_active = TRUE;
761                 __do_resume();
762         } else if (!bvisibility && b_active == TRUE) {
763                 _DBG(" Go to Pasue state \n");
764                 b_active = FALSE;
765                 __do_pause();
766         } else {
767                 _DBG(" No change state \n");
768         }
769
770 }
771
772 EXPORT_API void appcore_ui_base_window_on_pre_visibility(int type, void *event)
773 {
774         Ecore_Wl_Event_Window_Pre_Visibility_Change *ev = event;
775         bool bvisibility;
776
777         if (ev && ev->type == ECORE_WL_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
778                 __update_win((unsigned int)ev->win, 0, false);
779                 bvisibility = __check_visible();
780
781                 _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
782                 if (bvisibility && b_active == FALSE) {
783                         _DBG(" Go to Resume state\n");
784                         b_active = TRUE;
785                         __do_resume();
786                 }
787         }
788 }
789
790 EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv,
791                 void *data, unsigned int hint)
792 {
793         const char *bg_launch;
794         bundle *b;
795         char appid[PATH_MAX] = {0, };
796
797         ecore_wl_init(NULL);
798
799         appcore_ui_plugin_init(&ops, argc, argv, &hint);
800         aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
801         __context.ops = ops;
802         __context.data = data;
803         __context.argc = argc;
804         __context.argv = argv;
805         __context.hint = hint;
806         __context.state = AS_NONE;
807         __context.appid = strdup(appid);
808
809         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
810         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
811                 b = bundle_import_from_argv(argc, argv);
812                 if (b) {
813                         bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
814                         if (bg_launch && strcmp(bg_launch, "enable") == 0)
815                                 __set_bg_state();
816
817                         bundle_free(b);
818                 }
819         }
820
821         return appcore_base_init(ops.base, argc, argv, data);
822 }
823
824 EXPORT_API void appcore_ui_base_fini(void)
825 {
826         __del_ecore_events();
827         __finish_wl();
828
829         free(__context.appid);
830         __context.appid = NULL;
831
832         appcore_ui_plugin_fini();
833         appcore_base_fini();
834         ecore_wl_shutdown();
835 }
836
837 EXPORT_API void appcore_ui_base_pause(void)
838 {
839         __do_pause();
840 }
841
842 EXPORT_API void appcore_ui_base_resume(void)
843 {
844         __do_resume();
845 }
846
847 EXPORT_API bool appcore_ui_base_is_resumed(void)
848 {
849         return __context.state == AS_RUNNING;
850 }
851
852 EXPORT_API void appcore_ui_base_exit(void)
853 {
854         if (__context.ops.base.exit)
855                 __context.ops.base.exit(__context.data);
856 }
857
858 EXPORT_API unsigned int appcore_ui_base_get_main_window(void)
859 {
860         return __get_main_window();
861 }
862
863 EXPORT_API unsigned int appcore_ui_base_get_main_surface(void)
864 {
865         return __get_main_surface();
866 }
867
868 EXPORT_API int appcore_ui_base_get_hint(void)
869 {
870         return __context.hint;
871 }
872
873 EXPORT_API bool appcore_ui_base_get_bg_state(void)
874 {
875         return __context.bg_state;
876 }
877
878 EXPORT_API void appcore_ui_base_set_bg_state(bool bg_state)
879 {
880         __context.bg_state = bg_state;
881 }
882
883 static int __on_receive(aul_type type, bundle *b, void *data)
884 {
885         return appcore_ui_base_on_receive(type, b);
886 }
887
888 static int __on_create(void *data)
889 {
890         return appcore_ui_base_on_create();
891 }
892
893 static int __on_terminate(void *data)
894 {
895         return appcore_ui_base_on_terminate();
896 }
897
898 static int __on_pause(void *data)
899 {
900         return appcore_ui_base_on_pause();
901 }
902
903 static int __on_resume(void *data)
904 {
905         return appcore_ui_base_on_resume();
906 }
907
908 static void __window_on_show(int type, void *event, void *data)
909 {
910         appcore_ui_base_window_on_show(type, event);
911 }
912
913 static void __window_on_hide(int type, void *event, void *data)
914 {
915         appcore_ui_base_window_on_hide(type, event);
916 }
917
918 static void __window_on_lower(int type, void *event, void *data)
919 {
920         appcore_ui_base_window_on_lower(type, event);
921 }
922
923 static void __window_on_visibility(int type, void *event, void *data)
924 {
925         appcore_ui_base_window_on_visibility(type, event);
926 }
927
928 static void __window_on_pre_visibility(int type, void *event, void *data)
929 {
930         appcore_ui_base_window_on_pre_visibility(type, event);
931 }
932
933 EXPORT_API appcore_ui_base_ops appcore_ui_base_get_default_ops(void)
934 {
935         appcore_ui_base_ops ops;
936
937         ops.base = appcore_base_get_default_ops();
938
939         /* override methods */
940         ops.base.create = __on_create;
941         ops.base.terminate = __on_terminate;
942         ops.base.receive = __on_receive;
943         ops.base.init = NULL;
944         ops.base.finish = NULL;
945         ops.base.run = NULL;
946         ops.base.exit = NULL;
947
948         ops.pause = __on_pause;
949         ops.resume = __on_resume;
950         ops.window.show = __window_on_show;
951         ops.window.hide = __window_on_hide;
952         ops.window.lower = __window_on_lower;
953         ops.window.visibility = __window_on_visibility;
954         ops.window.pre_visibility = __window_on_pre_visibility;
955
956         return ops;
957 }
958
959