Handle window pre visibility change event
[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 <glib-object.h>
35 #include <malloc.h>
36 #include <glib.h>
37 #include <gio/gio.h>
38 #include <stdbool.h>
39 #include <aul.h>
40 #include <aul_svc.h>
41 #include <bundle_internal.h>
42 #include <ttrace.h>
43
44 #include "appcore_base.h"
45 #include "appcore_ui_base.h"
46 #include "appcore_ui_base_private.h"
47 #include "appcore_ui_plugin.h"
48
49 enum app_state {
50         AS_NONE,
51         AS_CREATED,
52         AS_RUNNING,
53         AS_PAUSED,
54         AS_DYING,
55 };
56
57 typedef struct _appcore_ui_base_context {
58         appcore_ui_base_ops ops;
59         void *data;
60         int argc;
61         char **argv;
62         unsigned int hint;
63         char *below_app;
64         char *appid;
65
66         int state;
67         Ecore_Event_Handler *hshow;
68         Ecore_Event_Handler *hhide;
69         Ecore_Event_Handler *hvchange;
70         Ecore_Event_Handler *hlower;
71         Ecore_Event_Handler *hpvchange;
72 } appcore_ui_base_context;
73
74
75 static bool b_active = false;
76 static bool first_launch = true;
77
78 struct win_node {
79         unsigned int win;
80         unsigned int surf;
81         bool bfobscured;
82 };
83
84 static GSList *g_winnode_list;
85 static appcore_ui_base_context __context;
86 static struct wl_display *dsp;
87 static struct wl_registry *reg;
88 static struct tizen_policy *tz_policy;
89 static bool bg_state = false;
90
91 static void __wl_listener_cb(void *data, struct wl_registry *reg,
92                 uint32_t id, const char *interface, uint32_t ver)
93 {
94         if (interface && !strcmp(interface, "tizen_policy")) {
95                 if (!tz_policy)
96                         tz_policy = wl_registry_bind(reg, id,
97                                         &tizen_policy_interface, 1);
98         }
99 }
100
101 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
102                 unsigned int id)
103 {
104         /* do nothing */
105 }
106
107 static const struct wl_registry_listener reg_listener = {
108         __wl_listener_cb,
109         __wl_listener_remove_cb
110 };
111
112 static Eina_Bool __stub_show_cb(void *data, int type, void *event)
113 {
114         if (__context.ops.window.show)
115                 __context.ops.window.show(type, event, __context.data);
116
117         return ECORE_CALLBACK_RENEW;
118 }
119
120 static Eina_Bool __stub_hide_cb(void *data, int type, void *event)
121 {
122         if (__context.ops.window.hide)
123                 __context.ops.window.hide(type, event, __context.data);
124
125         return ECORE_CALLBACK_RENEW;
126 }
127
128 static Eina_Bool __stub_visibility_cb(void *data, int type, void *event)
129 {
130         if (__context.ops.window.visibility)
131                 __context.ops.window.visibility(type, event, __context.data);
132
133         return ECORE_CALLBACK_RENEW;
134 }
135
136 static Eina_Bool __stub_lower_cb(void *data, int type, void *event)
137 {
138         if (__context.ops.window.lower)
139                 __context.ops.window.lower(type, event, __context.data);
140
141         return ECORE_CALLBACK_RENEW;
142 }
143
144 static Eina_Bool __stub_pre_visibility_cb(void *data, int type, void *event)
145 {
146         if (__context.ops.window.pre_visibility)
147                 __context.ops.window.pre_visibility(type, event, __context.data);
148
149         return ECORE_CALLBACK_RENEW;
150 }
151
152 static void __prepare_to_suspend(void)
153 {
154         int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
155
156         if (appcore_base_is_bg_allowed() && !appcore_base_is_suspended()) {
157                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
158                 appcore_base_toggle_suspended_state();
159         }
160 }
161
162 static void __exit_from_suspend(void)
163 {
164         int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
165
166         if (appcore_base_is_suspended()) {
167                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
168                 appcore_base_toggle_suspended_state();
169         }
170 }
171
172 static void __do_pause(void)
173 {
174         if (__context.state == AS_RUNNING) {
175                 if (__context.ops.pause) {
176                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
177                         __context.ops.pause(__context.data);
178                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
179                 }
180
181                 __context.state = AS_PAUSED;
182                 __prepare_to_suspend();
183         }
184         aul_status_update(STATUS_BG);
185 }
186
187 static void __do_resume(void)
188 {
189         if (__context.state == AS_PAUSED || __context.state == AS_CREATED) {
190                 __exit_from_suspend();
191                 if (__context.ops.resume) {
192                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", __context.appid);
193                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
194                         __context.ops.resume(__context.data);
195                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
196                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", __context.appid);
197                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching: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         bg_state = true;
410         _DBG("bg state: %d", 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         bg_state = false;
421         _DBG("bg state: %d", 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 (!bg_state && __context.state != AS_RUNNING)
449                                 __set_bg_state();
450                 } else {
451                         if (bg_state)
452                                 __unset_bg_state();
453                 }
454         }
455
456         if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL) {
457                 if (!bg_state)
458                         __raise_win();
459         }
460 }
461
462 EXPORT_API int appcore_ui_base_on_receive(aul_type type, bundle *b)
463 {
464         if (__context.state == AS_DYING) {
465                 _ERR("Skip the event in dying state");
466                 return 0;
467         }
468
469         if (type == AUL_TERMINATE_BGAPP && __context.state != AS_PAUSED)
470                 return 0;
471
472         if (type == AUL_START)
473                 __exit_from_suspend();
474
475         appcore_base_on_receive(type, b);
476
477         switch (type) {
478         case AUL_START:
479                 __do_start(b);
480                 break;
481         case AUL_RESUME:
482                 if (bg_state)
483                         __unset_bg_state();
484                 __raise_win();
485                 break;
486         case AUL_TERMINATE:
487                 break;
488         case AUL_TERMINATE_BGAPP:
489                 _DBG("[APP %d] is paused. TERMINATE", getpid());
490                 __context.state = AS_DYING;
491                 aul_status_update(STATUS_DYING);
492                 if (__context.ops.base.exit)
493                         __context.ops.base.exit(__context.data);
494                 break;
495         case AUL_PAUSE:
496                 __pause_win();
497                 break;
498         default:
499                 break;
500         }
501
502         return 0;
503 }
504
505 EXPORT_API int appcore_ui_base_on_create(void)
506 {
507         appcore_base_on_create();
508
509         __context.hshow = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __stub_show_cb, NULL);
510         __context.hhide = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __stub_hide_cb, NULL);
511         __context.hvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
512                                 __stub_visibility_cb, NULL);
513         __context.hlower = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER, __stub_lower_cb, NULL);
514         __context.hpvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE,
515                         __stub_pre_visibility_cb, NULL);
516         __context.state = AS_CREATED;
517         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]", __context.appid);
518
519         return 0;
520 }
521
522 EXPORT_API int appcore_ui_base_on_terminate(void)
523 {
524         if (__context.state == AS_RUNNING) {
525                 if (__context.ops.pause)
526                         __context.ops.pause(__context.data);
527         }
528
529         __context.state = AS_DYING;
530
531         appcore_base_on_terminate();
532
533         return 0;
534 }
535
536 EXPORT_API int appcore_ui_base_on_pause(void)
537 {
538         return 0;
539 }
540
541 EXPORT_API int appcore_ui_base_on_resume(void)
542 {
543         return 0;
544 }
545
546 EXPORT_API int appcore_ui_base_on_control(bundle *b)
547 {
548         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", __context.appid);
549         appcore_base_on_control(b);
550         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", __context.appid);
551
552         return 0;
553 }
554
555 static void __group_attach()
556 {
557         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
558                 return;
559
560         appcore_ui_base_group_add();
561 }
562
563 static void __group_lower()
564 {
565         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
566                 return;
567         appcore_ui_base_group_remove();
568 }
569
570 EXPORT_API void appcore_ui_base_group_add()
571 {
572         static bool attached = false;
573
574         _DBG("__group_attach");
575         if (attached)
576                 return;
577
578         int wid = __get_main_surface();
579         if (wid == 0) {
580                 _ERR("window wasn't ready");
581                 return;
582         }
583
584         aul_app_group_set_window(wid);
585         attached = true;
586 }
587
588 EXPORT_API void appcore_ui_base_group_remove()
589 {
590         int exit = 0;
591
592         _DBG("__group_lower");
593         aul_app_group_lower(&exit);
594         if (exit) {
595                 _DBG("__group_lower : sub-app!");
596                 if (__context.ops.base.exit)
597                         __context.ops.base.exit(__context.data);
598         }
599 }
600
601 EXPORT_API void appcore_ui_base_window_on_show(int type, void *event)
602 {
603         Ecore_Wl_Event_Window_Show *ev;
604
605         ev = event;
606         if (ev->parent_win != 0) {
607                 /* This is child window. Skip!!! */
608                 return;
609         }
610
611         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
612
613         if (!__find_win((unsigned int)ev->win))
614                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
615         else
616                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
617
618         if (ev->data[0] != 0)
619                 __group_attach();
620 }
621
622 static bool __check_visible(void)
623 {
624         GSList *iter = NULL;
625         struct win_node *entry = NULL;
626
627         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
628
629         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
630                 entry = iter->data;
631                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
632                 if (entry->bfobscured == FALSE)
633                         return true;
634         }
635
636         return false;
637 }
638
639 EXPORT_API void appcore_ui_base_window_on_hide(int type, void *event)
640 {
641         Ecore_Wl_Event_Window_Hide *ev;
642         int bvisibility;
643
644         ev = event;
645         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
646
647         if (__find_win((unsigned int)ev->win)) {
648                 __delete_win((unsigned int)ev->win);
649                 bvisibility = __check_visible();
650                 if (!bvisibility && b_active == TRUE) {
651                         _DBG(" Go to Pasue state \n");
652                         b_active = FALSE;
653                         __do_pause();
654                 }
655         }
656 }
657
658 EXPORT_API void appcore_ui_base_window_on_lower(int type, void *event)
659 {
660         Ecore_Wl_Event_Window_Lower *ev;
661
662         ev = event;
663         if (!ev)
664                 return;
665         _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
666         __group_lower();
667 }
668
669 EXPORT_API void appcore_ui_base_window_on_visibility(int type, void *event)
670 {
671         Ecore_Wl_Event_Window_Visibility_Change *ev;
672         int bvisibility;
673
674         ev = event;
675         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
676         bvisibility = __check_visible();
677
678         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
679
680         if (bvisibility && b_active == FALSE) {
681                 _DBG(" Go to Resume state\n");
682                 b_active = TRUE;
683                 __do_resume();
684         } else if (!bvisibility && b_active == TRUE) {
685                 _DBG(" Go to Pasue state \n");
686                 b_active = FALSE;
687                 __do_pause();
688         } else {
689                 _DBG(" No change state \n");
690         }
691
692 }
693
694 EXPORT_API void appcore_ui_base_window_on_pre_visibility(int type, void *event)
695 {
696         Ecore_Wl_Event_Window_Pre_Visibility_Change *ev = event;
697         bool bvisibility;
698
699         if (ev && ev->type == ECORE_WL_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
700                 __update_win((unsigned int)ev->win, 0, false);
701                 bvisibility = __check_visible();
702
703                 _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
704                 if (bvisibility && b_active == FALSE) {
705                         _DBG(" Go to Resume state\n");
706                         b_active = TRUE;
707                         __do_resume();
708                 }
709         }
710 }
711
712 EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv,
713                 void *data, unsigned int hint)
714 {
715         const char *bg_launch;
716         bundle *b;
717         char appid[PATH_MAX] = {0, };
718
719         appcore_ui_plugin_init(&ops, argc, argv, &hint);
720         aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
721         __context.ops = ops;
722         __context.data = data;
723         __context.argc = argc;
724         __context.argv = argv;
725         __context.hint = hint;
726         __context.state = AS_NONE;
727         __context.appid = strdup(appid);
728
729         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
730         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
731                 b = bundle_import_from_argv(argc, argv);
732                 if (b) {
733                         bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
734                         if (bg_launch && strcmp(bg_launch, "enable") == 0)
735                                 __set_bg_state();
736
737                         bundle_free(b);
738                 }
739         }
740
741         return appcore_base_init(ops.base, argc, argv, data);
742 }
743
744 EXPORT_API void appcore_ui_base_fini(void)
745 {
746         if (__context.hshow)
747                 ecore_event_handler_del(__context.hshow);
748         if (__context.hhide)
749                 ecore_event_handler_del(__context.hhide);
750         if (__context.hvchange)
751                 ecore_event_handler_del(__context.hvchange);
752         if (__context.hlower)
753                 ecore_event_handler_del(__context.hlower);
754         if (__context.hpvchange)
755                 ecore_event_handler_del(__context.hpvchange);
756
757         __finish_wl();
758
759         free(__context.appid);
760         __context.appid = NULL;
761
762         appcore_ui_plugin_fini();
763         appcore_base_fini();
764 }
765
766 EXPORT_API void appcore_ui_base_pause(void)
767 {
768         __do_pause();
769 }
770
771 EXPORT_API void appcore_ui_base_resume(void)
772 {
773         __do_resume();
774 }
775
776 EXPORT_API bool appcore_ui_base_is_resumed(void)
777 {
778         return __context.state == AS_RUNNING;
779 }
780
781 EXPORT_API void appcore_ui_base_exit(void)
782 {
783         if (__context.ops.base.exit)
784                 __context.ops.base.exit(__context.data);
785 }
786
787 EXPORT_API unsigned int appcore_ui_base_get_main_window(void)
788 {
789         return __get_main_window();
790 }
791
792 EXPORT_API unsigned int appcore_ui_base_get_main_surface(void)
793 {
794         return __get_main_surface();
795 }
796
797 EXPORT_API int appcore_ui_base_get_hint(void)
798 {
799         return __context.hint;
800 }
801
802 static int __on_receive(aul_type type, bundle *b, void *data)
803 {
804         return appcore_ui_base_on_receive(type, b);
805 }
806
807 static int __on_create(void *data)
808 {
809         return appcore_ui_base_on_create();
810 }
811
812 static int __on_terminate(void *data)
813 {
814         return appcore_ui_base_on_terminate();
815 }
816
817 static int __on_pause(void *data)
818 {
819         return appcore_ui_base_on_pause();
820 }
821
822 static int __on_resume(void *data)
823 {
824         return appcore_ui_base_on_resume();
825 }
826
827 static void __window_on_show(int type, void *event, void *data)
828 {
829         appcore_ui_base_window_on_show(type, event);
830 }
831
832 static void __window_on_hide(int type, void *event, void *data)
833 {
834         appcore_ui_base_window_on_hide(type, event);
835 }
836
837 static void __window_on_lower(int type, void *event, void *data)
838 {
839         appcore_ui_base_window_on_lower(type, event);
840 }
841
842 static void __window_on_visibility(int type, void *event, void *data)
843 {
844         appcore_ui_base_window_on_visibility(type, event);
845 }
846
847 static void __window_on_pre_visibility(int type, void *event, void *data)
848 {
849         appcore_ui_base_window_on_pre_visibility(type, event);
850 }
851
852 EXPORT_API appcore_ui_base_ops appcore_ui_base_get_default_ops(void)
853 {
854         appcore_ui_base_ops ops;
855
856         ops.base = appcore_base_get_default_ops();
857
858         /* override methods */
859         ops.base.create = __on_create;
860         ops.base.terminate = __on_terminate;
861         ops.base.receive = __on_receive;
862         ops.base.init = NULL;
863         ops.base.finish = NULL;
864         ops.base.run = NULL;
865         ops.base.exit = NULL;
866
867         ops.pause = __on_pause;
868         ops.resume = __on_resume;
869         ops.window.show = __window_on_show;
870         ops.window.hide = __window_on_hide;
871         ops.window.lower = __window_on_lower;
872         ops.window.visibility = __window_on_visibility;
873         ops.window.pre_visibility = __window_on_pre_visibility;
874
875         return ops;
876 }
877
878