Check return value
[platform/core/appfw/app-core.git] / src / ui_base / appcore_ui_base.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <stdarg.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <linux/limits.h>
28
29 #include <Ecore_Wayland.h>
30 #include <wayland-client.h>
31 #include <wayland-tbm-client.h>
32 #include <tizen-extension-client-protocol.h>
33
34 #include <Ecore.h>
35 #include <glib-object.h>
36 #include <malloc.h>
37 #include <glib.h>
38 #include <gio/gio.h>
39 #include <stdbool.h>
40 #include <aul.h>
41 #include <aul_svc.h>
42 #include <bundle_internal.h>
43 #include <ttrace.h>
44
45 #include "appcore_base.h"
46 #include "appcore_ui_base.h"
47 #include "appcore_ui_base_private.h"
48 #include "appcore_ui_plugin.h"
49
50 enum app_state {
51         AS_NONE,
52         AS_CREATED,
53         AS_RUNNING,
54         AS_PAUSED,
55         AS_DYING,
56 };
57
58 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_Wl_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_wl_window_find(win_id);
444         ecore_wl_window_activate(win);
445 }
446
447 static void __pause_win(void)
448 {
449         Ecore_Wl_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_wl_window_find(entry->win);
463                 ecore_wl_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_WL_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_WL_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_WL_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_WL_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_WL_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 static void __group_attach()
750 {
751         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
752                 return;
753
754         appcore_ui_base_group_add();
755 }
756
757 static void __group_lower()
758 {
759         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
760                 return;
761         appcore_ui_base_group_remove();
762 }
763
764 EXPORT_API void appcore_ui_base_group_add()
765 {
766         static bool attached = false;
767
768         _DBG("__group_attach");
769         if (attached)
770                 return;
771
772         int wid = __get_main_surface();
773         if (wid == 0) {
774                 _ERR("window wasn't ready");
775                 return;
776         }
777
778         aul_app_group_set_window(wid);
779         attached = true;
780 }
781
782 EXPORT_API void appcore_ui_base_group_remove()
783 {
784         int exit = 0;
785
786         _DBG("__group_lower");
787         aul_app_group_lower(&exit);
788         if (exit) {
789                 _DBG("__group_lower : sub-app!");
790                 if (__context.ops.base.exit)
791                         __context.ops.base.exit(__context.data);
792         }
793 }
794
795 EXPORT_API void appcore_ui_base_window_on_show(int type, void *event)
796 {
797         Ecore_Wl_Event_Window_Show *ev;
798
799         ev = event;
800         if (ev->parent_win != 0) {
801                 /* This is child window. Skip!!! */
802                 return;
803         }
804
805         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
806
807         if (!__find_win((unsigned int)ev->win))
808                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
809         else
810                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
811
812         if (ev->data[0] != 0)
813                 __group_attach();
814 }
815
816 static bool __check_visible(void)
817 {
818         GSList *iter = NULL;
819         struct win_node *entry = NULL;
820
821         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
822
823         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
824                 entry = iter->data;
825                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
826                 if (entry->bfobscured == FALSE)
827                         return true;
828         }
829
830         return false;
831 }
832
833 EXPORT_API void appcore_ui_base_window_on_hide(int type, void *event)
834 {
835         Ecore_Wl_Event_Window_Hide *ev;
836         int bvisibility;
837
838         ev = event;
839         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
840
841         if (__find_win((unsigned int)ev->win)) {
842                 __delete_win((unsigned int)ev->win);
843                 bvisibility = __check_visible();
844                 if (!bvisibility && w_status != WS_PAUSE) {
845                         _DBG(" Go to Pasue state \n");
846                         w_status = WS_PAUSE;
847                         __do_pause();
848                 }
849         }
850 }
851
852 EXPORT_API void appcore_ui_base_window_on_lower(int type, void *event)
853 {
854         Ecore_Wl_Event_Window_Lower *ev;
855
856         ev = event;
857         if (!ev)
858                 return;
859         _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
860         __group_lower();
861 }
862
863 EXPORT_API void appcore_ui_base_window_on_visibility(int type, void *event)
864 {
865         Ecore_Wl_Event_Window_Visibility_Change *ev;
866         int bvisibility;
867
868         ev = event;
869         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
870         bvisibility = __check_visible();
871
872         _DBG("bvisibility %d, w_status %d", bvisibility, w_status);
873
874         if (bvisibility && (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) &&
875                         __context.below_app) {
876                 aul_app_group_activate_below(__context.below_app);
877                 free(__context.below_app);
878                 __context.below_app = NULL;
879         }
880
881         if (bvisibility && w_status != WS_RESUME) {
882                 _DBG(" Go to Resume state\n");
883                 w_status = WS_RESUME;
884                 __do_resume();
885         } else if (!bvisibility && w_status != WS_PAUSE) {
886                 _DBG(" Go to Pasue state \n");
887                 w_status = WS_PAUSE;
888                 __do_pause();
889         } else {
890                 _DBG(" No change state \n");
891         }
892
893 }
894
895 EXPORT_API void appcore_ui_base_window_on_pre_visibility(int type, void *event)
896 {
897         Ecore_Wl_Event_Window_Pre_Visibility_Change *ev = event;
898         bool bvisibility;
899
900         if (ev && ev->type == ECORE_WL_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
901                 __update_win((unsigned int)ev->win, 0, false);
902                 bvisibility = __check_visible();
903
904                 _DBG("bvisibility %d, w_status %d", bvisibility, w_status);
905                 if (bvisibility && w_status != WS_RESUME) {
906                         _DBG(" Go to Resume state\n");
907                         w_status = WS_RESUME;
908                         __do_resume();
909                 }
910         }
911 }
912
913 EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv,
914                 void *data, unsigned int hint)
915 {
916         const char *bg_launch;
917         bundle *b;
918         char appid[PATH_MAX] = {0, };
919         int ret;
920
921         ecore_wl_init(NULL);
922
923         appcore_ui_plugin_init(&ops, argc, argv, &hint);
924         ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
925         if (ret != 0) {
926                 _ERR("Fail to get appid (%d)", getpid());
927                 return -1;
928         }
929         __context.ops = ops;
930         __context.data = data;
931         __context.argc = argc;
932         __context.argv = argv;
933         __context.hint = hint;
934         __context.state = AS_NONE;
935         __context.appid = strdup(appid);
936         __context.resource_reclaiming = true;
937
938         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
939         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
940                 b = bundle_import_from_argv(argc, argv);
941                 if (b) {
942                         bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
943                         if (bg_launch && strcmp(bg_launch, "enable") == 0)
944                                 __set_bg_state();
945
946                         bundle_free(b);
947                 }
948         }
949
950         return appcore_base_init(ops.base, argc, argv, data);
951 }
952
953 EXPORT_API void appcore_ui_base_fini(void)
954 {
955         __del_ecore_events();
956         __finish_wl();
957
958         free(__context.appid);
959         __context.appid = NULL;
960
961         appcore_base_fini();
962         appcore_ui_plugin_fini();
963         ecore_wl_shutdown();
964 }
965
966 EXPORT_API void appcore_ui_base_pause(void)
967 {
968         __do_pause();
969 }
970
971 EXPORT_API void appcore_ui_base_resume(void)
972 {
973         __do_resume();
974 }
975
976 EXPORT_API bool appcore_ui_base_is_resumed(void)
977 {
978         return __context.state == AS_RUNNING;
979 }
980
981 EXPORT_API void appcore_ui_base_exit(void)
982 {
983         if (__context.ops.base.exit)
984                 __context.ops.base.exit(__context.data);
985 }
986
987 EXPORT_API unsigned int appcore_ui_base_get_main_window(void)
988 {
989         return __get_main_window();
990 }
991
992 EXPORT_API unsigned int appcore_ui_base_get_main_surface(void)
993 {
994         return __get_main_surface();
995 }
996
997 EXPORT_API int appcore_ui_base_get_hint(void)
998 {
999         return __context.hint;
1000 }
1001
1002 EXPORT_API bool appcore_ui_base_get_bg_state(void)
1003 {
1004         return __context.bg_state;
1005 }
1006
1007 EXPORT_API void appcore_ui_base_set_bg_state(bool bg_state)
1008 {
1009         __context.bg_state = bg_state;
1010 }
1011
1012 EXPORT_API void appcore_ui_base_set_system_resource_reclaiming(bool enable)
1013 {
1014         __context.resource_reclaiming = enable;
1015 }
1016
1017 static int __on_receive(aul_type type, bundle *b, void *data)
1018 {
1019         return appcore_ui_base_on_receive(type, b);
1020 }
1021
1022 static int __on_create(void *data)
1023 {
1024         return appcore_ui_base_on_create();
1025 }
1026
1027 static int __on_terminate(void *data)
1028 {
1029         return appcore_ui_base_on_terminate();
1030 }
1031
1032 static int __on_pause(void *data)
1033 {
1034         return appcore_ui_base_on_pause();
1035 }
1036
1037 static int __on_resume(void *data)
1038 {
1039         return appcore_ui_base_on_resume();
1040 }
1041
1042 static void __window_on_show(int type, void *event, void *data)
1043 {
1044         appcore_ui_base_window_on_show(type, event);
1045 }
1046
1047 static void __window_on_hide(int type, void *event, void *data)
1048 {
1049         appcore_ui_base_window_on_hide(type, event);
1050 }
1051
1052 static void __window_on_lower(int type, void *event, void *data)
1053 {
1054         appcore_ui_base_window_on_lower(type, event);
1055 }
1056
1057 static void __window_on_visibility(int type, void *event, void *data)
1058 {
1059         appcore_ui_base_window_on_visibility(type, event);
1060 }
1061
1062 static void __window_on_pre_visibility(int type, void *event, void *data)
1063 {
1064         appcore_ui_base_window_on_pre_visibility(type, event);
1065 }
1066
1067 EXPORT_API appcore_ui_base_ops appcore_ui_base_get_default_ops(void)
1068 {
1069         appcore_ui_base_ops ops;
1070
1071         ops.base = appcore_base_get_default_ops();
1072
1073         /* override methods */
1074         ops.base.create = __on_create;
1075         ops.base.terminate = __on_terminate;
1076         ops.base.receive = __on_receive;
1077         ops.base.init = NULL;
1078         ops.base.finish = NULL;
1079         ops.base.run = NULL;
1080         ops.base.exit = NULL;
1081
1082         ops.pause = __on_pause;
1083         ops.resume = __on_resume;
1084         ops.window.show = __window_on_show;
1085         ops.window.hide = __window_on_hide;
1086         ops.window.lower = __window_on_lower;
1087         ops.window.visibility = __window_on_visibility;
1088         ops.window.pre_visibility = __window_on_pre_visibility;
1089
1090         return ops;
1091 }
1092
1093