2 * Copyright (c) 2015 - 2017 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.
22 #include <bundle_internal.h>
26 #include <glib-object.h>
28 #include <Elementary.h>
29 #include <widget_errno.h>
30 #include <widget_instance.h>
31 #include <aul_app_com.h>
32 #include <Ecore_Wayland.h>
33 #include <system_info.h>
35 #include <vconf-internal-keys.h>
36 #include <screen_connector_provider.h>
37 #include <appcore_multiwindow_base.h>
39 #include "widget_app.h"
40 #include "widget-log.h"
41 #include "widget-private.h"
42 #include "widget_app_internal.h"
48 #define LOG_TAG "CAPI_WIDGET_APPLICATION"
49 #define APP_TYPE_WIDGET "widgetapp"
50 #define STATUS_FOREGROUND "fg"
51 #define STATUS_BACKGROUND "bg"
61 struct widget_class_context {
62 widget_instance_lifecycle_callback_s callback;
66 struct widget_app_context {
67 widget_app_lifecycle_callback_s callback;
72 struct widget_foreach_context {
73 widget_context_cb callback;
77 struct app_event_info {
78 app_event_type_e type;
82 struct app_event_handler {
83 app_event_type_e type;
89 struct _widget_context {
93 static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = {
94 [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
95 [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
96 [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
97 [APP_EVENT_DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
98 [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
99 [APP_EVENT_SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
102 static struct widget_app_context __context;
103 static char *__appid;
104 static char *__package_id;
105 static bool __fg_signal;
106 char *_viewer_endpoint;
108 static bool __is_widget_feature_enabled(void)
110 static bool feature = false;
111 static bool retrieved = false;
114 if (retrieved == true)
117 ret = system_info_get_platform_bool(
118 "http://tizen.org/feature/shell.appwidget", &feature);
119 if (ret != SYSTEM_INFO_ERROR_NONE) {
120 _E("failed to get system info"); /* LCOV_EXCL_LINE */
121 return false; /* LCOV_EXCL_LINE */
129 /* LCOV_EXCL_START */
130 static void __on_poweroff(keynode_t *key, void *data)
134 val = vconf_keynode_get_int(key);
136 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
137 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
138 _I("power off changed: %d", val);
141 case VCONFKEY_SYSMAN_POWER_OFF_NONE:
142 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
150 static int __widget_app_create(void *data)
152 char pkgid[256] = {0, };
154 appcore_multiwindow_base_on_create();
155 app_get_id(&__appid);
156 if (aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0)
157 __package_id = strdup(pkgid);
159 if (!__package_id || !__appid) {
160 _E("__package_id is NULL");
164 screen_connector_provider_init();
165 vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, __on_poweroff, NULL);
167 if (__context.callback.create == NULL) {
168 _E("__context.callback.create(is NULL");
172 if (__context.callback.create(__context.data) == NULL) {
173 _E("app_create_cb() returns NULL");
177 _D("widget app is created");
181 static int __widget_app_terminate(void *data)
183 if (__context.callback.terminate)
184 __context.callback.terminate(__context.data);
186 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, __on_poweroff);
187 screen_connector_provider_fini();
189 if (_viewer_endpoint) {
190 free(_viewer_endpoint);
191 _viewer_endpoint = NULL;
204 appcore_multiwindow_base_on_terminate();
206 _D("widget app is terminated");
210 static int __send_lifecycle_event(const char *class_id, const char *instance_id,
213 bundle *b = bundle_create();
217 _E("out of memory"); /* LCOV_EXCL_LINE */
218 return -1; /* LCOV_EXCL_LINE */
221 bundle_add_str(b, AUL_K_WIDGET_ID, class_id);
222 bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
223 bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int));
224 bundle_add_str(b, AUL_K_PKGID, __package_id);
226 _D("send lifecycle %s(%d)", instance_id, status);
227 ret = aul_app_com_send("widget.status", b);
229 _E("send lifecycle error:%d", ret); /* LCOV_EXCL_LINE */
236 static int __send_update_status(const char *class_id, const char *instance_id,
237 int status, bundle *extra)
241 bundle_raw *raw = NULL;
246 _E("out of memory"); /* LCOV_EXCL_LINE */
247 return -1; /* LCOV_EXCL_LINE */
250 bundle_add_str(b, AUL_K_WIDGET_ID, class_id);
251 bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
252 bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int));
255 bundle_encode(extra, &raw, &len);
256 bundle_add_str(b, WIDGET_K_CONTENT_INFO, (const char *)raw);
257 aul_widget_instance_add(class_id, instance_id);
260 _D("send update %s(%d) to %s", instance_id, status, _viewer_endpoint);
261 aul_app_com_send(_viewer_endpoint, b);
264 case WIDGET_INSTANCE_EVENT_CREATE:
265 lifecycle = WIDGET_LIFE_CYCLE_EVENT_CREATE;
267 case WIDGET_INSTANCE_EVENT_DESTROY:
268 lifecycle = WIDGET_LIFE_CYCLE_EVENT_DESTROY;
270 case WIDGET_INSTANCE_EVENT_PAUSE:
271 lifecycle = WIDGET_LIFE_CYCLE_EVENT_PAUSE;
273 case WIDGET_INSTANCE_EVENT_RESUME:
274 lifecycle = WIDGET_LIFE_CYCLE_EVENT_RESUME;
279 __send_lifecycle_event(class_id, instance_id, lifecycle);
288 static void __instance_resume(const char *class_id, const char *id, bundle *b)
290 appcore_multiwindow_base_instance_h cxt;
292 cxt = appcore_multiwindow_base_instance_find(id);
295 _E("context not found: %s", id);
299 appcore_multiwindow_base_instance_resume(cxt);
301 __send_update_status(class_id, id,
302 WIDGET_INSTANCE_EVENT_RESUME, NULL);
304 _D("Send fg signal to resourceD");
305 aul_send_app_status_change_signal(getpid(),
314 static void __instance_pause(const char *class_id, const char *id, bundle *b)
316 appcore_multiwindow_base_instance_h cxt;
318 cxt = appcore_multiwindow_base_instance_find(id);
321 _E("context not found: %s", id);
325 appcore_multiwindow_base_instance_pause(cxt);
328 _D("Send bg signal to resourceD");
329 aul_send_app_status_change_signal(getpid(),
338 static void __instance_resize(const char *class_id, const char *id, bundle *b)
340 appcore_multiwindow_base_instance_h cxt;
341 struct widget_class_context *class_cxt;
342 const appcore_multiwindow_base_class *cls;
343 struct widget_extra *we;
350 cxt = appcore_multiwindow_base_instance_find(id);
353 _E("context not found: %s", id);
357 cls = appcore_multiwindow_base_instance_get_class(cxt);
361 class_cxt = cls->data;
367 we = appcore_multiwindow_base_instance_get_extra(cxt);
369 _E("widget extra is NULL");
373 bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
374 bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
377 w = (int)g_ascii_strtoll(w_str, &remain, 10);
380 h = (int)g_ascii_strtoll(h_str, &remain, 10);
383 evas_object_resize(we->win, w, h);
385 _E("unable to find window of %s", id);
387 if (class_cxt->callback.resize)
388 class_cxt->callback.resize(cxt, w, h, class_cxt->data);
389 _D("%s is resized to %dx%d", id, w, h);
390 __send_update_status(class_id, id,
391 WIDGET_INSTANCE_EVENT_SIZE_CHANGED, NULL);
394 static void __inst_cb(const char *class_id, const char *id,
395 appcore_multiwindow_base_instance_h cxt, void *data)
397 struct widget_class_context *class_cxt;
398 const appcore_multiwindow_base_class *cls;
399 bundle *content = NULL;
400 char *content_raw = NULL;
401 char *force_str = NULL;
406 _E("bundle is NULL");
410 cls = appcore_multiwindow_base_instance_get_class(cxt);
416 class_cxt = cls->data;
418 _E("class context is NULL");
422 if (!class_cxt->callback.update) {
423 _E("update callback is NULL");
427 bundle_get_str(b, WIDGET_K_FORCE, &force_str);
429 if (force_str && strcmp(force_str, "true") == 0)
434 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw);
437 content = bundle_decode((const bundle_raw *)content_raw, strlen(content_raw));
438 class_cxt->callback.update(cxt, content, force, class_cxt->data);
439 __send_update_status(class_id, id,
440 WIDGET_INSTANCE_EVENT_UPDATE, NULL);
441 _D("updated:%s", id);
444 bundle_free(content);
447 static void __instance_update(const char *class_id, const char *id, bundle *b)
449 appcore_multiwindow_base_instance_h cxt;
452 appcore_multiwindow_base_instance_foreach(class_id, __inst_cb, b);
456 cxt = appcore_multiwindow_base_instance_find(id);
459 _E("context not found: %s", id);
463 __inst_cb(class_id, id, cxt, b);
466 static void __instance_create(const char *class_id, const char *id, bundle *b)
468 struct widget_extra *we;
469 char *content = NULL;
471 we = (struct widget_extra *)calloc(1, sizeof(struct widget_extra));
477 we->instance_id = strdup(id);
479 appcore_multiwindow_base_instance_run(class_id, id, we);
482 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
484 we->content = strdup(content);
488 static void __check_empty_instance(void)
490 int cnt = appcore_multiwindow_base_instance_get_cnt();
496 static void __instance_destroy(const char *class_id, const char *id, bundle *b)
498 appcore_multiwindow_base_instance_h cxt;
499 struct widget_extra *we;
501 cxt = appcore_multiwindow_base_instance_find(id);
503 _E("could not find widget obj: %s, clear amd info", id);
504 aul_widget_instance_del(class_id, id);
508 we = appcore_multiwindow_base_instance_get_extra(cxt);
510 appcore_multiwindow_base_instance_exit(cxt);
511 free(we->instance_id);
514 __check_empty_instance();
517 static int __widget_app_control(bundle *b, void *data)
519 char *class_id = NULL;
521 char *operation = NULL;
523 appcore_multiwindow_base_on_control(b);
525 bundle_get_str(b, WIDGET_K_CLASS, &class_id);
526 /* for previous version compatibility, use appid for default class id */
527 if (class_id == NULL)
530 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
531 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
534 _E("operation is NULL");
538 if (strcmp(operation, "create") == 0) {
539 __instance_create(class_id, id, b);
540 } else if (strcmp(operation, "resize") == 0) {
541 __instance_resize(class_id, id, b);
542 } else if (strcmp(operation, "update") == 0) {
543 __instance_update(class_id, id, b);
544 } else if (strcmp(operation, "destroy") == 0) {
545 __instance_destroy(class_id, id, b);
546 } else if (strcmp(operation, "resume") == 0) {
547 __instance_resume(class_id, id, b);
548 } else if (strcmp(operation, "pause") == 0) {
549 __instance_pause(class_id, id, b);
550 } else if (strcmp(operation, "terminate") == 0) {
551 __instance_destroy(class_id, id, b);
557 static void __inst_resume_cb(const char *class_id, const char *id,
558 appcore_multiwindow_base_instance_h cxt, void *data)
560 __instance_resume(class_id, id, data);
563 static void __get_content(bundle *b)
565 char *instance_id = NULL;
566 appcore_multiwindow_base_instance_h cxt;
567 struct widget_extra *we;
569 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
571 _E("instance id is NULL");
575 cxt = appcore_multiwindow_base_instance_find(instance_id);
577 _E("could not find widget obj: %s", instance_id);
581 we = appcore_multiwindow_base_instance_get_extra(cxt);
583 _E("widget extra is NULL");
588 bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, we->content);
589 _D("content info of %s found", instance_id);
591 bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, "");
592 _D("empty content info added");
596 static int __widget_app_receive(aul_type type, bundle *b, void *data)
598 appcore_multiwindow_base_on_receive(type, b);
602 appcore_multiwindow_base_instance_foreach_full(__inst_resume_cb, b);
607 case AUL_WIDGET_CONTENT:
617 static int __widget_app_init(int argc, char **argv, void *data)
619 elm_init(argc, argv);
623 static void __widget_app_finish(void)
627 /* Check Loader case */
628 if (getenv("AUL_LOADER_INIT")) {
629 unsetenv("AUL_LOADER_INIT");
634 static void __widget_app_run(void *data)
639 static void __widget_app_exit(void *data)
644 EXPORT_API int widget_app_main(int argc, char **argv,
645 widget_app_lifecycle_callback_s *callback, void *user_data)
648 char *viewer_endpoint = NULL;
650 if (!__is_widget_feature_enabled()) {
651 _E("not supported"); /* LCOV_EXCL_LINE */
652 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
655 if (argc <= 0 || argv == NULL || callback == NULL)
656 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
659 if (__context.dirty) {
660 _E("Already started");
661 return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL);
664 if (callback->create == NULL)
665 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
667 "widget_app_create_cb() callback must be "
670 appcore_multiwindow_base_ops ops = appcore_multiwindow_base_get_default_ops();
672 /* override methods */
673 ops.base.create = __widget_app_create;
674 ops.base.control = __widget_app_control;
675 ops.base.terminate = __widget_app_terminate;
676 ops.base.receive = __widget_app_receive;
677 ops.base.init = __widget_app_init;
678 ops.base.finish = __widget_app_finish;
679 ops.base.run = __widget_app_run;
680 ops.base.exit = __widget_app_exit;
682 __context.callback = *callback;
683 __context.data = user_data;
684 kb = bundle_import_from_argv(argc, argv);
686 bundle_get_str(kb, WIDGET_K_ENDPOINT, &viewer_endpoint);
687 if (viewer_endpoint) {
688 _D("viewer endpoint :%s", viewer_endpoint);
689 _viewer_endpoint = strdup(viewer_endpoint);
691 _E("endpoint is missing");
696 _E("failed to get launch argv"); /* LCOV_EXCL_LINE */
697 return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL);
700 __context.dirty = true;
701 appcore_multiwindow_base_init(ops, argc, argv, NULL);
702 appcore_multiwindow_base_fini();
703 __context.dirty = false;
705 return WIDGET_ERROR_NONE;
708 EXPORT_API int widget_app_exit(void)
710 if (!__is_widget_feature_enabled()) {
711 _E("not supported"); /* LCOV_EXCL_LINE */
712 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
715 appcore_multiwindow_base_exit();
716 aul_widget_notify_exit();
718 return WIDGET_ERROR_NONE;
721 static gboolean __finish_event_cb(gpointer user_data)
723 appcore_multiwindow_base_instance_h cxt = user_data;
726 const char *class_id;
729 _E("user_data is NULL");
733 id = appcore_multiwindow_base_instance_get_id(cxt);
734 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
742 bundle_add_str(b, WIDGET_K_OPERATION, "terminate");
743 __instance_destroy(class_id, id, b);
749 EXPORT_API int widget_app_terminate_context(widget_context_h context)
751 if (!__is_widget_feature_enabled()) {
752 _E("not supported"); /* LCOV_EXCL_LINE */
753 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
757 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
760 g_idle_add(__finish_event_cb, context);
761 return WIDGET_ERROR_NONE;
764 static void __inst_full_cb(const char *class_id, const char *id,
765 appcore_multiwindow_base_instance_h cxt, void *data)
767 struct widget_foreach_context *foreach_context = data;
772 if (foreach_context->callback)
773 foreach_context->callback(cxt, foreach_context->data);
776 EXPORT_API int widget_app_foreach_context(widget_context_cb cb, void *data)
778 struct widget_foreach_context foreach_context;
780 if (!__is_widget_feature_enabled()) {
781 _E("not supported"); /* LCOV_EXCL_LINE */
782 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
786 _E("callback is NULL");
787 return WIDGET_ERROR_INVALID_PARAMETER;
790 foreach_context.callback = cb;
791 foreach_context.data = data;
792 appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context);
794 return WIDGET_ERROR_NONE;
797 int __event_cb(void *event, void *data)
799 app_event_handler_h handler = data;
801 struct app_event_info app_event;
803 app_event.type = handler->type;
804 app_event.value = event;
807 handler->cb(&app_event, handler->data);
812 EXPORT_API int widget_app_add_event_handler(app_event_handler_h *event_handler,
813 app_event_type_e event_type, app_event_cb callback,
818 app_event_handler_h handler;
820 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
822 return WIDGET_ERROR_FAULT;
825 return WIDGET_ERROR_NOT_SUPPORTED;
827 if (event_handler == NULL || callback == NULL)
828 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
830 if (event_type < APP_EVENT_LOW_MEMORY
831 || event_type > APP_EVENT_REGION_FORMAT_CHANGED)
832 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
834 if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
835 return widget_app_error(WIDGET_ERROR_NOT_SUPPORTED, __FUNCTION__, NULL);
838 handler = calloc(1, sizeof(struct app_event_handler));
840 return widget_app_error(WIDGET_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create handler");
842 handler->type = event_type;
843 handler->cb = callback;
844 handler->data = user_data;
845 handler->raw = appcore_base_add_event(__app_event_converter[event_type], __event_cb, handler);
846 *event_handler = handler;
848 return WIDGET_ERROR_NONE;
851 EXPORT_API int widget_app_remove_event_handler(app_event_handler_h
857 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
859 return WIDGET_ERROR_FAULT;
862 return WIDGET_ERROR_NOT_SUPPORTED;
864 app_event_type_e type;
866 if (event_handler == NULL)
867 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
869 type = event_handler->type;
870 if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_REGION_FORMAT_CHANGED)
871 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
873 r = appcore_base_remove_event(event_handler->raw);
875 return widget_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid raw handler");
879 return WIDGET_ERROR_NONE;
882 EXPORT_API const char *widget_app_get_id(widget_context_h context)
884 if (!__is_widget_feature_enabled()) {
885 _E("not supported"); /* LCOV_EXCL_LINE */
886 set_last_result(WIDGET_ERROR_NOT_SUPPORTED); /* LCOV_EXCL_LINE */
887 return NULL; /* LCOV_EXCL_LINE */
891 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
895 set_last_result(WIDGET_ERROR_NONE);
896 return appcore_multiwindow_base_instance_get_id(context);
899 static void __win_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
902 plug_id = evas_object_data_del(obj, "___PLUGID");
906 EXPORT_API int widget_app_get_elm_win(widget_context_h context,
909 Evas_Object *ret_win;
910 Ecore_Wl_Window *wl_win;
911 struct wl_surface *surface;
912 struct widget_extra *we;
917 appcore_multiwindow_base_instance_h cxt;
919 if (!__is_widget_feature_enabled()) {
920 _E("not supported"); /* LCOV_EXCL_LINE */
921 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
924 if (context == NULL || win == NULL)
925 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
928 cxt = (appcore_multiwindow_base_instance_h)context;
929 id = appcore_multiwindow_base_instance_get_id(cxt);
930 ret_win = elm_win_add(NULL, id, ELM_WIN_BASIC);
931 if (ret_win == NULL) {
932 _E("failed to create window"); /* LCOV_EXCL_LINE */
933 goto fault; /* LCOV_EXCL_LINE */
936 elm_win_wm_rotation_preferred_rotation_set(ret_win, -1);
937 elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1);
939 wl_win = elm_win_wl_window_get(ret_win);
940 if (wl_win == NULL) {
941 _E("failed to get wayland window"); /* LCOV_EXCL_LINE */
945 surface = ecore_wl_window_surface_get(wl_win);
946 if (surface == NULL) {
947 _E("failed to get surface"); /* LCOV_EXCL_LINE */
948 goto fault; /* LCOV_EXCL_LINE */
950 screen_connector_provider_remote_enable(id, surface);
952 ecore_wl_window_class_name_set(wl_win, id);
953 elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1");
956 we = appcore_multiwindow_base_instance_get_extra(cxt);
958 win_id = ecore_wl_window_id_get(wl_win);
960 /* Set data to use in accessibility */
961 snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid());
962 evas_object_data_set(ret_win, "___PLUGID", strdup(buffer));
963 evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL);
964 appcore_multiwindow_base_window_bind(cxt, wl_win);
966 _D("window created: %d", win_id);
968 return WIDGET_ERROR_NONE;
971 if (ret_win) /* LCOV_EXCL_LINE */
972 evas_object_del(ret_win); /* LCOV_EXCL_LINE */
974 return WIDGET_ERROR_FAULT; /* LCOV_EXCL_LINE */
977 static void __instance_drop(appcore_multiwindow_base_instance_h cxt)
979 struct widget_extra *we;
981 we = appcore_multiwindow_base_instance_get_extra(cxt);
982 appcore_multiwindow_base_instance_drop(cxt);
983 free(we->instance_id);
986 __check_empty_instance();
989 static void __stub_create(appcore_multiwindow_base_instance_h context, void *data)
991 struct widget_class_context *cxt = data;
992 struct widget_extra *we;
994 bundle *content_info = NULL;
996 char *class_id = NULL;
997 char *operation = NULL;
998 char *content = NULL;
1001 char *remain = NULL;
1006 appcore_multiwindow_base_class_on_create(context);
1007 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1010 bundle_get_str(b, WIDGET_K_CLASS, &class_id);
1011 /* for previous version compatibility, use appid for default class id */
1012 if (class_id == NULL)
1015 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
1016 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
1019 _E("no operation provided");
1023 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
1024 bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
1025 bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
1028 w = (int)g_ascii_strtoll(w_str, &remain, 10);
1031 h = (int)g_ascii_strtoll(h_str, &remain, 10);
1034 content_info = bundle_decode((const bundle_raw *)content, strlen(content));
1036 if (cxt->callback.create)
1037 ret = cxt->callback.create(context, content_info, w, h, cxt->data);
1038 _D("%s is created %d", id);
1041 _W("Create callback returns error(%d)", ret);
1042 ret = __send_update_status(class_id, id,
1043 WIDGET_INSTANCE_EVENT_CREATE_ABORTED, NULL);
1044 __instance_drop(context);
1046 ret = __send_update_status(class_id, id,
1047 WIDGET_INSTANCE_EVENT_CREATE, NULL);
1049 aul_widget_instance_add(class_id, id);
1053 bundle_free(content_info);
1056 static void __stub_terminate(appcore_multiwindow_base_instance_h context, void *data)
1058 struct widget_class_context *class_cxt = data;
1059 struct widget_extra *we;
1061 char *operation = NULL;
1062 bundle *content_info;
1063 widget_app_destroy_type_e reason = WIDGET_APP_DESTROY_TYPE_TEMPORARY;
1064 int event = WIDGET_INSTANCE_EVENT_TERMINATE;
1066 const char *class_id;
1068 id = appcore_multiwindow_base_instance_get_id(context);
1069 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1070 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1074 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
1075 if (operation && strcmp(operation, "destroy") == 0)
1076 reason = WIDGET_APP_DESTROY_TYPE_PERMANENT;
1080 content_info = bundle_decode((const bundle_raw *)we->content, strlen(we->content));
1082 content_info = bundle_create();
1084 if (class_cxt->callback.destroy)
1085 class_cxt->callback.destroy(context, reason, content_info, class_cxt->data);
1086 _D("%s is destroyed %d", id, reason);
1088 if (reason == WIDGET_APP_DESTROY_TYPE_PERMANENT) {
1089 event = WIDGET_INSTANCE_EVENT_DESTROY;
1090 aul_widget_instance_del(class_id, id);
1092 __send_update_status(class_id, id,
1093 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info);
1097 bundle_free(content_info);
1099 __send_update_status(class_id, id, event, NULL);
1100 appcore_multiwindow_base_class_on_terminate(context);
1103 static void __stub_pause(appcore_multiwindow_base_instance_h context, void *data)
1105 struct widget_class_context *class_cxt = data;
1107 const char *class_id;
1109 appcore_multiwindow_base_class_on_pause(context);
1110 id = appcore_multiwindow_base_instance_get_id(context);
1111 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1114 _E("class context is NULL");
1118 if (class_cxt->callback.pause)
1119 class_cxt->callback.pause(context, class_cxt->data);
1120 _D("%s is paused", id);
1121 __send_update_status(class_id, id,
1122 WIDGET_INSTANCE_EVENT_PAUSE, NULL);
1125 static void __stub_resume(appcore_multiwindow_base_instance_h context, void *data)
1127 struct widget_class_context *class_cxt = data;
1129 const char *class_id;
1131 appcore_multiwindow_base_class_on_resume(context);
1132 id = appcore_multiwindow_base_instance_get_id(context);
1133 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1136 _E("class context is NULL");
1140 if (class_cxt->callback.resume)
1141 class_cxt->callback.resume(context, class_cxt->data);
1142 _D("%s is resumed", id);
1143 __send_update_status(class_id, id,
1144 WIDGET_INSTANCE_EVENT_RESUME, NULL);
1147 EXPORT_API widget_class_h widget_app_class_add(widget_class_h widget_class,
1148 const char *class_id,
1149 widget_instance_lifecycle_callback_s callback, void *user_data)
1151 appcore_multiwindow_base_class cls;
1152 struct widget_class_context *cxt;
1154 if (!__is_widget_feature_enabled()) {
1155 _E("not supported");
1156 set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
1161 _E("class is is NULL");
1162 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
1166 cxt = calloc(1, sizeof(struct widget_class_context));
1169 _E("failed to calloc : %s", __FUNCTION__);
1170 set_last_result(WIDGET_ERROR_OUT_OF_MEMORY);
1174 cxt->callback = callback;
1175 cxt->data = user_data;
1177 cls.id = strdup(class_id);
1179 cls.create = __stub_create;
1180 cls.terminate = __stub_terminate;
1181 cls.pause = __stub_pause;
1182 cls.resume = __stub_resume;
1184 appcore_multiwindow_base_class_add(cls);
1185 set_last_result(WIDGET_ERROR_NONE);
1187 return (widget_class_h)cxt;
1190 EXPORT_API widget_class_h widget_app_class_create(
1191 widget_instance_lifecycle_callback_s callback, void *user_data)
1193 return widget_app_class_add(NULL, __appid, callback, user_data);
1196 EXPORT_API int widget_app_context_set_tag(widget_context_h context, void *tag)
1198 struct widget_extra *we;
1200 if (!__is_widget_feature_enabled()) {
1201 _E("not supported"); /* LCOV_EXCL_LINE */
1202 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1206 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1207 __FUNCTION__, NULL);
1209 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1212 return WIDGET_ERROR_NONE;
1215 EXPORT_API int widget_app_context_get_tag(widget_context_h context, void **tag)
1217 struct widget_extra *we;
1219 if (!__is_widget_feature_enabled()) {
1220 _E("not supported"); /* LCOV_EXCL_LINE */
1221 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1224 if (!context || !tag)
1225 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1226 __FUNCTION__, NULL);
1228 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1230 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1231 __FUNCTION__, NULL);
1234 return WIDGET_ERROR_NONE;
1237 EXPORT_API int widget_app_context_set_content_info(widget_context_h context,
1238 bundle *content_info)
1241 bundle_raw *raw = NULL;
1244 const char *class_id;
1245 struct widget_extra *we;
1246 appcore_multiwindow_base_instance_h cxt;
1248 if (!__is_widget_feature_enabled()) {
1249 _E("not supported"); /* LCOV_EXCL_LINE */
1250 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1253 if (!context || !content_info)
1254 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1255 __FUNCTION__, NULL);
1257 cxt = (appcore_multiwindow_base_instance_h)context;
1258 id = appcore_multiwindow_base_instance_get_id(cxt);
1259 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
1260 we = appcore_multiwindow_base_instance_get_extra(cxt);
1262 if (!class_id || !id || !we)
1263 return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL);
1265 ret = __send_update_status(class_id, id,
1266 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info);
1271 bundle_encode(content_info, &raw, &len);
1273 we->content = strdup((const char *)raw);
1279 /* LCOV_EXCL_START */
1280 _E("failed to send content info: %s of %s (%d)", id,
1282 return widget_app_error(WIDGET_ERROR_IO_ERROR, __FUNCTION__,
1284 /* LCOV_EXCL_STOP */
1287 return WIDGET_ERROR_NONE;
1290 EXPORT_API int widget_app_context_set_title(widget_context_h context,
1293 appcore_multiwindow_base_instance_h cxt;
1294 struct widget_extra *we;
1296 if (!__is_widget_feature_enabled()) {
1297 _E("not supported"); /* LCOV_EXCL_LINE */
1298 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1301 if (!context || !title) {
1302 _E("Invalid parameter %p %p", context, title);
1303 return WIDGET_ERROR_INVALID_PARAMETER;
1306 cxt = (appcore_multiwindow_base_instance_h)context;
1307 we = appcore_multiwindow_base_instance_get_extra(cxt);
1310 elm_win_title_set(we->win, title);
1312 return WIDGET_ERROR_NONE;