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