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