2 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <sys/types.h>
18 #include <sys/socket.h>
26 #include <linux/limits.h>
28 #include <Ecore_Wayland.h>
29 #include <wayland-client.h>
30 #include <wayland-tbm-client.h>
31 #include <tizen-extension-client-protocol.h>
34 #include <glib-object.h>
41 #include <bundle_internal.h>
44 #include "appcore_base.h"
45 #include "appcore_ui_base.h"
46 #include "appcore_ui_base_private.h"
47 #include "appcore_ui_plugin.h"
57 typedef struct _appcore_ui_base_context {
58 appcore_ui_base_ops ops;
67 Ecore_Event_Handler *hshow;
68 Ecore_Event_Handler *hhide;
69 Ecore_Event_Handler *hvchange;
70 Ecore_Event_Handler *hlower;
71 Ecore_Event_Handler *hpvchange;
72 } appcore_ui_base_context;
75 static bool b_active = false;
76 static bool first_launch = true;
84 static GSList *g_winnode_list;
85 static appcore_ui_base_context __context;
86 static struct wl_display *dsp;
87 static struct wl_registry *reg;
88 static struct tizen_policy *tz_policy;
89 static bool bg_state = false;
91 static void __wl_listener_cb(void *data, struct wl_registry *reg,
92 uint32_t id, const char *interface, uint32_t ver)
94 if (interface && !strcmp(interface, "tizen_policy")) {
96 tz_policy = wl_registry_bind(reg, id,
97 &tizen_policy_interface, 1);
101 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
107 static const struct wl_registry_listener reg_listener = {
109 __wl_listener_remove_cb
112 static Eina_Bool __stub_show_cb(void *data, int type, void *event)
114 if (__context.ops.window.show)
115 __context.ops.window.show(type, event, __context.data);
117 return ECORE_CALLBACK_RENEW;
120 static Eina_Bool __stub_hide_cb(void *data, int type, void *event)
122 if (__context.ops.window.hide)
123 __context.ops.window.hide(type, event, __context.data);
125 return ECORE_CALLBACK_RENEW;
128 static Eina_Bool __stub_visibility_cb(void *data, int type, void *event)
130 if (__context.ops.window.visibility)
131 __context.ops.window.visibility(type, event, __context.data);
133 return ECORE_CALLBACK_RENEW;
136 static Eina_Bool __stub_lower_cb(void *data, int type, void *event)
138 if (__context.ops.window.lower)
139 __context.ops.window.lower(type, event, __context.data);
141 return ECORE_CALLBACK_RENEW;
144 static Eina_Bool __stub_pre_visibility_cb(void *data, int type, void *event)
146 if (__context.ops.window.pre_visibility)
147 __context.ops.window.pre_visibility(type, event, __context.data);
149 return ECORE_CALLBACK_RENEW;
152 static void __prepare_to_suspend(void)
154 int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
156 if (appcore_base_is_bg_allowed() && !appcore_base_is_suspended()) {
157 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
158 appcore_base_toggle_suspended_state();
162 static void __exit_from_suspend(void)
164 int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
166 if (appcore_base_is_suspended()) {
167 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
168 appcore_base_toggle_suspended_state();
172 static void __do_pause(void)
174 if (__context.state == AS_RUNNING) {
175 if (__context.ops.pause) {
176 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
177 __context.ops.pause(__context.data);
178 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
181 __context.state = AS_PAUSED;
182 __prepare_to_suspend();
184 aul_status_update(STATUS_BG);
187 static void __do_resume(void)
189 if (__context.state == AS_PAUSED || __context.state == AS_CREATED) {
190 __exit_from_suspend();
191 if (__context.ops.resume) {
192 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", __context.appid);
193 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
194 __context.ops.resume(__context.data);
195 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
196 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", __context.appid);
197 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]", __context.appid);
199 if ((__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) &&
200 __context.below_app) {
201 aul_app_group_activate_below(__context.below_app);
202 free(__context.below_app);
203 __context.below_app = NULL;
205 __context.state = AS_RUNNING;
208 aul_status_update(STATUS_VISIBLE);
211 static GSList *__find_win(unsigned int win)
216 for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
218 if (t && t->win == win)
225 static int __get_main_window(void)
227 struct win_node *entry = NULL;
229 if (g_winnode_list != NULL) {
230 entry = g_winnode_list->data;
231 return (unsigned int) entry->win;
237 static int __get_main_surface(void)
239 struct win_node *entry = NULL;
241 if (g_winnode_list != NULL) {
242 entry = g_winnode_list->data;
243 return (unsigned int) entry->surf;
249 static bool __add_win(unsigned int win, unsigned int surf)
254 _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
259 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
263 t = calloc(1, sizeof(struct win_node));
269 t->bfobscured = FALSE;
271 g_winnode_list = g_slist_append(g_winnode_list, t);
276 static bool __delete_win(unsigned int win)
283 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
289 g_winnode_list = g_slist_delete_link(g_winnode_list, f);
294 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
299 _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
305 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
309 t = (struct win_node *)f->data;
313 t->bfobscured = bfobscured;
318 static void __raise_win(void)
320 Ecore_Wl_Window *win;
323 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
326 win_id = __get_main_window();
328 _DBG("Raise window: %d", win_id);
329 win = ecore_wl_window_find(win_id);
330 ecore_wl_window_activate(win);
333 static void __pause_win(void)
335 Ecore_Wl_Window *win;
336 GSList *wlist = g_winnode_list;
337 struct win_node *entry = NULL;
339 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
342 _DBG("Pause window");
347 _DBG("Pause window: %d", entry->win);
348 win = ecore_wl_window_find(entry->win);
349 ecore_wl_window_iconified_set(win, EINA_TRUE);
355 static int __init_wl(void)
357 _DBG("initialize wayland");
358 dsp = wl_display_connect(NULL);
360 _ERR("Failed to connect wl display");
364 reg = wl_display_get_registry(dsp);
366 _ERR("Failed to get registry");
367 wl_display_disconnect(dsp);
371 wl_registry_add_listener(reg, ®_listener, NULL);
372 wl_display_roundtrip(dsp);
375 _ERR("Failed to get tizen policy interface");
376 wl_registry_destroy(reg);
377 wl_display_disconnect(dsp);
384 static void __finish_wl(void)
387 tizen_policy_destroy(tz_policy);
392 wl_registry_destroy(reg);
397 wl_display_disconnect(dsp);
402 static void __set_bg_state(void)
404 if (!tz_policy && __init_wl() < 0)
407 tizen_policy_set_background_state(tz_policy, getpid());
408 wl_display_roundtrip(dsp);
410 _DBG("bg state: %d", bg_state);
413 static void __unset_bg_state(void)
418 tizen_policy_unset_background_state(tz_policy, getpid());
419 wl_display_roundtrip(dsp);
421 _DBG("bg state: %d", bg_state);
424 static void __do_start(bundle *b)
426 const char *bg_launch;
427 const char *below_app;
429 if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) {
430 if (__context.below_app) {
431 free(__context.below_app);
432 __context.below_app = NULL;
435 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
437 __context.below_app = strdup(below_app);
441 first_launch = FALSE;
445 if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
446 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
447 if (bg_launch && strcmp(bg_launch, "enable") == 0) {
448 if (!bg_state && __context.state != AS_RUNNING)
456 if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL) {
462 EXPORT_API int appcore_ui_base_on_receive(aul_type type, bundle *b)
464 if (__context.state == AS_DYING) {
465 _ERR("Skip the event in dying state");
469 if (type == AUL_TERMINATE_BGAPP && __context.state != AS_PAUSED)
472 if (type == AUL_START)
473 __exit_from_suspend();
475 appcore_base_on_receive(type, b);
488 case AUL_TERMINATE_BGAPP:
489 _DBG("[APP %d] is paused. TERMINATE", getpid());
490 __context.state = AS_DYING;
491 aul_status_update(STATUS_DYING);
492 if (__context.ops.base.exit)
493 __context.ops.base.exit(__context.data);
505 EXPORT_API int appcore_ui_base_on_create(void)
507 appcore_base_on_create();
509 __context.hshow = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __stub_show_cb, NULL);
510 __context.hhide = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __stub_hide_cb, NULL);
511 __context.hvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
512 __stub_visibility_cb, NULL);
513 __context.hlower = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER, __stub_lower_cb, NULL);
514 __context.hpvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE,
515 __stub_pre_visibility_cb, NULL);
516 __context.state = AS_CREATED;
517 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]", __context.appid);
522 EXPORT_API int appcore_ui_base_on_terminate(void)
524 if (__context.state == AS_RUNNING) {
525 if (__context.ops.pause)
526 __context.ops.pause(__context.data);
529 __context.state = AS_DYING;
531 appcore_base_on_terminate();
536 EXPORT_API int appcore_ui_base_on_pause(void)
541 EXPORT_API int appcore_ui_base_on_resume(void)
546 EXPORT_API int appcore_ui_base_on_control(bundle *b)
548 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", __context.appid);
549 appcore_base_on_control(b);
550 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", __context.appid);
555 static void __group_attach()
557 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
560 appcore_ui_base_group_add();
563 static void __group_lower()
565 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
567 appcore_ui_base_group_remove();
570 EXPORT_API void appcore_ui_base_group_add()
572 static bool attached = false;
574 _DBG("__group_attach");
578 int wid = __get_main_surface();
580 _ERR("window wasn't ready");
584 aul_app_group_set_window(wid);
588 EXPORT_API void appcore_ui_base_group_remove()
592 _DBG("__group_lower");
593 aul_app_group_lower(&exit);
595 _DBG("__group_lower : sub-app!");
596 if (__context.ops.base.exit)
597 __context.ops.base.exit(__context.data);
601 EXPORT_API void appcore_ui_base_window_on_show(int type, void *event)
603 Ecore_Wl_Event_Window_Show *ev;
606 if (ev->parent_win != 0) {
607 /* This is child window. Skip!!! */
611 _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
613 if (!__find_win((unsigned int)ev->win))
614 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
616 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
618 if (ev->data[0] != 0)
622 static bool __check_visible(void)
625 struct win_node *entry = NULL;
627 _DBG("[EVENT_TEST][EVENT] __check_visible\n");
629 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
631 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
632 if (entry->bfobscured == FALSE)
639 EXPORT_API void appcore_ui_base_window_on_hide(int type, void *event)
641 Ecore_Wl_Event_Window_Hide *ev;
645 _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
647 if (__find_win((unsigned int)ev->win)) {
648 __delete_win((unsigned int)ev->win);
649 bvisibility = __check_visible();
650 if (!bvisibility && b_active == TRUE) {
651 _DBG(" Go to Pasue state \n");
658 EXPORT_API void appcore_ui_base_window_on_lower(int type, void *event)
660 Ecore_Wl_Event_Window_Lower *ev;
665 _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
669 EXPORT_API void appcore_ui_base_window_on_visibility(int type, void *event)
671 Ecore_Wl_Event_Window_Visibility_Change *ev;
675 __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
676 bvisibility = __check_visible();
678 _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
680 if (bvisibility && b_active == FALSE) {
681 _DBG(" Go to Resume state\n");
684 } else if (!bvisibility && b_active == TRUE) {
685 _DBG(" Go to Pasue state \n");
689 _DBG(" No change state \n");
694 EXPORT_API void appcore_ui_base_window_on_pre_visibility(int type, void *event)
696 Ecore_Wl_Event_Window_Pre_Visibility_Change *ev = event;
699 if (ev && ev->type == ECORE_WL_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
700 __update_win((unsigned int)ev->win, 0, false);
701 bvisibility = __check_visible();
703 _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
704 if (bvisibility && b_active == FALSE) {
705 _DBG(" Go to Resume state\n");
712 EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv,
713 void *data, unsigned int hint)
715 const char *bg_launch;
717 char appid[PATH_MAX] = {0, };
719 appcore_ui_plugin_init(&ops, argc, argv, &hint);
720 aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
722 __context.data = data;
723 __context.argc = argc;
724 __context.argv = argv;
725 __context.hint = hint;
726 __context.state = AS_NONE;
727 __context.appid = strdup(appid);
729 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
730 if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
731 b = bundle_import_from_argv(argc, argv);
733 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
734 if (bg_launch && strcmp(bg_launch, "enable") == 0)
741 return appcore_base_init(ops.base, argc, argv, data);
744 EXPORT_API void appcore_ui_base_fini(void)
747 ecore_event_handler_del(__context.hshow);
749 ecore_event_handler_del(__context.hhide);
750 if (__context.hvchange)
751 ecore_event_handler_del(__context.hvchange);
752 if (__context.hlower)
753 ecore_event_handler_del(__context.hlower);
754 if (__context.hpvchange)
755 ecore_event_handler_del(__context.hpvchange);
759 free(__context.appid);
760 __context.appid = NULL;
762 appcore_ui_plugin_fini();
766 EXPORT_API void appcore_ui_base_pause(void)
771 EXPORT_API void appcore_ui_base_resume(void)
776 EXPORT_API bool appcore_ui_base_is_resumed(void)
778 return __context.state == AS_RUNNING;
781 EXPORT_API void appcore_ui_base_exit(void)
783 if (__context.ops.base.exit)
784 __context.ops.base.exit(__context.data);
787 EXPORT_API unsigned int appcore_ui_base_get_main_window(void)
789 return __get_main_window();
792 EXPORT_API unsigned int appcore_ui_base_get_main_surface(void)
794 return __get_main_surface();
797 EXPORT_API int appcore_ui_base_get_hint(void)
799 return __context.hint;
802 static int __on_receive(aul_type type, bundle *b, void *data)
804 return appcore_ui_base_on_receive(type, b);
807 static int __on_create(void *data)
809 return appcore_ui_base_on_create();
812 static int __on_terminate(void *data)
814 return appcore_ui_base_on_terminate();
817 static int __on_pause(void *data)
819 return appcore_ui_base_on_pause();
822 static int __on_resume(void *data)
824 return appcore_ui_base_on_resume();
827 static void __window_on_show(int type, void *event, void *data)
829 appcore_ui_base_window_on_show(type, event);
832 static void __window_on_hide(int type, void *event, void *data)
834 appcore_ui_base_window_on_hide(type, event);
837 static void __window_on_lower(int type, void *event, void *data)
839 appcore_ui_base_window_on_lower(type, event);
842 static void __window_on_visibility(int type, void *event, void *data)
844 appcore_ui_base_window_on_visibility(type, event);
847 static void __window_on_pre_visibility(int type, void *event, void *data)
849 appcore_ui_base_window_on_pre_visibility(type, event);
852 EXPORT_API appcore_ui_base_ops appcore_ui_base_get_default_ops(void)
854 appcore_ui_base_ops ops;
856 ops.base = appcore_base_get_default_ops();
858 /* override methods */
859 ops.base.create = __on_create;
860 ops.base.terminate = __on_terminate;
861 ops.base.receive = __on_receive;
862 ops.base.init = NULL;
863 ops.base.finish = NULL;
865 ops.base.exit = NULL;
867 ops.pause = __on_pause;
868 ops.resume = __on_resume;
869 ops.window.show = __window_on_show;
870 ops.window.hide = __window_on_hide;
871 ops.window.lower = __window_on_lower;
872 ops.window.visibility = __window_on_visibility;
873 ops.window.pre_visibility = __window_on_pre_visibility;