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