Modified flushing memory logic
[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_Wl2.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 enum win_status {
59         WS_NONE,
60         WS_PAUSE,
61         WS_RESUME,
62 };
63
64 typedef struct _appcore_ui_base_context {
65         appcore_ui_base_ops ops;
66         void *data;
67         int argc;
68         char **argv;
69         unsigned int hint;
70         char *below_app;
71         char *appid;
72         bool bg_state;
73         bool resource_reclaiming;
74
75         int state;
76         Ecore_Event_Handler *hshow;
77         Ecore_Event_Handler *hhide;
78         Ecore_Event_Handler *hvchange;
79         Ecore_Event_Handler *hlower;
80         Ecore_Event_Handler *hpvchange;
81 } appcore_ui_base_context;
82
83
84 static int w_status = WS_NONE;
85 static bool first_launch = true;
86
87 struct win_node {
88         unsigned int win;
89         unsigned int surf;
90         bool bfobscured;
91 };
92
93 static GSList *g_winnode_list;
94 static appcore_ui_base_context __context;
95 static struct wl_display *dsp;
96 static struct wl_registry *reg;
97 static struct tizen_policy *tz_policy;
98
99 static void _wl_cb_conformant(void *data,
100                 struct tizen_policy *tizen_policy,
101                 struct wl_surface *surface_resource,
102                 uint32_t is_conformant)
103 {
104         ; // nothing to do.
105 }
106
107 static void _wl_cb_conformant_area(void *data,
108                 struct tizen_policy *tizen_policy,
109                 struct wl_surface *surface_resource,
110                 uint32_t conformant_part,
111                 uint32_t state,
112                 int32_t x, int32_t y, int32_t w, int32_t h)
113 {
114         ; // nothing to do.
115 }
116
117 static void _wl_cb_notification_done(void *data,
118                 struct tizen_policy *tizen_policy,
119                 struct wl_surface *surface,
120                 int32_t level,
121                 uint32_t state)
122 {
123         ; // nothing to do.
124 }
125
126 static void _wl_cb_transient_for_done(void *data,
127                 struct tizen_policy *tizen_policy,
128                 uint32_t child_id)
129 {
130         ; // nothing to do.
131 }
132
133 static void _wl_cb_scr_mode_done(void *data,
134                 struct tizen_policy *tizen_policy,
135                 struct wl_surface *surface,
136                 uint32_t mode,
137                 uint32_t state)
138 {
139         ; // nothing to do.
140 }
141
142 static void _wl_cb_iconify_state_changed(void *data,
143                 struct tizen_policy *tizen_policy,
144                 struct wl_surface *surface_resource,
145                 uint32_t iconified,
146                 uint32_t force)
147 {
148         ; // nothing to do.
149 }
150
151 static void _wl_cb_supported_aux_hints(void *data,
152                 struct tizen_policy *tizen_policy,
153                 struct wl_surface *surface_resource,
154                 struct wl_array *hints,
155                 uint32_t num_hints)
156 {
157         ; // nothing to do.
158 }
159
160 static void _wl_cb_allowed_aux_hint(void *data,
161                 struct tizen_policy *tizen_policy,
162                 struct wl_surface *surface_resource,
163                 int id)
164 {
165         ; // nothing to do.
166 }
167
168 static void _wl_cb_aux_message(void *data,
169                 struct tizen_policy *tizen_policy,
170                 struct wl_surface *surface_resource,
171                 const char *key,
172                 const char *val,
173                 struct wl_array *options)
174 {
175         ; // nothing to do.
176 }
177
178 static void _wl_cb_conformant_region(void *data,
179                 struct tizen_policy *tizen_policy,
180                 struct wl_surface *surface,
181                 uint32_t conformant_part,
182                 uint32_t state,
183                 int32_t x, int32_t y, int32_t w, int32_t h,
184                 uint32_t serial)
185 {
186         ; // nothing to do.
187 }
188
189 static const struct tizen_policy_listener _tizen_policy_listener = {
190         _wl_cb_conformant,
191         _wl_cb_conformant_area,
192         _wl_cb_notification_done,
193         _wl_cb_transient_for_done,
194         _wl_cb_scr_mode_done,
195         _wl_cb_iconify_state_changed,
196         _wl_cb_supported_aux_hints,
197         _wl_cb_allowed_aux_hint,
198         _wl_cb_aux_message,
199         _wl_cb_conformant_region,
200 };
201
202 static void __wl_listener_cb(void *data, struct wl_registry *reg,
203                 uint32_t id, const char *interface, uint32_t ver)
204 {
205         if (interface && !strcmp(interface, "tizen_policy")) {
206                 if (!tz_policy)
207                         tz_policy = wl_registry_bind(reg, id,
208                                         &tizen_policy_interface, 7);
209                 if (tz_policy) {
210                         tizen_policy_add_listener(tz_policy, &_tizen_policy_listener, dsp);
211                 }
212         }
213 }
214
215 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
216                 unsigned int id)
217 {
218         /* do nothing */
219 }
220
221 static const struct wl_registry_listener reg_listener = {
222         __wl_listener_cb,
223         __wl_listener_remove_cb
224 };
225
226 static Eina_Bool __stub_show_cb(void *data, int type, void *event)
227 {
228         if (__context.ops.window.show)
229                 __context.ops.window.show(type, event, __context.data);
230
231         return ECORE_CALLBACK_RENEW;
232 }
233
234 static Eina_Bool __stub_hide_cb(void *data, int type, void *event)
235 {
236         if (__context.ops.window.hide)
237                 __context.ops.window.hide(type, event, __context.data);
238
239         return ECORE_CALLBACK_RENEW;
240 }
241
242 static Eina_Bool __stub_visibility_cb(void *data, int type, void *event)
243 {
244         if (__context.ops.window.visibility)
245                 __context.ops.window.visibility(type, event, __context.data);
246
247         return ECORE_CALLBACK_RENEW;
248 }
249
250 static Eina_Bool __stub_lower_cb(void *data, int type, void *event)
251 {
252         if (__context.ops.window.lower)
253                 __context.ops.window.lower(type, event, __context.data);
254
255         return ECORE_CALLBACK_RENEW;
256 }
257
258 static Eina_Bool __stub_pre_visibility_cb(void *data, int type, void *event)
259 {
260         if (__context.ops.window.pre_visibility)
261                 __context.ops.window.pre_visibility(type, event, __context.data);
262
263         return ECORE_CALLBACK_RENEW;
264 }
265
266 static void __prepare_to_suspend(void)
267 {
268         int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
269
270         if (appcore_base_is_bg_allowed() && !appcore_base_is_suspended()) {
271                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
272                 appcore_base_toggle_suspended_state();
273         }
274 }
275
276 static void __exit_from_suspend(void)
277 {
278         int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
279
280         if (appcore_base_is_suspended()) {
281                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
282                 appcore_base_toggle_suspended_state();
283         }
284 }
285
286 static void __do_pause(void)
287 {
288         int r = -1;
289
290         if (__context.state == AS_RUNNING) {
291                 if (__context.ops.pause) {
292                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
293                         _DBG("Call pause callback");
294                         r = __context.ops.pause(__context.data);
295                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
296                 }
297
298                 if (r >= 0 && __context.resource_reclaiming)
299                         appcore_base_add_suspend_timer();
300
301                 __context.state = AS_PAUSED;
302                 __prepare_to_suspend();
303         }
304         aul_status_update(STATUS_BG);
305 }
306
307 static void __do_resume(void)
308 {
309         if (__context.state == AS_PAUSED || __context.state == AS_CREATED) {
310                 __exit_from_suspend();
311                 if (__context.ops.resume) {
312                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", __context.appid);
313                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
314                         _DBG("Call resume callback");
315                         __context.ops.resume(__context.data);
316                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
317                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", __context.appid);
318                 }
319                 __context.state = AS_RUNNING;
320         }
321
322         aul_status_update(STATUS_VISIBLE);
323 }
324
325 static GSList *__find_win(unsigned int win)
326 {
327         GSList *iter;
328         struct win_node *t;
329
330         for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
331                 t = iter->data;
332                 if (t && t->win == win)
333                         return iter;
334         }
335
336         return NULL;
337 }
338
339 static int __get_main_window(void)
340 {
341         struct win_node *entry = NULL;
342
343         if (g_winnode_list != NULL) {
344                 entry = g_winnode_list->data;
345                 return (unsigned int) entry->win;
346         }
347
348         return 0;
349 }
350
351 static int __get_main_surface(void)
352 {
353         struct win_node *entry = NULL;
354
355         if (g_winnode_list != NULL) {
356                 entry = g_winnode_list->data;
357                 return (unsigned int) entry->surf;
358         }
359
360         return 0;
361 }
362
363 static bool __add_win(unsigned int win, unsigned int surf)
364 {
365         struct win_node *t;
366         GSList *f;
367
368         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
369
370         f = __find_win(win);
371         if (f) {
372                 errno = ENOENT;
373                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
374                 return FALSE;
375         }
376
377         t = calloc(1, sizeof(struct win_node));
378         if (t == NULL)
379                 return FALSE;
380
381         t->win = win;
382         t->surf = surf;
383         t->bfobscured = FALSE;
384
385         g_winnode_list = g_slist_append(g_winnode_list, t);
386
387         return TRUE;
388 }
389
390 static bool __delete_win(unsigned int win)
391 {
392         GSList *f;
393
394         f = __find_win(win);
395         if (!f) {
396                 errno = ENOENT;
397                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
398                                 win);
399                 return FALSE;
400         }
401
402         free(f->data);
403         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
404
405         return TRUE;
406 }
407
408 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
409 {
410         GSList *f;
411         struct win_node *t;
412
413         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
414              bfobscured);
415
416         f = __find_win(win);
417         if (!f) {
418                 errno = ENOENT;
419                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
420                 return FALSE;
421         }
422
423         t = (struct win_node *)f->data;
424         t->win = win;
425         if (surf != 0)
426                 t->surf = surf;
427         t->bfobscured = bfobscured;
428
429         return TRUE;
430 }
431
432 static void __raise_win(void)
433 {
434         Ecore_Wl2_Window *win;
435         unsigned int win_id;
436
437         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
438                 return;
439
440         win_id = __get_main_window();
441
442         _DBG("Raise window: %d", win_id);
443         win = ecore_wl2_display_window_find(ecore_wl2_connected_display_get(NULL), win_id);
444         ecore_wl2_window_activate(win);
445 }
446
447 static void __pause_win(void)
448 {
449         Ecore_Wl2_Window *win;
450         GSList *wlist = g_winnode_list;
451         struct win_node *entry = NULL;
452
453         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
454                 return;
455
456         _DBG("Pause window");
457
458         while (wlist) {
459                 entry = wlist->data;
460
461                 _DBG("Pause window: %d", entry->win);
462                 win = ecore_wl2_display_window_find(ecore_wl2_connected_display_get(NULL), entry->win);
463                 ecore_wl2_window_iconified_set(win, EINA_TRUE);
464
465                 wlist = wlist->next;
466         }
467 }
468
469 static int __init_wl(void)
470 {
471         _DBG("initialize wayland");
472         dsp = wl_display_connect(NULL);
473         if (dsp == NULL) {
474                 _ERR("Failed to connect wl display");
475                 return -1;
476         }
477
478         reg = wl_display_get_registry(dsp);
479         if (reg == NULL) {
480                 _ERR("Failed to get registry");
481                 wl_display_disconnect(dsp);
482                 return -1;
483         }
484
485         wl_registry_add_listener(reg, &reg_listener, NULL);
486         wl_display_roundtrip(dsp);
487
488         if (!tz_policy) {
489                 _ERR("Failed to get tizen policy interface");
490                 wl_registry_destroy(reg);
491                 wl_display_disconnect(dsp);
492                 return -1;
493         }
494
495         return 0;
496 }
497
498 static void __finish_wl(void)
499 {
500         if (tz_policy) {
501                 tizen_policy_destroy(tz_policy);
502                 tz_policy = NULL;
503         }
504
505         if (reg) {
506                 wl_registry_destroy(reg);
507                 reg = NULL;
508         }
509
510         if (dsp) {
511                 wl_display_disconnect(dsp);
512                 dsp = NULL;
513         }
514 }
515
516 static void __set_bg_state(void)
517 {
518         if (!tz_policy && __init_wl() < 0)
519                 return;
520
521         tizen_policy_set_background_state(tz_policy, getpid());
522         wl_display_roundtrip(dsp);
523         __context.bg_state = true;
524         _DBG("bg state: %d", __context.bg_state);
525 }
526
527 static void __unset_bg_state(void)
528 {
529         if (!tz_policy)
530                 return;
531
532         tizen_policy_unset_background_state(tz_policy, getpid());
533         wl_display_roundtrip(dsp);
534         __context.bg_state = false;
535         _DBG("bg state: %d", __context.bg_state);
536 }
537
538 static void __do_start(bundle *b)
539 {
540         const char *bg_launch;
541         const char *below_app;
542
543         if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) {
544                 if (__context.below_app) {
545                         free(__context.below_app);
546                         __context.below_app = NULL;
547                 }
548
549                 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
550                 if (below_app)
551                         __context.below_app = strdup(below_app);
552         }
553
554         if (first_launch) {
555                 first_launch = FALSE;
556                 return;
557         }
558
559         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
560                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
561                 if (bg_launch && strcmp(bg_launch, "enable") == 0) {
562                         if (!__context.bg_state &&
563                                         __context.state != AS_RUNNING)
564                                 __set_bg_state();
565                 } else {
566                         if (__context.bg_state)
567                                 __unset_bg_state();
568                 }
569         }
570
571         if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL) {
572                 if (!__context.bg_state)
573                         __raise_win();
574         }
575 }
576
577 static int __is_legacy_lifecycle(void)
578 {
579         static int is_legacy = -1;
580         const char *api_version;
581
582         if (is_legacy != -1)
583                 return is_legacy;
584
585         api_version = getenv("TIZEN_API_VERSION");
586         if (api_version) {
587                 if (strverscmp("2.4", api_version) > 0 &&
588                                 strverscmp("2.2.1", api_version) < 0)
589                         is_legacy = 1;
590                 else
591                         is_legacy = 0;
592         } else {
593                 is_legacy = 0;
594         }
595
596         return is_legacy;
597 }
598
599 EXPORT_API int appcore_ui_base_on_receive(aul_type type, bundle *b)
600 {
601         if (__context.state == AS_DYING) {
602                 _ERR("Skip the event in dying state");
603                 return 0;
604         }
605
606         if (type == AUL_TERMINATE_BGAPP && __context.state != AS_PAUSED)
607                 return 0;
608
609         if (type == AUL_START)
610                 __exit_from_suspend();
611
612         appcore_base_on_receive(type, b);
613
614         switch (type) {
615         case AUL_START:
616                 __do_start(b);
617                 if (__context.hint & APPCORE_UI_BASE_HINT_LEGACY_CONTROL) {
618                         if (!__context.bg_state && __is_legacy_lifecycle()) {
619                                 _DBG("Legacy lifecycle");
620                                 __do_resume();
621                         }
622                 }
623                 break;
624         case AUL_RESUME:
625                 if (__context.bg_state)
626                         __unset_bg_state();
627                 __raise_win();
628                 break;
629         case AUL_TERMINATE:
630                 break;
631         case AUL_TERMINATE_BGAPP:
632                 _DBG("[APP %d] is paused. TERMINATE", getpid());
633                 __context.state = AS_DYING;
634                 aul_status_update(STATUS_DYING);
635                 if (__context.ops.base.exit)
636                         __context.ops.base.exit(__context.data);
637                 break;
638         case AUL_PAUSE:
639                 __pause_win();
640                 break;
641         default:
642                 break;
643         }
644
645         return 0;
646 }
647
648 static void __add_ecore_events(void)
649 {
650         __context.hshow = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_SHOW,
651                         __stub_show_cb, NULL);
652         if (!__context.hshow)
653                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_SHOW event");
654
655         __context.hhide = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_HIDE,
656                         __stub_hide_cb, NULL);
657         if (!__context.hhide)
658                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_HIDE event");
659
660         __context.hvchange = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE,
661                         __stub_visibility_cb, NULL);
662         if (!__context.hvchange)
663                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE event");
664
665         __context.hlower = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_LOWER,
666                         __stub_lower_cb, NULL);
667         if (!__context.hlower)
668                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_LOWER event");
669
670         __context.hpvchange = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE,
671                         __stub_pre_visibility_cb, NULL);
672         if (!__context.hpvchange)
673                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE event");
674 }
675
676 static void __del_ecore_events(void)
677 {
678         if (__context.hshow) {
679                 ecore_event_handler_del(__context.hshow);
680                 __context.hshow = NULL;
681         }
682
683         if (__context.hhide) {
684                 ecore_event_handler_del(__context.hhide);
685                 __context.hhide = NULL;
686         }
687
688         if (__context.hvchange) {
689                 ecore_event_handler_del(__context.hvchange);
690                 __context.hvchange = NULL;
691         }
692
693         if (__context.hlower) {
694                 ecore_event_handler_del(__context.hlower);
695                 __context.hlower = NULL;
696         }
697
698         if (__context.hpvchange) {
699                 ecore_event_handler_del(__context.hpvchange);
700                 __context.hpvchange = NULL;
701         }
702 }
703
704 EXPORT_API int appcore_ui_base_on_create(void)
705 {
706         __add_ecore_events();
707         appcore_base_on_create();
708         __context.state = AS_CREATED;
709         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]", __context.appid);
710
711         return 0;
712 }
713
714 EXPORT_API int appcore_ui_base_on_terminate(void)
715 {
716         if (__context.state == AS_RUNNING) {
717                 if (__context.ops.pause) {
718                         _DBG("Call pause callback");
719                         __context.ops.pause(__context.data);
720                 }
721         }
722
723         __context.state = AS_DYING;
724
725         appcore_base_on_terminate();
726
727         return 0;
728 }
729
730 EXPORT_API int appcore_ui_base_on_pause(void)
731 {
732         return 0;
733 }
734
735 EXPORT_API int appcore_ui_base_on_resume(void)
736 {
737         return 0;
738 }
739
740 EXPORT_API int appcore_ui_base_on_control(bundle *b)
741 {
742         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", __context.appid);
743         appcore_base_on_control(b);
744         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", __context.appid);
745
746         return 0;
747 }
748
749 EXPORT_API int appcore_ui_base_on_trim_memory(void)
750 {
751         return appcore_base_on_trim_memory();
752 }
753
754 static void __group_attach()
755 {
756         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
757                 return;
758
759         appcore_ui_base_group_add();
760 }
761
762 static void __group_lower()
763 {
764         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
765                 return;
766         appcore_ui_base_group_remove();
767 }
768
769 EXPORT_API void appcore_ui_base_group_add()
770 {
771         static bool attached = false;
772
773         _DBG("__group_attach");
774         if (attached)
775                 return;
776
777         int wid = __get_main_surface();
778         if (wid == 0) {
779                 _ERR("window wasn't ready");
780                 return;
781         }
782
783         aul_app_group_set_window(wid);
784         attached = true;
785 }
786
787 EXPORT_API void appcore_ui_base_group_remove()
788 {
789         int exit = 0;
790
791         _DBG("__group_lower");
792         aul_app_group_lower(&exit);
793         if (exit) {
794                 _DBG("__group_lower : sub-app!");
795                 if (__context.ops.base.exit)
796                         __context.ops.base.exit(__context.data);
797         }
798 }
799
800 EXPORT_API void appcore_ui_base_window_on_show(int type, void *event)
801 {
802         Ecore_Wl2_Event_Window_Show *ev;
803
804         ev = event;
805         if (ev->parent_win != 0) {
806                 /* This is child window. Skip!!! */
807                 return;
808         }
809
810         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
811
812         if (!__find_win((unsigned int)ev->win))
813                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
814         else
815                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
816
817         if (ev->data[0] != 0)
818                 __group_attach();
819 }
820
821 static bool __check_visible(void)
822 {
823         GSList *iter = NULL;
824         struct win_node *entry = NULL;
825
826         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
827
828         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
829                 entry = iter->data;
830                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
831                 if (entry->bfobscured == FALSE)
832                         return true;
833         }
834
835         return false;
836 }
837
838 EXPORT_API void appcore_ui_base_window_on_hide(int type, void *event)
839 {
840         Ecore_Wl2_Event_Window_Hide *ev;
841         int bvisibility;
842
843         ev = event;
844         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
845
846         if (__find_win((unsigned int)ev->win)) {
847                 __delete_win((unsigned int)ev->win);
848                 bvisibility = __check_visible();
849                 if (!bvisibility && w_status != WS_PAUSE) {
850                         _DBG(" Go to Pasue state \n");
851                         w_status = WS_PAUSE;
852                         __do_pause();
853                 }
854         }
855 }
856
857 EXPORT_API void appcore_ui_base_window_on_lower(int type, void *event)
858 {
859         Ecore_Wl2_Event_Window_Lower *ev;
860
861         ev = event;
862         if (!ev)
863                 return;
864         _DBG("ECORE_WL2_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
865         __group_lower();
866 }
867
868 EXPORT_API void appcore_ui_base_window_on_visibility(int type, void *event)
869 {
870         Ecore_Wl2_Event_Window_Visibility_Change *ev;
871         int bvisibility;
872
873         ev = event;
874         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
875         bvisibility = __check_visible();
876
877         _DBG("bvisibility %d, w_status %d", bvisibility, w_status);
878
879         if (bvisibility && (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) &&
880                         __context.below_app) {
881                 aul_app_group_activate_below(__context.below_app);
882                 free(__context.below_app);
883                 __context.below_app = NULL;
884         }
885
886         if (bvisibility && w_status != WS_RESUME) {
887                 _DBG(" Go to Resume state\n");
888                 w_status = WS_RESUME;
889                 __do_resume();
890         } else if (!bvisibility && w_status != WS_PAUSE) {
891                 _DBG(" Go to Pasue state \n");
892                 w_status = WS_PAUSE;
893                 __do_pause();
894         } else {
895                 _DBG(" No change state \n");
896         }
897
898 }
899
900 EXPORT_API void appcore_ui_base_window_on_pre_visibility(int type, void *event)
901 {
902         Ecore_Wl2_Event_Window_Pre_Visibility_Change *ev = event;
903         bool bvisibility;
904
905         if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
906                 __update_win((unsigned int)ev->win, 0, false);
907                 bvisibility = __check_visible();
908
909                 _DBG("bvisibility %d, w_status %d", bvisibility, w_status);
910                 if (bvisibility && w_status != WS_RESUME) {
911                         _DBG(" Go to Resume state\n");
912                         w_status = WS_RESUME;
913                         __do_resume();
914                 }
915         }
916 }
917
918 EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv,
919                 void *data, unsigned int hint)
920 {
921         const char *bg_launch;
922         bundle *b;
923         char appid[PATH_MAX] = {0, };
924         int ret;
925
926         if (!ecore_wl2_init()) {
927                 _ERR("could not wl2 init");
928                 return -1;
929         }
930
931         ecore_wl2_display_connect(NULL);
932         appcore_ui_plugin_init(&ops, argc, argv, &hint);
933         ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
934         if (ret != 0) {
935                 _ERR("Fail to get appid (%d)", getpid());
936         }
937         __context.ops = ops;
938         __context.data = data;
939         __context.argc = argc;
940         __context.argv = argv;
941         __context.hint = hint;
942         __context.state = AS_NONE;
943         __context.appid = strdup(appid);
944         __context.resource_reclaiming = true;
945
946         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
947         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
948                 b = bundle_import_from_argv(argc, argv);
949                 if (b) {
950                         bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
951                         if (bg_launch && strcmp(bg_launch, "enable") == 0)
952                                 __set_bg_state();
953
954                         bundle_free(b);
955                 }
956         }
957
958         return appcore_base_init(ops.base, argc, argv, data);
959 }
960
961 EXPORT_API void appcore_ui_base_fini(void)
962 {
963         __del_ecore_events();
964         __finish_wl();
965
966         free(__context.appid);
967         __context.appid = NULL;
968
969         appcore_base_fini();
970         appcore_ui_plugin_fini();
971         _ERR("disconnect wl2_display");
972         ecore_wl2_display_disconnect(ecore_wl2_connected_display_get(NULL));
973         ecore_wl2_shutdown();
974 }
975
976 EXPORT_API void appcore_ui_base_pause(void)
977 {
978         __do_pause();
979 }
980
981 EXPORT_API void appcore_ui_base_resume(void)
982 {
983         __do_resume();
984 }
985
986 EXPORT_API bool appcore_ui_base_is_resumed(void)
987 {
988         return __context.state == AS_RUNNING;
989 }
990
991 EXPORT_API void appcore_ui_base_exit(void)
992 {
993         if (__context.ops.base.exit)
994                 __context.ops.base.exit(__context.data);
995 }
996
997 EXPORT_API unsigned int appcore_ui_base_get_main_window(void)
998 {
999         return __get_main_window();
1000 }
1001
1002 EXPORT_API unsigned int appcore_ui_base_get_main_surface(void)
1003 {
1004         return __get_main_surface();
1005 }
1006
1007 EXPORT_API int appcore_ui_base_get_hint(void)
1008 {
1009         return __context.hint;
1010 }
1011
1012 EXPORT_API bool appcore_ui_base_get_bg_state(void)
1013 {
1014         return __context.bg_state;
1015 }
1016
1017 EXPORT_API void appcore_ui_base_set_bg_state(bool bg_state)
1018 {
1019         __context.bg_state = bg_state;
1020 }
1021
1022 EXPORT_API void appcore_ui_base_set_system_resource_reclaiming(bool enable)
1023 {
1024         __context.resource_reclaiming = enable;
1025 }
1026
1027 static int __on_receive(aul_type type, bundle *b, void *data)
1028 {
1029         return appcore_ui_base_on_receive(type, b);
1030 }
1031
1032 static int __on_create(void *data)
1033 {
1034         return appcore_ui_base_on_create();
1035 }
1036
1037 static int __on_terminate(void *data)
1038 {
1039         return appcore_ui_base_on_terminate();
1040 }
1041
1042 static int __on_pause(void *data)
1043 {
1044         return appcore_ui_base_on_pause();
1045 }
1046
1047 static int __on_resume(void *data)
1048 {
1049         return appcore_ui_base_on_resume();
1050 }
1051
1052 static void __window_on_show(int type, void *event, void *data)
1053 {
1054         appcore_ui_base_window_on_show(type, event);
1055 }
1056
1057 static void __window_on_hide(int type, void *event, void *data)
1058 {
1059         appcore_ui_base_window_on_hide(type, event);
1060 }
1061
1062 static void __window_on_lower(int type, void *event, void *data)
1063 {
1064         appcore_ui_base_window_on_lower(type, event);
1065 }
1066
1067 static void __window_on_visibility(int type, void *event, void *data)
1068 {
1069         appcore_ui_base_window_on_visibility(type, event);
1070 }
1071
1072 static void __window_on_pre_visibility(int type, void *event, void *data)
1073 {
1074         appcore_ui_base_window_on_pre_visibility(type, event);
1075 }
1076
1077 EXPORT_API appcore_ui_base_ops appcore_ui_base_get_default_ops(void)
1078 {
1079         appcore_ui_base_ops ops;
1080
1081         ops.base = appcore_base_get_default_ops();
1082
1083         /* override methods */
1084         ops.base.create = __on_create;
1085         ops.base.terminate = __on_terminate;
1086         ops.base.receive = __on_receive;
1087         ops.base.init = NULL;
1088         ops.base.finish = NULL;
1089         ops.base.run = NULL;
1090         ops.base.exit = NULL;
1091
1092         ops.pause = __on_pause;
1093         ops.resume = __on_resume;
1094         ops.window.show = __window_on_show;
1095         ops.window.hide = __window_on_hide;
1096         ops.window.lower = __window_on_lower;
1097         ops.window.visibility = __window_on_visibility;
1098         ops.window.pre_visibility = __window_on_pre_visibility;
1099
1100         return ops;
1101 }
1102
1103