From f42c993425ba9047016c56762e84ddf1ac28692c Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 20 Jun 2017 14:50:05 +0900 Subject: [PATCH 01/16] Override multiwindow base methods The methods are init(), finish(), run() and exit(). The elementary dependency is removed from multiwindow base. Requires: - https://review.tizen.org/gerrit/#/c/134810/ Change-Id: Icc01285d3ca1313f20e5ad0767da7d78b8b6676e Signed-off-by: Hwankyu Jhun --- src/widget_app.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/widget_app.c b/src/widget_app.c index 3840ac2..4c20c2c 100755 --- a/src/widget_app.c +++ b/src/widget_app.c @@ -614,6 +614,33 @@ static int __widget_app_receive(aul_type type, bundle *b, void *data) return 0; } +static int __widget_app_init(int argc, char **argv, void *data) +{ + elm_init(argc, argv); + return 0; +} + +static void __widget_app_finish(void) +{ + elm_shutdown(); + + /* Check Loader case */ + if (getenv("AUL_LOADER_INIT")) { + unsetenv("AUL_LOADER_INIT"); + elm_shutdown(); + } +} + +static void __widget_app_run(void *data) +{ + elm_run(); +} + +static void __widget_app_exit(void *data) +{ + elm_exit(); +} + EXPORT_API int widget_app_main(int argc, char **argv, widget_app_lifecycle_callback_s *callback, void *user_data) { @@ -647,6 +674,11 @@ EXPORT_API int widget_app_main(int argc, char **argv, ops.base.control = __widget_app_control; ops.base.terminate = __widget_app_terminate; ops.base.receive = __widget_app_receive; + ops.base.init = __widget_app_init; + ops.base.finish = __widget_app_finish; + ops.base.run = __widget_app_run; + ops.base.exit = __widget_app_exit; + __context.callback = *callback; __context.data = user_data; kb = bundle_import_from_argv(argc, argv); @@ -929,7 +961,7 @@ EXPORT_API int widget_app_get_elm_win(widget_context_h context, snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid()); evas_object_data_set(ret_win, "___PLUGID", strdup(buffer)); evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL); - appcore_multiwindow_base_window_bind(cxt, ret_win); + appcore_multiwindow_base_window_bind(cxt, wl_win); _D("window created: %d", win_id); -- 2.7.4 From e655f9a68af50188238c647bacaa61476818075c Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 21 Jun 2017 09:24:00 +0900 Subject: [PATCH 02/16] Fix invalid log format Change-Id: I2c0d30f1a90754ff1744d2ec9a1e31d6a88902b1 Signed-off-by: Hwankyu Jhun --- src/widget_app.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget_app.c b/src/widget_app.c index 4c20c2c..63ef11b 100755 --- a/src/widget_app.c +++ b/src/widget_app.c @@ -1035,7 +1035,7 @@ static void __stub_create(appcore_multiwindow_base_instance_h context, void *dat if (cxt->callback.create) ret = cxt->callback.create(context, content_info, w, h, cxt->data); - _D("%s is created %d", id); + _D("%s is created", id); if (ret < 0) { _W("Create callback returns error(%d)", ret); -- 2.7.4 From 9925d8896be783d8e6fe9c99ab5813732698ac49 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 29 Jun 2017 14:02:02 +0900 Subject: [PATCH 03/16] Release version 1.1.3 Changes: - Fix invalid log format - Override multiwindow base methods Change-Id: I61b54252730f6f6be653a4e0afa1994aac4ed7e6 Signed-off-by: Hwankyu Jhun --- packaging/appcore-widget.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/appcore-widget.spec b/packaging/appcore-widget.spec index 42899da..40d32e4 100644 --- a/packaging/appcore-widget.spec +++ b/packaging/appcore-widget.spec @@ -1,6 +1,6 @@ Name: appcore-widget Summary: Widget Application -Version: 1.1.2 +Version: 1.1.3 Release: 1 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From f14751ab0da7cd0e15c73faaa1e5a40e40936cf4 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 6 Jul 2017 15:58:52 +0900 Subject: [PATCH 04/16] Fix typo The LOG_TAG should be "CAPI_WIDGET_APPLICATION". Change-Id: Ib8bb756b23156462ca0bba966d56c21a1fda7f24 Signed-off-by: Hwankyu Jhun --- src/widget_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget_error.c b/src/widget_error.c index 8f90de4..cd79e5f 100755 --- a/src/widget_error.c +++ b/src/widget_error.c @@ -27,7 +27,7 @@ #undef LOG_TAG #endif -#define LOG_TAG "CAPI_WIDGET_APPLICATIO" +#define LOG_TAG "CAPI_WIDGET_APPLICATION" static const char *widget_app_error_to_string(widget_error_e error) { -- 2.7.4 From c93e468993a30c8c4cfbad075aae7136cff854b9 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 7 Jul 2017 13:01:24 +0900 Subject: [PATCH 05/16] Release version 1.1.4 Changes: - Fix typo Change-Id: I54dde607de7b9d9c853a9ba48fff0214edeeeefe Signed-off-by: Hwankyu Jhun --- packaging/appcore-widget.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/appcore-widget.spec b/packaging/appcore-widget.spec index 40d32e4..b36d898 100644 --- a/packaging/appcore-widget.spec +++ b/packaging/appcore-widget.spec @@ -1,6 +1,6 @@ Name: appcore-widget Summary: Widget Application -Version: 1.1.3 +Version: 1.1.4 Release: 1 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 67d554c153366b6482e3e16222bbc2706c599abb Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Wed, 30 Aug 2017 13:53:59 +0900 Subject: [PATCH 06/16] Fix wrong description Change-Id: Ic1a7a27fb1442e32d0ffbee03c23d014d842e957 Signed-off-by: Daehyeon Jung --- include/widget_app.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/widget_app.h b/include/widget_app.h index cf1b275..1bae4a5 100755 --- a/include/widget_app.h +++ b/include/widget_app.h @@ -432,7 +432,7 @@ int widget_app_context_set_title(widget_context_h context, const char *title); * @return The new widget class object, * NULL on error * @exception #WIDGET_ERROR_NONE Successfully added - * @exception #WIDGET_ERROR_INVALID_PARAMETER Not supported + * @exception #WIDGET_ERROR_INVALID_PARAMETER Invalid parameter * @exception #WIDGET_ERROR_NOT_SUPPORTED Not supported * @exception #WIDGET_ERROR_OUT_OF_MEMORY Out of memory * @see get_last_result() -- 2.7.4 From 3151b95ac4ca7e44e3796686d5bc7384d8abe387 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Wed, 6 Sep 2017 13:47:01 +0900 Subject: [PATCH 07/16] Fix build error - Require: https://review.tizen.org/gerrit/#/c/147906/ Change-Id: I5fbe33b00d4acc6e5ba43a0a94452b3906eb4a09 Signed-off-by: Junghoon Park --- src/widget_app.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widget_app.c b/src/widget_app.c index 63ef11b..5479b95 100755 --- a/src/widget_app.c +++ b/src/widget_app.c @@ -614,10 +614,9 @@ static int __widget_app_receive(aul_type type, bundle *b, void *data) return 0; } -static int __widget_app_init(int argc, char **argv, void *data) +static void __widget_app_init(int argc, char **argv, void *data) { elm_init(argc, argv); - return 0; } static void __widget_app_finish(void) -- 2.7.4 From bc80aba1fa289601d45a4bae9690dd7bf0a67442 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 8 Sep 2017 12:13:16 +0900 Subject: [PATCH 08/16] Release version 1.1.5 Changes: - Fix build error - Fix wrong description Change-Id: I31c661f2b98a08e0ebfd8e07231c65e3ec8144f0 Signed-off-by: Hwankyu Jhun --- packaging/appcore-widget.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/appcore-widget.spec b/packaging/appcore-widget.spec index b36d898..ee9de3d 100644 --- a/packaging/appcore-widget.spec +++ b/packaging/appcore-widget.spec @@ -1,6 +1,6 @@ Name: appcore-widget Summary: Widget Application -Version: 1.1.4 +Version: 1.1.5 Release: 1 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 409d1e95a1f99acb699ee4d38ffc3be10256e5f7 Mon Sep 17 00:00:00 2001 From: Hyunho Kang Date: Fri, 8 Sep 2017 14:10:36 +0900 Subject: [PATCH 09/16] Create widget base API set Change-Id: I65e7c0405b4839b23aeefc666075b7270dddd5bd Signed-off-by: Hyunho Kang Signed-off-by: Junghoon Park --- CMakeLists.txt | 50 +- appcore-widget-base.pc.in | 13 + capi-appfw-widget-application.pc.in | 3 +- include/widget_app.h | 2 +- include/widget_base.h | 133 +++ packaging/appcore-widget.spec | 36 +- src/base/widget_base.c | 1450 ++++++++++++++++++++++++++++++ src/{ => efl_base}/widget-log.h | 0 src/{ => efl_base}/widget-private.h | 2 - src/efl_base/widget_app.c | 518 +++++++++++ src/{ => efl_base}/widget_app_internal.c | 4 +- src/{ => efl_base}/widget_error.c | 0 src/widget_app.c | 1312 --------------------------- 13 files changed, 2192 insertions(+), 1331 deletions(-) create mode 100644 appcore-widget-base.pc.in create mode 100644 include/widget_base.h create mode 100644 src/base/widget_base.c rename src/{ => efl_base}/widget-log.h (100%) mode change 100755 => 100644 rename src/{ => efl_base}/widget-private.h (92%) create mode 100644 src/efl_base/widget_app.c rename src/{ => efl_base}/widget_app_internal.c (95%) rename src/{ => efl_base}/widget_error.c (100%) mode change 100755 => 100644 delete mode 100755 src/widget_app.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 6dc73c9..a665178 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,9 +18,46 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_SKIP_BUILD_RPATH TRUE) ################################################################# +# Build appcore-widget base Library +# ------------------------------ +SET(APPCORE_WIDGET_BASE "appcore-widget-base") +SET(SOURCES_base src/base/widget_base.c) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkg_widget_base REQUIRED + dlog + appcore-common + capi-appfw-app-common + vconf + vconf-internal-keys + widget_service + capi-system-info + ecore-wayland + capi-system-info + screen_connector_provider + appcore-multiwindow + ) + +FOREACH(flag ${pkg_widget_base_CFLAGS}) + SET(EXTRA_CFLAGS_widget "${EXTRA_CFLAGS_widget} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${APPCORE_WIDGET_BASE} SHARED ${SOURCES_base}) +SET_TARGET_PROPERTIES(${APPCORE_WIDGET_BASE} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${APPCORE_WIDGET_BASE} PROPERTIES VERSION ${FULLVER}) +SET_TARGET_PROPERTIES(${APPCORE_WIDGET_BASE} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_widget}) +TARGET_LINK_LIBRARIES(${APPCORE_WIDGET_BASE} ${pkg_widget_base_LDFLAGS} "-ldl -Wl,--no-undefined") + +CONFIGURE_FILE(${APPCORE_WIDGET_BASE}.pc.in ${APPCORE_WIDGET_BASE}.pc @ONLY) +INSTALL(TARGETS ${APPCORE_WIDGET_BASE} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_WIDGET_BASE}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + + +################################################################# # Build appcore-widget Library # ------------------------------ SET(APPCORE_WIDGET "capi-appfw-widget-application") +SET(SOURCES_efl src/efl_base/widget_app.c src/efl_base/widget_app_internal.c src/efl_base/widget_error.c) INCLUDE(FindPkgConfig) pkg_check_modules(pkg_widget REQUIRED @@ -28,25 +65,17 @@ pkg_check_modules(pkg_widget REQUIRED dlog appcore-common capi-appfw-app-common - vconf elementary - vconf-internal-keys - widget_service - capi-system-info - ecore-wayland - screen_connector_provider - appcore-multiwindow ) FOREACH(flag ${pkg_widget_CFLAGS}) SET(EXTRA_CFLAGS_widget "${EXTRA_CFLAGS_widget} ${flag}") ENDFOREACH(flag) -AUX_SOURCE_DIRECTORY(src SOURCES) -ADD_LIBRARY(${APPCORE_WIDGET} SHARED ${SOURCES}) +ADD_LIBRARY(${APPCORE_WIDGET} SHARED ${SOURCES_efl}) SET_TARGET_PROPERTIES(${APPCORE_WIDGET} PROPERTIES SOVERSION ${MAJORVER}) SET_TARGET_PROPERTIES(${APPCORE_WIDGET} PROPERTIES VERSION ${FULLVER}) SET_TARGET_PROPERTIES(${APPCORE_WIDGET} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_widget}) -TARGET_LINK_LIBRARIES(${APPCORE_WIDGET} ${pkg_widget_LDFLAGS} "-ldl -Wl,--no-undefined") +TARGET_LINK_LIBRARIES(${APPCORE_WIDGET} ${pkg_widget_LDFLAGS} ${APPCORE_WIDGET_BASE} "-ldl -Wl,--no-undefined") CONFIGURE_FILE(${APPCORE_WIDGET}.pc.in ${APPCORE_WIDGET}.pc @ONLY) INSTALL(TARGETS ${APPCORE_WIDGET} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) @@ -56,3 +85,4 @@ INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/appfw/ FILES_MATCHING PATTERN "*.h" ) + diff --git a/appcore-widget-base.pc.in b/appcore-widget-base.pc.in new file mode 100644 index 0000000..78de159 --- /dev/null +++ b/appcore-widget-base.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDEDIR@ + +Name: appcore-widget-base +Description: widget base library +Version: @VERSION@ +Requires: aul dlog capi-appfw-app-common widget_service +Libs: -L${libdir} -lappcore-widget-base +Cflags: -I${includedir} -I${includedir}/appfw diff --git a/capi-appfw-widget-application.pc.in b/capi-appfw-widget-application.pc.in index 8512e85..6f7ec01 100644 --- a/capi-appfw-widget-application.pc.in +++ b/capi-appfw-widget-application.pc.in @@ -8,6 +8,7 @@ includedir=@INCLUDEDIR@ Name: capi-appfw-widget-application Description: widget application library Version: @VERSION@ -Requires: aul dlog elementary capi-appfw-app-common widget_service +Requires.private: aul dlog elementary capi-appfw-app-common widget_service +Requires: appcore-widget-base Libs: -L${libdir} -lcapi-appfw-widget-application Cflags: -I${includedir} -I${includedir}/appfw diff --git a/include/widget_app.h b/include/widget_app.h index 1bae4a5..cf1b275 100755 --- a/include/widget_app.h +++ b/include/widget_app.h @@ -432,7 +432,7 @@ int widget_app_context_set_title(widget_context_h context, const char *title); * @return The new widget class object, * NULL on error * @exception #WIDGET_ERROR_NONE Successfully added - * @exception #WIDGET_ERROR_INVALID_PARAMETER Invalid parameter + * @exception #WIDGET_ERROR_INVALID_PARAMETER Not supported * @exception #WIDGET_ERROR_NOT_SUPPORTED Not supported * @exception #WIDGET_ERROR_OUT_OF_MEMORY Out of memory * @see get_last_result() diff --git a/include/widget_base.h b/include/widget_base.h new file mode 100644 index 0000000..0358000 --- /dev/null +++ b/include/widget_base.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#define FEATURE_SHELL_APPWIDGET "http://tizen.org/feature/shell.appwidget" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum widget_base_destroy_type { + WIDGET_BASE_DESTROY_TYPE_PERMANENT = 0x00, + WIDGET_BASE_DESTROY_TYPE_TEMPORARY = 0x01, +} widget_base_destroy_type_e; + +typedef enum widget_base_error { + WIDGET_BASE_ERROR_NONE = TIZEN_ERROR_NONE, /**< Operation is successfully completed */ + WIDGET_BASE_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid function parameter */ + WIDGET_BASE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + WIDGET_BASE_ERROR_RESOURCE_BUSY = TIZEN_ERROR_RESOURCE_BUSY, /**< Device or resource busy */ + WIDGET_BASE_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */ + WIDGET_BASE_ERROR_CANCELED = TIZEN_ERROR_CANCELED, /**< Operation Canceled */ + WIDGET_BASE_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */ + WIDGET_BASE_ERROR_TIMED_OUT = TIZEN_ERROR_TIMED_OUT, /**< Time out */ + WIDGET_BASE_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + WIDGET_BASE_ERROR_FILE_NO_SPACE_ON_DEVICE = TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE, /**< No space left on device */ + WIDGET_BASE_ERROR_FAULT = TIZEN_ERROR_WIDGET | 0x0001, /**< Fault - Unable to recover from the error */ + WIDGET_BASE_ERROR_ALREADY_EXIST = TIZEN_ERROR_WIDGET | 0x0002, /**< Already exists */ + WIDGET_BASE_ERROR_ALREADY_STARTED = TIZEN_ERROR_WIDGET | 0x0004, /**< Operation is already started */ + WIDGET_BASE_ERROR_NOT_EXIST = TIZEN_ERROR_WIDGET | 0x0008, /**< Not exists */ + WIDGET_BASE_ERROR_DISABLED = TIZEN_ERROR_WIDGET | 0x0010, /**< Disabled */ + WIDGET_BASE_ERROR_MAX_EXCEEDED = TIZEN_ERROR_WIDGET | 0x0011, /**< Maximum number of instances exceeded (Since 3.0) */ +} widget_base_error_e; + +typedef appcore_multiwindow_base_instance_h widget_base_instance_h; + +typedef struct _widget_base_class_ops { + int (*create)(widget_base_instance_h instance_h, bundle *content, + int w, int h, void *class_data); + int (*destroy)(widget_base_instance_h instance_h, + widget_base_destroy_type_e reason, bundle *content, + void *class_data); + int (*pause)(widget_base_instance_h instance_h, void *class_data); + int (*resume)(widget_base_instance_h instance_h, void *class_data); + int (*resize)(widget_base_instance_h instance_h, int w, int h, void *class_data); + int (*update)(widget_base_instance_h instance_h, bundle *content, int force, + void *class_data); +} widget_base_class_ops; + +typedef struct _widget_base_ops { + int (*create)(void *data); + int (*terminate)(void *data); + void (*init)(int argc, char **argv, void *data); + void (*finish)(void); + void (*run)(void *data); + void (*exit)(void *data); +} widget_base_ops; + +typedef struct _widget_base_class { + char *id; + widget_base_class_ops ops; +} widget_base_class; + +typedef bool (*widget_base_instance_cb)(widget_base_instance_h instance, void *data); + +int widget_base_foreach_context(widget_base_instance_cb cb, void *data); +int widget_base_terminate_context(widget_base_instance_h instance_h); +int widget_base_add_event_handler(app_event_handler_h *event_handler, + app_event_type_e event_type, + app_event_cb callback, + void *user_data); +int widget_base_remove_event_handler(app_event_handler_h + event_handler); +int widget_base_context_set_content_info(widget_base_instance_h instance_h, + bundle *content_info); +int widget_base_context_get_tag(widget_base_instance_h instance_h, void **tag); +int widget_base_context_set_tag(widget_base_instance_h instance_h, void *tag); +void *widget_base_context_get_user_data(widget_base_instance_h instance_h); +int widget_base_context_set_user_data(widget_base_instance_h instance_h, + void *user_data); +int widget_base_context_get_id(widget_base_instance_h instance_h, char **id); +const char *widget_base_get_viewer_endpoint(void); +int widget_base_init(widget_base_ops ops, int argc, char **argv, void *data); +int widget_base_on_create(void); +int widget_base_on_terminate(void); +int widget_base_on_init(int argc, char **argv); +void widget_base_on_finish(void); +void widget_base_on_run(void); +void widget_base_on_exit(void); +widget_base_ops widget_base_get_default_ops(void); +void widget_base_fini(void); +int widget_base_exit(void); +int widget_base_context_window_bind( + widget_base_instance_h instance_h, const char *id, + Ecore_Wl_Window *wl_win); +int widget_base_class_on_create(widget_base_instance_h instance_h, + bundle *content, int w, int h); +int widget_base_class_on_pause(widget_base_instance_h instance_h); +int widget_base_class_on_resume(widget_base_instance_h instance_h); +int widget_base_class_on_resize(widget_base_instance_h instance_h, + int w, int h); +int widget_base_class_on_update(widget_base_instance_h instance_h, + bundle *content, int force); +int widget_base_class_on_destroy(widget_base_instance_h instance_h, + widget_base_destroy_type_e reason, bundle *content); +widget_base_class widget_base_class_get_default(void); +widget_base_class *widget_base_class_add(widget_base_class cls, + const char *class_id, void *class_data); + +#ifdef __cplusplus +} +#endif diff --git a/packaging/appcore-widget.spec b/packaging/appcore-widget.spec index ee9de3d..9cc0e6f 100644 --- a/packaging/appcore-widget.spec +++ b/packaging/appcore-widget.spec @@ -20,9 +20,28 @@ BuildRequires: pkgconfig(appcore-multiwindow) BuildRequires: pkgconfig(screen_connector_provider) BuildRequires: cmake +%description +Widget base + +%package -n appcore-widget-base +Summary: Widget base +Group: Development/Libraries +Requires(post): /sbin/ldconfig +%description -n appcore-widget-base +Requires(postun): /sbin/ldconfig %description -Widget application +Widget base devel + +%package -n appcore-widget-base-devel +Summary: Widget base +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +%description -n appcore-widget-base-devel +widget application (development files) + +%description +Widget application devel %package -n capi-appfw-widget-application-devel Summary: Widget application @@ -50,9 +69,20 @@ cp capi-appfw-widget-application.pc %{buildroot}%{_libdir}/pkgconfig %postun -p /sbin/ldconfig +%files -n appcore-widget-base +%manifest %{name}.manifest +%defattr(-,root,root,-) +%{_libdir}/libappcore-widget-base.so.* +%license LICENSE + +%files -n appcore-widget-base-devel +/usr/include/appfw/widget_base.h +%{_libdir}/pkgconfig/appcore-widget-base.pc +%{_libdir}/libappcore-widget-base.so + -%files -%manifest appcore-widget.manifest +%files -n appcore-widget +%manifest %{name}.manifest %defattr(-,root,root,-) %{_libdir}/libcapi-appfw-widget-application.so.* %license LICENSE diff --git a/src/base/widget_base.c b/src/base/widget_base.c new file mode 100644 index 0000000..7cbba6c --- /dev/null +++ b/src/base/widget_base.c @@ -0,0 +1,1450 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "widget_base.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_WIDGET_APPLICATION" +#define APP_TYPE_WIDGET "widgetapp" +#define STATUS_FOREGROUND "fg" +#define STATUS_BACKGROUND "bg" + +static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = { + [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY, + [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY, + [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE, + [APP_EVENT_DEVICE_ORIENTATION_CHANGED] + = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED, + [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE, + [APP_EVENT_SUSPENDED_STATE_CHANGED] + = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE, +}; + +struct app_event_info { + app_event_type_e type; + void *value; +}; + +struct app_event_handler { + app_event_type_e type; + app_event_cb cb; + void *data; + void *raw; +}; + +struct widget_foreach_context { + widget_base_instance_cb callback; + void *data; +}; + +typedef struct _widget_base_context { + widget_base_ops ops; + void *data; + int argc; + char **argv; + GList *classes; +} widget_base_context; + +typedef struct _widget_base_instance_data { + bundle *args; + char *content; + void *tag; + void *user_data; +} widget_base_instance_data; + +static widget_base_context __context; +static char *__appid; +static char *__package_id; +static bool __fg_signal; +static char *__viewer_endpoint; + +static bool __is_widget_feature_enabled(void) +{ + static bool feature = false; + static bool retrieved = false; + int ret; + + if (retrieved == true) + return feature; + + ret = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature); + if (ret != SYSTEM_INFO_ERROR_NONE) { + LOGE("failed to get system info"); /* LCOV_EXCL_LINE */ + return false; /* LCOV_EXCL_LINE */ + } + + retrieved = true; + + return feature; +} + +/* LCOV_EXCL_START */ +static void __on_poweroff(keynode_t *key, void *data) +{ + int val; + + val = vconf_keynode_get_int(key); + switch (val) { + case VCONFKEY_SYSMAN_POWER_OFF_DIRECT: + case VCONFKEY_SYSMAN_POWER_OFF_RESTART: + LOGI("power off changed: %d", val); + widget_base_exit(); + break; + case VCONFKEY_SYSMAN_POWER_OFF_NONE: + case VCONFKEY_SYSMAN_POWER_OFF_POPUP: + default: + /* DO NOTHING */ + break; + } +} +/* LCOV_EXCL_STOP */ + +static void __check_empty_instance(void) +{ + int cnt = appcore_multiwindow_base_instance_get_cnt(); + + if (cnt == 0) + widget_base_exit(); +} + +static void __instance_drop(appcore_multiwindow_base_instance_h instance_h) +{ + widget_base_instance_data *data; + + data = appcore_multiwindow_base_instance_get_extra(instance_h); + appcore_multiwindow_base_instance_drop(instance_h); + free(data->content); + free(data); + __check_empty_instance(); +} + +static gint __comp_class(gconstpointer a, gconstpointer b) +{ + const widget_base_class *cls = a; + + return strcmp(cls->id, b); +} + +static widget_base_class __get_class(const char *class_id) +{ + widget_base_class *cls; + GList *class_node; + + class_node = g_list_find_custom(__context.classes, class_id, + __comp_class); + cls = (widget_base_class *)class_node->data; + + return *cls; +} + +static int __send_lifecycle_event(const char *class_id, const char *instance_id, + int status) +{ + bundle *b = bundle_create(); + int ret; + + if (b == NULL) { + LOGE("out of memory"); /* LCOV_EXCL_LINE */ + return -1; /* LCOV_EXCL_LINE */ + } + + bundle_add_str(b, AUL_K_WIDGET_ID, class_id); + bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id); + bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int)); + bundle_add_str(b, AUL_K_PKGID, __package_id); + + LOGD("send lifecycle %s(%d)", instance_id, status); + ret = aul_app_com_send("widget.status", b); + if (ret < 0) + LOGE("send lifecycle error:%d", ret); /* LCOV_EXCL_LINE */ + + bundle_free(b); + + return ret; +} + +static int __send_update_status(const char *class_id, const char *instance_id, + int status, bundle *extra) +{ + bundle *b; + int lifecycle = -1; + bundle_raw *raw = NULL; + int len; + + b = bundle_create(); + if (!b) { + LOGE("out of memory"); /* LCOV_EXCL_LINE */ + return -1; /* LCOV_EXCL_LINE */ + } + + bundle_add_str(b, AUL_K_WIDGET_ID, class_id); + bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id); + bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int)); + + if (extra) { + bundle_encode(extra, &raw, &len); + bundle_add_str(b, WIDGET_K_CONTENT_INFO, (const char *)raw); + aul_widget_instance_add(class_id, instance_id); + } + + LOGD("send update %s(%d) to %s", instance_id, status, __viewer_endpoint); + aul_app_com_send(__viewer_endpoint, b); + + switch (status) { + case WIDGET_INSTANCE_EVENT_CREATE: + lifecycle = WIDGET_LIFE_CYCLE_EVENT_CREATE; + break; + case WIDGET_INSTANCE_EVENT_DESTROY: + lifecycle = WIDGET_LIFE_CYCLE_EVENT_DESTROY; + break; + case WIDGET_INSTANCE_EVENT_PAUSE: + lifecycle = WIDGET_LIFE_CYCLE_EVENT_PAUSE; + break; + case WIDGET_INSTANCE_EVENT_RESUME: + lifecycle = WIDGET_LIFE_CYCLE_EVENT_RESUME; + break; + } + + if (lifecycle > -1) + __send_lifecycle_event(class_id, instance_id, lifecycle); + + bundle_free(b); + if (raw) + free(raw); + + return 0; +} + +static void __control_create(const char *class_id, const char *id, bundle *b) +{ + widget_base_instance_data *data; + char *content = NULL; + + data = (widget_base_instance_data *) + calloc(1, sizeof(widget_base_instance_data)); + if (!data) { + LOGE("Out of memory"); + return; + } + + data->args = b; + + /* call stub create */ + appcore_multiwindow_base_instance_run(class_id, id, data); + data->args = NULL; + bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content); + if (content) + data->content = strdup(content); + +} + +static void __control_resume(const char *class_id, const char *id, bundle *b) +{ + appcore_multiwindow_base_instance_h cxt; + + cxt = appcore_multiwindow_base_instance_find(id); + if (!cxt) { + LOGE("context not found: %s", id); + return; + } + + /* call stub resume */ + appcore_multiwindow_base_instance_resume(cxt); +} + +static void __control_pause(const char *class_id, const char *id, bundle *b) +{ + appcore_multiwindow_base_instance_h instance_h; + + instance_h = appcore_multiwindow_base_instance_find(id); + + if (!instance_h) { + LOGE("instance not found: %s", id); + return; + } + + /* call stub pause */ + appcore_multiwindow_base_instance_pause(instance_h); +} + +static void __control_resize(const char *class_id, const char *id, bundle *b) +{ + appcore_multiwindow_base_instance_h instance_h; + char *remain = NULL; + char *w_str = NULL; + char *h_str = NULL; + int w = 0; + int h = 0; + void *class_data; + widget_base_class cls; + const appcore_multiwindow_base_class *raw_cls; + + instance_h = appcore_multiwindow_base_instance_find(id); + if (!instance_h) { + LOGE("context not found: %s", id); + return; + } + + raw_cls = appcore_multiwindow_base_instance_get_class(instance_h); + if (!raw_cls) + return; + + cls = __get_class(class_id); + class_data = raw_cls->data; + bundle_get_str(b, WIDGET_K_WIDTH, &w_str); + bundle_get_str(b, WIDGET_K_HEIGHT, &h_str); + + if (w_str) + w = (int)g_ascii_strtoll(w_str, &remain, 10); + + if (h_str) + h = (int)g_ascii_strtoll(h_str, &remain, 10); + + if (cls.ops.resize) + cls.ops.resize(instance_h, w, h, class_data); + + LOGD("%s is resized to %dx%d", id, w, h); + __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_SIZE_CHANGED, NULL); +} + +static void __update_cb(const char *class_id, const char *id, + appcore_multiwindow_base_instance_h instance_h, void *data) +{ + void *class_data; + const appcore_multiwindow_base_class *raw_cls; + bundle *content = NULL; + char *content_raw = NULL; + char *force_str = NULL; + int force; + bundle *b = data; + widget_base_class cls; + + if (!b) { + LOGE("bundle is NULL"); + return; + } + + raw_cls = appcore_multiwindow_base_instance_get_class(instance_h); + if (!raw_cls) { + LOGE("class is NULL"); + return; + } + + class_data = raw_cls->data; + cls = __get_class(class_id); + + if (!cls.ops.update) { + LOGE("update callback is NULL"); + return; + } + + bundle_get_str(b, WIDGET_K_FORCE, &force_str); + + if (force_str && strcmp(force_str, "true") == 0) + force = 1; + else + force = 0; + + bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw); + + if (content_raw) { + content = bundle_decode((const bundle_raw *)content_raw, + strlen(content_raw)); + } + + if (cls.ops.update) + cls.ops.update(instance_h, content, force, class_data); + + __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_UPDATE, NULL); + LOGD("updated:%s", id); + + if (content) + bundle_free(content); +} + +static void __control_update(const char *class_id, const char *id, bundle *b) +{ + appcore_multiwindow_base_instance_h instance_h; + + if (!id) { + appcore_multiwindow_base_instance_foreach(class_id, + __update_cb, b); + return; + } + + instance_h = appcore_multiwindow_base_instance_find(id); + if (!instance_h) { + LOGE("context not found: %s", id); + return; + } + + __update_cb(class_id, id, instance_h, b); +} + +static void __control_destroy(const char *class_id, const char *id, bundle *b) +{ + appcore_multiwindow_base_instance_h instance_h; + widget_base_instance_data *data; + + instance_h = appcore_multiwindow_base_instance_find(id); + if (!instance_h) { + LOGE("could not find widget obj: %s, clear amd info", id); + aul_widget_instance_del(class_id, id); + return; + } + + data = (widget_base_instance_data *) + appcore_multiwindow_base_instance_get_extra(instance_h); + data->args = b; + + /* call stub terminate */ + appcore_multiwindow_base_instance_exit(instance_h); + free(data->content); + free(data); + __check_empty_instance(); +} + +static int __multiwindow_create(void *data) +{ + char pkgid[256] = {0, }; + int ret = 0; + + appcore_multiwindow_base_on_create(); + app_get_id(&__appid); + if (aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0) + __package_id = strdup(pkgid); + + if (!__package_id || !__appid) { + LOGE("__package_id is NULL"); + return -1; + } + + screen_connector_provider_init(); + vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, + __on_poweroff, NULL); + + + if (__context.ops.create) + ret = __context.ops.create(data); + + LOGD("widget base is created"); + return ret; +} + +static int __multiwindow_terminate(void *data) +{ + if (__context.ops.terminate) + __context.ops.terminate(data); + + vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, + __on_poweroff); + screen_connector_provider_fini(); + + if (__viewer_endpoint) { + free(__viewer_endpoint); + __viewer_endpoint = NULL; + } + + if (__package_id) { + free(__package_id); + __package_id = NULL; + } + + if (__appid) { + free(__appid); + __appid = NULL; + } + + appcore_multiwindow_base_on_terminate(); + + LOGD("widget base is terminated"); + return 0; +} + +static int __multiwindow_control(bundle *b, void *data) +{ + char *class_id = NULL; + char *id = NULL; + char *operation = NULL; + + appcore_multiwindow_base_on_control(b); + bundle_get_str(b, WIDGET_K_CLASS, &class_id); + /* for previous version compatibility, use appid for default class id */ + if (class_id == NULL) + class_id = __appid; + + bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id); + bundle_get_str(b, WIDGET_K_OPERATION, &operation); + + if (!operation) { + LOGE("operation is NULL"); + return 0; + } + + if (strcmp(operation, "create") == 0) + __control_create(class_id, id, b); + else if (strcmp(operation, "resize") == 0) + __control_resize(class_id, id, b); + else if (strcmp(operation, "update") == 0) + __control_update(class_id, id, b); + else if (strcmp(operation, "destroy") == 0) + __control_destroy(class_id, id, b); + else if (strcmp(operation, "resume") == 0) + __control_resume(class_id, id, b); + else if (strcmp(operation, "pause") == 0) + __control_pause(class_id, id, b); + else if (strcmp(operation, "terminate") == 0) + __control_destroy(class_id, id, b); + + return 0; +} + +static void __inst_resume_cb(const char *class_id, const char *id, + appcore_multiwindow_base_instance_h cxt, void *data) +{ + __control_resume(class_id, id, data); +} + +static void __get_content(bundle *b) +{ + char *instance_id = NULL; + appcore_multiwindow_base_instance_h cxt; + widget_base_instance_data * we; + + bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &instance_id); + if (!instance_id) { + LOGE("instance id is NULL"); + return; + } + + cxt = appcore_multiwindow_base_instance_find(instance_id); + if (!cxt) { + LOGE("could not find widget obj: %s", instance_id); + return; + } + + we = appcore_multiwindow_base_instance_get_extra(cxt); + if (!we) { + LOGE("widget extra is NULL"); + return; + } + + if (we->content) { + bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, we->content); + LOGD("content info of %s found", instance_id); + } else { + bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, ""); + LOGD("empty content info added"); + } +} + +static int __multiwindow_receive(aul_type type, bundle *b, void *data) +{ + appcore_multiwindow_base_on_receive(type, b); + + switch (type) { + case AUL_RESUME: + appcore_multiwindow_base_instance_foreach_full( + __inst_resume_cb, b); + break; + case AUL_TERMINATE: + widget_base_exit(); + break; + case AUL_WIDGET_CONTENT: + __get_content(b); + break; + default: + break; + } + + return 0; +} + +static void __multiwindow_init(int argc, char **argv, void *data) +{ + if (__context.ops.init) + __context.ops.init(argc, argv, data); +} + +static void __multiwindow_finish(void) +{ + if (__context.ops.finish) { + __context.ops.finish(); + /* Check Loader case */ + if (getenv("AUL_LOADER_INIT")) { + unsetenv("AUL_LOADER_INIT"); + __context.ops.finish(); + } + } +} + +static void __multiwindow_run(void *data) +{ + if (__context.ops.run) + __context.ops.run(data); +} + +static void __multiwindow_exit(void *data) +{ + if (__context.ops.exit) + __context.ops.exit(data); +} + +EXPORT_API int widget_base_exit(void) +{ + appcore_multiwindow_base_exit(); + aul_widget_notify_exit(); + + return 0; +} + +static gboolean __finish_event_cb(gpointer user_data) +{ + appcore_multiwindow_base_instance_h cxt = user_data; + bundle *b; + const char *id; + const char *class_id; + + if (!cxt) { + LOGE("user_data is NULL"); + return FALSE; + } + + id = appcore_multiwindow_base_instance_get_id(cxt); + class_id = appcore_multiwindow_base_instance_get_class_id(cxt); + b = bundle_create(); + + if (!b) { + LOGE("Out-of-memory"); + return FALSE; + } + + bundle_add_str(b, WIDGET_K_OPERATION, "terminate"); + __control_destroy(class_id, id, b); + bundle_free(b); + + return FALSE; +} + +EXPORT_API int widget_base_terminate_context(widget_base_instance_h context) +{ + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + if (!context) { + LOGE("context is null"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + g_idle_add(__finish_event_cb, context); + + return WIDGET_ERROR_NONE; +} + +static void __inst_full_cb(const char *class_id, const char *id, + appcore_multiwindow_base_instance_h cxt, void *data) +{ + struct widget_foreach_context *foreach_context = data; + + if (!data) + return; + + if (foreach_context->callback) + foreach_context->callback(cxt, foreach_context->data); +} + +EXPORT_API int widget_base_foreach_context(widget_base_instance_cb cb, void *data) +{ + struct widget_foreach_context foreach_context; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + if (!cb) { + LOGE("callback is NULL"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + foreach_context.callback = cb; + foreach_context.data = data; + appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context); + + return WIDGET_ERROR_NONE; +} + +static int __event_cb(void *event, void *data) +{ + app_event_handler_h handler = data; + + struct app_event_info app_event; + + app_event.type = handler->type; + app_event.value = event; + + if (handler->cb) + handler->cb(&app_event, handler->data); + + return 0; +} + +EXPORT_API int widget_base_add_event_handler(app_event_handler_h *event_handler, + app_event_type_e event_type, + app_event_cb callback, + void *user_data) +{ + int r; + bool feature; + app_event_handler_h handler; + + r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature); + if (r < 0) + return WIDGET_BASE_ERROR_FAULT; + + if (!feature) + return WIDGET_BASE_ERROR_NOT_SUPPORTED; + + if (event_handler == NULL || callback == NULL) + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + + if (event_type < APP_EVENT_LOW_MEMORY + || event_type > APP_EVENT_REGION_FORMAT_CHANGED) + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + + if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED) + return WIDGET_BASE_ERROR_NOT_SUPPORTED; + + + handler = calloc(1, sizeof(struct app_event_handler)); + if (!handler) + return WIDGET_BASE_ERROR_OUT_OF_MEMORY; + + handler->type = event_type; + handler->cb = callback; + handler->data = user_data; + handler->raw = appcore_base_add_event( + __app_event_converter[event_type], __event_cb, handler); + *event_handler = handler; + + return WIDGET_BASE_ERROR_NONE; +} + +EXPORT_API int widget_base_remove_event_handler(app_event_handler_h + event_handler) +{ + int r; + bool feature; + app_event_type_e type; + + r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature); + if (r < 0) + return WIDGET_BASE_ERROR_FAULT; + + if (!feature) + return WIDGET_BASE_ERROR_NOT_SUPPORTED; + + if (event_handler == NULL) + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + + type = event_handler->type; + if (type < APP_EVENT_LOW_MEMORY || + type > APP_EVENT_REGION_FORMAT_CHANGED) + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + + r = appcore_base_remove_event(event_handler->raw); + if (r < 0) + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + + free(event_handler); + + return WIDGET_BASE_ERROR_NONE; +} + +EXPORT_API int widget_base_context_set_content_info( + widget_base_instance_h context, + bundle *content_info) +{ + int ret = 0; + bundle_raw *raw = NULL; + int len; + const char *id; + const char *class_id; + widget_base_instance_data *data; + appcore_multiwindow_base_instance_h instance_h; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + if (!context || !content_info) + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + + instance_h = (appcore_multiwindow_base_instance_h)context; + id = appcore_multiwindow_base_instance_get_id(instance_h); + class_id = appcore_multiwindow_base_instance_get_class_id(instance_h); + data = appcore_multiwindow_base_instance_get_extra(instance_h); + + if (!class_id || !id || !data) + return WIDGET_BASE_ERROR_FAULT; + + ret = __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info); + + if (data->content) + free(data->content); + + bundle_encode(content_info, &raw, &len); + if (raw) + data->content = strdup((const char *)raw); + else + data->content = NULL; + + free(raw); + if (ret < 0) { + /* LCOV_EXCL_START */ + LOGE("failed to send content info: %s of %s (%d)", id, + class_id, ret); + return WIDGET_BASE_ERROR_IO_ERROR; + /* LCOV_EXCL_STOP */ + } + + return WIDGET_BASE_ERROR_NONE; +} + +EXPORT_API int widget_base_context_get_tag(widget_base_instance_h context, void **tag) +{ + appcore_multiwindow_base_instance_h instance_h; + widget_base_instance_data *data; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + if (!context || !tag) { + LOGE("Invalid parameter"); + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + } + + instance_h = (appcore_multiwindow_base_instance_h)context; + data = (widget_base_instance_data *) + appcore_multiwindow_base_instance_get_extra(instance_h); + + if (!data) { + LOGE("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + *tag = data->tag; + + return WIDGET_BASE_ERROR_NONE; +} + +EXPORT_API int widget_base_context_set_tag(widget_base_instance_h context, void *tag) +{ + appcore_multiwindow_base_instance_h instance_h; + widget_base_instance_data *data; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + if (!context) { + LOGE("Invalid parameter"); + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + } + + instance_h = (appcore_multiwindow_base_instance_h)context; + data = (widget_base_instance_data *) + appcore_multiwindow_base_instance_get_extra(instance_h); + data->tag = tag; + + return WIDGET_BASE_ERROR_NONE; +} + +EXPORT_API void *widget_base_context_get_user_data( + widget_base_instance_h context) +{ + appcore_multiwindow_base_instance_h instance_h; + widget_base_instance_data *data; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return NULL; /* LCOV_EXCL_LINE */ + } + + if (!context) { + LOGE("Invalid parameter"); + return NULL; + } + + instance_h = (appcore_multiwindow_base_instance_h)context; + data = (widget_base_instance_data *) + appcore_multiwindow_base_instance_get_extra(instance_h); + + return data->user_data; +} + + +EXPORT_API int widget_base_context_set_user_data( + widget_base_instance_h context, void *user_data) +{ + appcore_multiwindow_base_instance_h instance_h; + widget_base_instance_data *data; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + if (!context) { + LOGE("Invalid parameter"); + return WIDGET_BASE_ERROR_INVALID_PARAMETER; + } + + instance_h = (appcore_multiwindow_base_instance_h)context; + data = (widget_base_instance_data *) + appcore_multiwindow_base_instance_get_extra(instance_h); + data->user_data = user_data; + + return WIDGET_BASE_ERROR_NONE; +} + +EXPORT_API int widget_base_context_get_id(widget_base_instance_h context, char **id) +{ + appcore_multiwindow_base_instance_h instance_h; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + instance_h = (appcore_multiwindow_base_instance_h)context; + *id = (char *)appcore_multiwindow_base_instance_get_id(instance_h); + + return WIDGET_BASE_ERROR_NONE; +} + +EXPORT_API const char *widget_base_get_viewer_endpoint() +{ + return __viewer_endpoint; +} + +EXPORT_API int widget_base_init(widget_base_ops ops, int argc, char **argv, + void *data) +{ + bundle *kb; + char *viewer_endpoint = NULL; + appcore_multiwindow_base_ops raw_ops + = appcore_multiwindow_base_get_default_ops(); + + __context.ops = ops; + __context.argc = argc; + __context.argv = argv; + __context.data = data; + + /* override methods */ + raw_ops.base.create = __multiwindow_create; + raw_ops.base.control = __multiwindow_control; + raw_ops.base.terminate = __multiwindow_terminate; + raw_ops.base.receive = __multiwindow_receive; + raw_ops.base.init = __multiwindow_init; + raw_ops.base.finish = __multiwindow_finish; + raw_ops.base.run = __multiwindow_run; + raw_ops.base.exit = __multiwindow_exit; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); /* LCOV_EXCL_LINE */ + return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ + } + + kb = bundle_import_from_argv(argc, argv); + if (kb) { + bundle_get_str(kb, WIDGET_K_ENDPOINT, &viewer_endpoint); + if (viewer_endpoint) { + LOGD("viewer endpoint :%s", viewer_endpoint); + __viewer_endpoint = strdup(viewer_endpoint); + } else { + LOGE("endpoint is missing"); + } + + bundle_free(kb); + } else { + LOGE("failed to get launch argv"); /* LCOV_EXCL_LINE */ + return WIDGET_ERROR_FAULT; + } + + if (appcore_multiwindow_base_init(raw_ops, argc, argv, data) < 0) + return WIDGET_ERROR_FAULT; + + return WIDGET_ERROR_NONE; +} + +static int __on_create(void *data) +{ + return widget_base_on_create(); +} + +static int __on_terminate(void *data) +{ + return widget_base_on_terminate(); +} + +static void __on_init(int argc, char **argv, void *data) +{ + widget_base_on_init(argc, argv); +} + +static void __on_finish(void) +{ + widget_base_on_finish(); +} + +static void __on_run(void *data) +{ + widget_base_on_run(); +} + +static void __on_exit(void *data) +{ + widget_base_on_exit(); +} + +EXPORT_API int widget_base_on_create(void) +{ + appcore_multiwindow_base_on_create(); + + return 0; +} + +EXPORT_API int widget_base_on_terminate(void) +{ + appcore_multiwindow_base_on_terminate(); + + return 0; +} + +EXPORT_API int widget_base_on_init(int argc, char **argv) +{ + return 0; +} + +EXPORT_API void widget_base_on_finish(void) +{ +} + +EXPORT_API void widget_base_on_run(void) +{ +} + +EXPORT_API void widget_base_on_exit(void) +{ +} + +EXPORT_API widget_base_ops widget_base_get_default_ops(void) +{ + widget_base_ops ops; + + /* override methods */ + ops.create = __on_create; + ops.terminate = __on_terminate; + ops.init = __on_init; + ops.finish = __on_finish; + ops.run = __on_run; + ops.exit = __on_exit; + + return ops; +} + +static void __free_class(gpointer data) +{ + widget_base_class *cls = data; + + free(cls->id); + free(cls); +} + +EXPORT_API void widget_base_fini(void) +{ + g_list_free_full(__context.classes, __free_class); + __context.classes = NULL; + + appcore_multiwindow_base_fini(); +} + +EXPORT_API int widget_base_context_window_bind( + widget_base_instance_h instance_h, const char *id, + Ecore_Wl_Window *wl_win) +{ + struct wl_surface *surface; + + surface = ecore_wl_window_surface_get(wl_win); + if (surface == NULL) { + LOGE("failed to get surface"); /* LCOV_EXCL_LINE */ + return WIDGET_BASE_ERROR_FAULT; /* LCOV_EXCL_LINE */ + } + + screen_connector_provider_remote_enable(id, surface); + appcore_multiwindow_base_window_bind(instance_h, wl_win); + + return WIDGET_BASE_ERROR_NONE; +} + +static int __class_on_create(widget_base_instance_h instance_h, bundle *content, + int w, int h, void *class_data) +{ + return widget_base_class_on_create(instance_h, content, w, h); +} + +static int __class_on_resume(widget_base_instance_h instance_h, void *class_data) +{ + return widget_base_class_on_resume(instance_h); +} + +static int __class_on_pause(widget_base_instance_h instance_h, + void *class_data) +{ + return widget_base_class_on_pause(instance_h); +} + +static int __class_on_resize(widget_base_instance_h instance_h, int w, int h, + void *class_data) +{ + return widget_base_class_on_resize(instance_h, w, h); +} + +static int __class_on_update(widget_base_instance_h instance_h, bundle *content, + int force, void *class_data) +{ + return widget_base_class_on_update(instance_h, content, force); +} + +static int __class_on_destroy(widget_base_instance_h instance_h, + widget_base_destroy_type_e reason, bundle *content, + void *class_data) +{ + return widget_base_class_on_destroy(instance_h, reason, content); +} + +static void __multiwindow_instance_create( + appcore_multiwindow_base_instance_h instance_h, + void *class_data) +{ + widget_base_instance_data *instance_data; + bundle *b; + bundle *content_info = NULL; + char *id = NULL; + char *class_id = NULL; + char *operation = NULL; + char *content = NULL; + char *w_str = NULL; + char *h_str = NULL; + char *remain = NULL; + int w = 0; + int h = 0; + int ret = -1; + widget_base_class cls; + + appcore_multiwindow_base_class_on_create(instance_h); + instance_data = appcore_multiwindow_base_instance_get_extra(instance_h); + b = instance_data->args; + + bundle_get_str(b, WIDGET_K_CLASS, &class_id); + /* for previous version compatibility, use appid for default class id */ + if (class_id == NULL) + class_id = __appid; + + cls = __get_class(class_id); + bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id); + bundle_get_str(b, WIDGET_K_OPERATION, &operation); + + if (!operation) { + LOGE("no operation provided"); + return; + } + + bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content); + bundle_get_str(b, WIDGET_K_WIDTH, &w_str); + bundle_get_str(b, WIDGET_K_HEIGHT, &h_str); + + if (w_str) + w = (int)g_ascii_strtoll(w_str, &remain, 10); + + if (h_str) + h = (int)g_ascii_strtoll(h_str, &remain, 10); + + if (content) + content_info = bundle_decode((const bundle_raw *)content, + strlen(content)); + + if (cls.ops.create) + ret = cls.ops.create(instance_h, content_info, w, h, class_data); + + if (ret < 0) { + LOGW("Create callback returns error(%d)", ret); + ret = __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_CREATE_ABORTED, NULL); + __instance_drop(instance_h); + } else { + LOGD("%s is created", id); + ret = __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_CREATE, NULL); + + aul_widget_instance_add(class_id, id); + } + + if (content_info) + bundle_free(content_info); +} + +static void __multiwindow_instance_resume( + appcore_multiwindow_base_instance_h instance_h, + void *class_data) +{ + const char *id; + const char *class_id; + widget_base_class cls; + + appcore_multiwindow_base_class_on_resume(instance_h); + id = appcore_multiwindow_base_instance_get_id(instance_h); + class_id = appcore_multiwindow_base_instance_get_class_id(instance_h); + cls = __get_class(class_id); + + if (cls.ops.resume) + cls.ops.resume(instance_h, class_data); + + LOGD("%s is resumed", id); + __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_RESUME, NULL); + + if (!__fg_signal) { + LOGD("Send fg signal to resourceD"); + aul_send_app_status_change_signal(getpid(), + __appid, + __package_id, + STATUS_FOREGROUND, + APP_TYPE_WIDGET); + __fg_signal = true; + } +} + +static void __multiwindow_instance_pause( + appcore_multiwindow_base_instance_h instance_h, + void *class_data) +{ + const char *id; + const char *class_id; + widget_base_class cls; + + appcore_multiwindow_base_class_on_pause(instance_h); + id = appcore_multiwindow_base_instance_get_id(instance_h); + class_id = appcore_multiwindow_base_instance_get_class_id(instance_h); + cls = __get_class(class_id); + + if (cls.ops.pause) + cls.ops.pause(instance_h, class_data); + + LOGD("%s is paused", id); + __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_PAUSE, NULL); + + if (__fg_signal) { + LOGD("Send bg signal to resourceD"); + aul_send_app_status_change_signal(getpid(), + __appid, + __package_id, + STATUS_BACKGROUND, + APP_TYPE_WIDGET); + __fg_signal = false; + } +} + +static void __multiwindow_instance_terminate( + appcore_multiwindow_base_instance_h instance_h, + void *class_data) +{ + widget_base_instance_data *data; + bundle *b; + char *operation = NULL; + bundle *content_info; + widget_base_destroy_type_e reason = WIDGET_BASE_DESTROY_TYPE_TEMPORARY; + int event = WIDGET_INSTANCE_EVENT_TERMINATE; + const char *id; + const char *class_id; + widget_base_class cls; + + id = appcore_multiwindow_base_instance_get_id(instance_h); + class_id = appcore_multiwindow_base_instance_get_class_id(instance_h); + data = appcore_multiwindow_base_instance_get_extra( + (appcore_multiwindow_base_instance_h)instance_h); + b = data->args; + cls = __get_class(class_id); + + if (b) { + bundle_get_str(b, WIDGET_K_OPERATION, &operation); + if (operation && strcmp(operation, "destroy") == 0) + reason = WIDGET_BASE_DESTROY_TYPE_PERMANENT; + } + + if (data->content) + content_info = bundle_decode((const bundle_raw *)data->content, + strlen(data->content)); + else + content_info = bundle_create(); + + if (cls.ops.destroy) + cls.ops.destroy(instance_h, reason, content_info, class_data); + + LOGD("%s is destroyed %d", id, reason); + if (reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) { + event = WIDGET_INSTANCE_EVENT_DESTROY; + aul_widget_instance_del(class_id, id); + } else { + __send_update_status(class_id, id, + WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, + content_info); + } + + if (content_info) + bundle_free(content_info); + + __send_update_status(class_id, id, event, NULL); + appcore_multiwindow_base_class_on_terminate(instance_h); +} + +EXPORT_API int widget_base_class_on_create(widget_base_instance_h instance_h, + bundle *content, int w, int h) +{ + appcore_multiwindow_base_class_on_create(instance_h); + + return 0; +} + +EXPORT_API int widget_base_class_on_pause(widget_base_instance_h instance_h) +{ + appcore_multiwindow_base_class_on_pause(instance_h); + + return 0; +} + +EXPORT_API int widget_base_class_on_resume(widget_base_instance_h instance_h) +{ + appcore_multiwindow_base_class_on_resume(instance_h); + + return 0; +} + +EXPORT_API int widget_base_class_on_resize(widget_base_instance_h instance_h, + int w, int h) +{ + return 0; +} + +EXPORT_API int widget_base_class_on_update(widget_base_instance_h instance_h, + bundle *content, int force) +{ + return 0; +} + +EXPORT_API int widget_base_class_on_destroy(widget_base_instance_h instance_h, + widget_base_destroy_type_e reason, bundle *content) +{ + appcore_multiwindow_base_class_on_terminate(instance_h); + + return 0; +} + +EXPORT_API widget_base_class widget_base_class_get_default(void) +{ + widget_base_class cls; + + cls.ops.create = __class_on_create; + cls.ops.resize = __class_on_resize; + cls.ops.update = __class_on_update; + cls.ops.destroy = __class_on_destroy; + cls.ops.pause = __class_on_pause; + cls.ops.resume = __class_on_resume; + + return cls; +} + +EXPORT_API widget_base_class *widget_base_class_add(widget_base_class cls, + const char *class_id, void *class_data) +{ + widget_base_class *c; + appcore_multiwindow_base_class raw_cls; + + if (!__is_widget_feature_enabled()) { + LOGE("not supported"); + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return NULL; + } + + if (!class_id) { + LOGE("class is is NULL"); + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return NULL; + } + + raw_cls.id = strdup(class_id); + raw_cls.data = class_data; + raw_cls.create = __multiwindow_instance_create; + raw_cls.terminate = __multiwindow_instance_terminate; + raw_cls.pause = __multiwindow_instance_pause; + raw_cls.resume = __multiwindow_instance_resume; + appcore_multiwindow_base_class_add(raw_cls); + + c = malloc(sizeof(widget_base_class)); + if (!c) + return NULL; + + *c = cls; + c->id = strdup(class_id); + __context.classes = g_list_append(__context.classes, c); + + return c; +} diff --git a/src/widget-log.h b/src/efl_base/widget-log.h old mode 100755 new mode 100644 similarity index 100% rename from src/widget-log.h rename to src/efl_base/widget-log.h diff --git a/src/widget-private.h b/src/efl_base/widget-private.h similarity index 92% rename from src/widget-private.h rename to src/efl_base/widget-private.h index 293e226..34fdc5f 100644 --- a/src/widget-private.h +++ b/src/efl_base/widget-private.h @@ -25,8 +25,6 @@ #include #include -#define FEATURE_SHELL_APPWIDGET "http://tizen.org/feature/shell.appwidget" - int widget_app_error(widget_error_e error, const char *function, const char *description); diff --git a/src/efl_base/widget_app.c b/src/efl_base/widget_app.c new file mode 100644 index 0000000..640dca2 --- /dev/null +++ b/src/efl_base/widget_app.c @@ -0,0 +1,518 @@ +/* + * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "widget_base.h" +#include "widget_app.h" +#include "widget-log.h" +#include "widget-private.h" +#include "widget_app_internal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_WIDGET_APPLICATION" + +struct instance_data { + Evas_Object *win; +}; + +struct app_cb_info { + widget_app_lifecycle_callback_s *callback; + void *user_data; +}; + +struct app_class_cb_info { + widget_instance_lifecycle_callback_s callback; + void *user_data; +}; + +static int __class_resize(widget_base_instance_h instance_h, int w, int h, + void *class_data) +{ + int ret = 0; + struct instance_data *data; + struct app_class_cb_info *callback_data = + (struct app_class_cb_info *)class_data; + + widget_base_class_on_resize(instance_h, w, h); + data = (struct instance_data *) + widget_base_context_get_user_data(instance_h); + if (data->win) + evas_object_resize(data->win, w, h); + else + _E("unable to find window"); + + if (callback_data && callback_data->callback.resize) { + ret = callback_data->callback.resize( + (widget_context_h)instance_h, + w, h, callback_data->user_data); + } + + return ret; +} + +static int __class_update(widget_base_instance_h instance_h, bundle *content, + int force, void *class_data) +{ + int ret = 0; + struct app_class_cb_info *callback_data = + (struct app_class_cb_info *)class_data; + + widget_base_class_on_update(instance_h, content, force); + if (callback_data && callback_data->callback.update) { + ret = callback_data->callback.update( + (widget_context_h)instance_h, + content, force, callback_data->user_data); + } + + return ret; +} + +static int __class_create(widget_base_instance_h instance_h, bundle *content, + int w, int h, void *class_data) +{ + int ret = -1; + struct app_class_cb_info *callback_data = + (struct app_class_cb_info *)class_data; + + widget_base_class_on_create(instance_h, content, w, h); + if (callback_data && callback_data->callback.create) { + ret = callback_data->callback.create( + (widget_context_h)instance_h, + content, w, h, callback_data->user_data); + } + return ret; +} + +static int __class_destroy(widget_base_instance_h instance_h, + widget_base_destroy_type_e reason, bundle *content, + void *class_data) +{ + int ret = 0; + struct instance_data *data; + struct app_class_cb_info *callback_data = + (struct app_class_cb_info *)class_data; + + if (callback_data && callback_data->callback.destroy) { + ret = callback_data->callback.destroy( + (widget_context_h)instance_h, + reason, content, callback_data->user_data); + } + + data = (struct instance_data *)widget_base_context_get_user_data(instance_h); + if (data != NULL) { + widget_base_context_set_user_data(instance_h, NULL); + free(data); + } + + widget_base_class_on_destroy(instance_h, reason, content); + + return ret; +} + +static int __class_pause(widget_base_instance_h instance_h, void *class_data) +{ + int ret = 0; + struct app_class_cb_info *callback_data = + (struct app_class_cb_info *)class_data; + + widget_base_class_on_pause(instance_h); + if (callback_data && callback_data->callback.pause) { + ret = callback_data->callback.pause( + (widget_context_h)instance_h, + callback_data->user_data); + } + + return ret; +} + +static int __class_resume(widget_base_instance_h instance_h, void *class_data) +{ + int ret = 0; + struct app_class_cb_info *callback_data = + (struct app_class_cb_info *)class_data; + + widget_base_class_on_resume(instance_h); + if (callback_data && callback_data->callback.resume) { + ret = callback_data->callback.resume( + (widget_context_h)instance_h, + callback_data->user_data); + } + + return ret; +} + +static int __widget_app_create(void *data) +{ + struct app_cb_info *cb_info = (struct app_cb_info *)data; + widget_app_lifecycle_callback_s *callback; + + widget_base_on_create(); + if (cb_info && cb_info->callback && cb_info->callback->create) { + callback = cb_info->callback; + if (callback->create(cb_info->user_data) == NULL) { + _D("fail to create widget"); + return -1; + } + _D("widget app is created"); + return 0; + } + + return -1; +} + +static int __widget_app_terminate(void *data) +{ + struct app_cb_info *cb_info = (struct app_cb_info *)data; + widget_app_lifecycle_callback_s *callback; + + if (cb_info && cb_info->callback && cb_info->callback->terminate) { + callback = cb_info->callback; + callback->terminate(cb_info->user_data); + widget_base_on_terminate(); + _D("widget app is terminated"); + + return 0; + } + + widget_base_on_terminate(); + + return -1; +} + +static void __widget_app_init(int argc, char **argv, void *data) +{ + elm_init(argc, argv); +} + +static void __widget_app_finish(void) +{ + elm_shutdown(); +} + +static void __widget_app_run(void *data) +{ + elm_run(); +} + +static void __widget_app_exit(void *data) +{ + elm_exit(); +} + +EXPORT_API int widget_app_main(int argc, char **argv, + widget_app_lifecycle_callback_s *callback, void *user_data) +{ + widget_base_ops ops; + struct app_cb_info cb_info; + int r; + + if (argc <= 0 || argv == NULL || callback == NULL) + return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, + __FUNCTION__, NULL); + + if (callback->create == NULL) + return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, + __FUNCTION__, + "widget_app_create_cb() callback must be " + "registered"); + + ops.create = __widget_app_create; + ops.terminate = __widget_app_terminate; + ops.init = __widget_app_init; + ops.finish = __widget_app_finish; + ops.run = __widget_app_run; + ops.exit = __widget_app_exit; + + cb_info.callback = callback; + cb_info.user_data = user_data; + + r = widget_base_init(ops, argc, argv, &cb_info); + widget_base_fini(); + + return r; +} + +EXPORT_API int widget_app_exit(void) +{ + return widget_base_exit(); +} + +EXPORT_API int widget_app_terminate_context(widget_context_h context) +{ + return widget_base_terminate_context((widget_base_instance_h)context); +} + +EXPORT_API int widget_app_foreach_context(widget_context_cb cb, void *data) +{ + return widget_base_foreach_context((widget_base_instance_cb)cb, data); +} + +EXPORT_API int widget_app_add_event_handler(app_event_handler_h *event_handler, + app_event_type_e event_type, + app_event_cb callback, + void *user_data) +{ + return widget_base_add_event_handler(event_handler, event_type, + callback, user_data); +} + +EXPORT_API int widget_app_remove_event_handler(app_event_handler_h + event_handler) +{ + return widget_base_remove_event_handler(event_handler); +} + +EXPORT_API const char *widget_app_get_id(widget_context_h context) +{ + int ret; + char *id; + + if (!context) { + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return NULL; + } + + ret = widget_base_context_get_id((widget_base_instance_h)context, &id); + if (ret != WIDGET_BASE_ERROR_NONE) { + _E("failed to get context id"); /* LCOV_EXCL_LINE */ + set_last_result(ret); /* LCOV_EXCL_LINE */ + return NULL; /* LCOV_EXCL_LINE */ + } + + set_last_result(WIDGET_ERROR_NONE); + return id; +} + +static void __win_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + char *plug_id; + plug_id = evas_object_data_del(obj, "___PLUGID"); + free(plug_id); +} + +EXPORT_API int widget_app_get_elm_win(widget_context_h context, + Evas_Object **win) +{ + Evas_Object *ret_win = NULL; + Ecore_Wl_Window *wl_win; + struct instance_data *data; + char buffer[256]; + int rots[3] = {0}; + int win_id; + char *id; + int ret; + + if (context == NULL || win == NULL) + return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, + __FUNCTION__, NULL); + + ret = widget_base_context_get_id((widget_base_instance_h)context, &id); + if (ret != WIDGET_BASE_ERROR_NONE) { + _E("failed to get context id"); /* LCOV_EXCL_LINE */ + goto fault; /* LCOV_EXCL_LINE */ + } + + ret_win = elm_win_add(NULL, id, ELM_WIN_BASIC); + if (ret_win == NULL) { + _E("failed to create window"); /* LCOV_EXCL_LINE */ + goto fault; /* LCOV_EXCL_LINE */ + } + + elm_win_wm_rotation_preferred_rotation_set(ret_win, -1); + elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1); + + wl_win = elm_win_wl_window_get(ret_win); + if (wl_win == NULL) { + _E("failed to get wayland window"); /* LCOV_EXCL_LINE */ + goto fault; + } + + ecore_wl_window_class_name_set(wl_win, id); + elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1"); + widget_base_context_window_bind((widget_base_instance_h)context, id, wl_win); + + /* Set data to use in accessibility */ + snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid()); + evas_object_data_set(ret_win, "___PLUGID", strdup(buffer)); + evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL); + + win_id = ecore_wl_window_id_get(wl_win); + _D("window created: %d", win_id); + + data = (struct instance_data *)widget_base_context_get_user_data( + (widget_base_instance_h)context); + if (data == NULL) { + data = calloc(1, sizeof(struct instance_data)); + if (data == NULL) { + _E("failed to alloc instance_data"); /* LCOV_EXCL_LINE */ + goto fault; /* LCOV_EXCL_LINE */ + } + + ret = widget_base_context_set_user_data((widget_base_instance_h)context, data); + if (ret != WIDGET_BASE_ERROR_NONE) { + _E("fail to set extra data"); /* LCOV_EXCL_LINE */ + goto fault; /* LCOV_EXCL_LINE */ + } + } + + data->win = ret_win; + *win = ret_win; + + return WIDGET_ERROR_NONE; + +fault: + if (ret_win) /* LCOV_EXCL_LINE */ + evas_object_del(ret_win); /* LCOV_EXCL_LINE */ + + return WIDGET_ERROR_FAULT; /* LCOV_EXCL_LINE */ +} + +EXPORT_API widget_class_h widget_app_class_add(widget_class_h widget_class, + const char *class_id, + widget_instance_lifecycle_callback_s callback, void *user_data) +{ + widget_base_class cls; + struct app_class_cb_info *callback_data; + widget_class_h wc; + + cls = widget_base_class_get_default(); + + /* override methods */ + cls.ops.create = __class_create; + cls.ops.destroy = __class_destroy; + cls.ops.pause = __class_pause; + cls.ops.resume = __class_resume; + cls.ops.resize = __class_resize; + cls.ops.update = __class_update; + + callback_data = calloc(1, sizeof(struct app_class_cb_info)); + if (!callback_data) { + _E("failed to calloc : %s", __FUNCTION__); + set_last_result(WIDGET_ERROR_OUT_OF_MEMORY); + return NULL; + } + callback_data->callback = callback; + callback_data->user_data = user_data; + + wc = (widget_class_h)widget_base_class_add(cls, class_id, + callback_data); + + if (!wc) { + free(callback_data); + return NULL; + } + + set_last_result(WIDGET_ERROR_NONE); + + return wc; +} + +EXPORT_API widget_class_h widget_app_class_create( + widget_instance_lifecycle_callback_s callback, void *user_data) +{ + char *appid; + widget_class_h wc; + + app_get_id(&appid); + if (!appid) { + LOGE("appid is NULL"); + return NULL; + } + + wc = (widget_class_h)widget_app_class_add(NULL, appid, callback, + user_data); + free(appid); + + return wc; +} + +EXPORT_API int widget_app_context_set_tag(widget_context_h context, void *tag) +{ + int ret = 0; + + ret = widget_base_context_set_tag((widget_base_instance_h)context, tag); + if (ret != WIDGET_BASE_ERROR_NONE) + return widget_app_error(ret, __FUNCTION__, NULL); + + return WIDGET_ERROR_NONE; +} + +EXPORT_API int widget_app_context_get_tag(widget_context_h context, void **tag) +{ + int ret = 0; + + ret = widget_base_context_get_tag((widget_base_instance_h)context, tag); + if (ret != WIDGET_BASE_ERROR_NONE) + return widget_app_error(ret, __FUNCTION__, NULL); + + return WIDGET_ERROR_NONE; +} + +EXPORT_API int widget_app_context_set_content_info(widget_context_h context, + bundle *content_info) +{ + int ret = 0; + + ret = widget_base_context_set_content_info( + (widget_base_instance_h)context, content_info); + if (ret != WIDGET_BASE_ERROR_NONE) + return widget_app_error(ret, __FUNCTION__, NULL); + + return WIDGET_ERROR_NONE; +} + +EXPORT_API int widget_app_context_set_title(widget_context_h context, + const char *title) +{ + struct instance_data *data = NULL; + int ret; + + if (!context || !title) { + _E("Invalid parameter %p %p", context, title); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + data = (struct instance_data *)widget_base_context_get_user_data( + (widget_base_instance_h)context); + if (data == NULL) { + data = calloc(1, sizeof(struct instance_data)); + if (data == NULL) { + return widget_app_error(WIDGET_ERROR_FAULT, + __FUNCTION__, NULL); + } + ret = widget_base_context_set_user_data(context, data); + if (ret != WIDGET_BASE_ERROR_NONE) + widget_app_error(ret, __FUNCTION__, NULL); + } + + if (data->win) + elm_win_title_set(data->win, title); + + return WIDGET_ERROR_NONE; +} diff --git a/src/widget_app_internal.c b/src/efl_base/widget_app_internal.c similarity index 95% rename from src/widget_app_internal.c rename to src/efl_base/widget_app_internal.c index 302248f..43de979 100644 --- a/src/widget_app_internal.c +++ b/src/efl_base/widget_app_internal.c @@ -34,13 +34,13 @@ #include "widget-private.h" #include "widget_app_internal.h" #include "widget-private.h" +#include "widget_base.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "CAPI_WIDGET_APPLICATION" -extern char *_viewer_endpoint; static char *__class_id; static void __inst_cb(const char *class_id, const char *id, @@ -61,7 +61,7 @@ EXPORT_API int widget_app_restart(void) kb = bundle_create(); bundle_add_str(kb, AUL_K_WIDGET_ID, __class_id); bundle_add_byte(kb, AUL_K_WIDGET_STATUS, &status, sizeof(int)); - ret = aul_app_com_send(_viewer_endpoint, kb); + ret = aul_app_com_send(widget_base_get_viewer_endpoint(), kb); bundle_free(kb); if (__class_id) { free(__class_id); diff --git a/src/widget_error.c b/src/efl_base/widget_error.c old mode 100755 new mode 100644 similarity index 100% rename from src/widget_error.c rename to src/efl_base/widget_error.c diff --git a/src/widget_app.c b/src/widget_app.c deleted file mode 100755 index 5479b95..0000000 --- a/src/widget_app.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* - * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "widget_app.h" -#include "widget-log.h" -#include "widget-private.h" -#include "widget_app_internal.h" - -#ifdef LOG_TAG -#undef LOG_TAG -#endif - -#define LOG_TAG "CAPI_WIDGET_APPLICATION" -#define APP_TYPE_WIDGET "widgetapp" -#define STATUS_FOREGROUND "fg" -#define STATUS_BACKGROUND "bg" - -struct widget_extra { - void *extra; - char *instance_id; - bundle *args; - char *content; - Evas_Object *win; -}; - -struct widget_class_context { - widget_instance_lifecycle_callback_s callback; - void *data; -}; - -struct widget_app_context { - widget_app_lifecycle_callback_s callback; - void *data; - bool dirty; -}; - -struct widget_foreach_context { - widget_context_cb callback; - void *data; -}; - -struct app_event_info { - app_event_type_e type; - void *value; -}; - -struct app_event_handler { - app_event_type_e type; - app_event_cb cb; - void *data; - void *raw; -}; - -struct _widget_context { - int dummy; -}; - -static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = { - [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY, - [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY, - [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE, - [APP_EVENT_DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED, - [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE, - [APP_EVENT_SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE, -}; - -static struct widget_app_context __context; -static char *__appid; -static char *__package_id; -static bool __fg_signal; -char *_viewer_endpoint; - -static bool __is_widget_feature_enabled(void) -{ - static bool feature = false; - static bool retrieved = false; - int ret; - - if (retrieved == true) - return feature; - - ret = system_info_get_platform_bool( - "http://tizen.org/feature/shell.appwidget", &feature); - if (ret != SYSTEM_INFO_ERROR_NONE) { - _E("failed to get system info"); /* LCOV_EXCL_LINE */ - return false; /* LCOV_EXCL_LINE */ - } - - retrieved = true; - - return feature; -} - -/* LCOV_EXCL_START */ -static void __on_poweroff(keynode_t *key, void *data) -{ - int val; - - val = vconf_keynode_get_int(key); - switch (val) { - case VCONFKEY_SYSMAN_POWER_OFF_DIRECT: - case VCONFKEY_SYSMAN_POWER_OFF_RESTART: - _I("power off changed: %d", val); - widget_app_exit(); - break; - case VCONFKEY_SYSMAN_POWER_OFF_NONE: - case VCONFKEY_SYSMAN_POWER_OFF_POPUP: - default: - /* DO NOTHING */ - break; - } -} -/* LCOV_EXCL_STOP */ - -static int __widget_app_create(void *data) -{ - char pkgid[256] = {0, }; - - appcore_multiwindow_base_on_create(); - app_get_id(&__appid); - if (aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0) - __package_id = strdup(pkgid); - - if (!__package_id || !__appid) { - _E("__package_id is NULL"); - return -1; - } - - screen_connector_provider_init(); - vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, __on_poweroff, NULL); - - if (__context.callback.create == NULL) { - _E("__context.callback.create(is NULL"); - return -1; - } - - if (__context.callback.create(__context.data) == NULL) { - _E("app_create_cb() returns NULL"); - return -1; - } - - _D("widget app is created"); - return 0; -} - -static int __widget_app_terminate(void *data) -{ - if (__context.callback.terminate) - __context.callback.terminate(__context.data); - - vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, __on_poweroff); - screen_connector_provider_fini(); - - if (_viewer_endpoint) { - free(_viewer_endpoint); - _viewer_endpoint = NULL; - } - - if (__package_id) { - free(__package_id); - __package_id = NULL; - } - - if (__appid) { - free(__appid); - __appid = NULL; - } - - appcore_multiwindow_base_on_terminate(); - - _D("widget app is terminated"); - return 0; -} - -static int __send_lifecycle_event(const char *class_id, const char *instance_id, - int status) -{ - bundle *b = bundle_create(); - int ret; - - if (b == NULL) { - _E("out of memory"); /* LCOV_EXCL_LINE */ - return -1; /* LCOV_EXCL_LINE */ - } - - bundle_add_str(b, AUL_K_WIDGET_ID, class_id); - bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id); - bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int)); - bundle_add_str(b, AUL_K_PKGID, __package_id); - - _D("send lifecycle %s(%d)", instance_id, status); - ret = aul_app_com_send("widget.status", b); - if (ret < 0) - _E("send lifecycle error:%d", ret); /* LCOV_EXCL_LINE */ - - bundle_free(b); - - return ret; -} - -static int __send_update_status(const char *class_id, const char *instance_id, - int status, bundle *extra) -{ - bundle *b; - int lifecycle = -1; - bundle_raw *raw = NULL; - int len; - - b = bundle_create(); - if (!b) { - _E("out of memory"); /* LCOV_EXCL_LINE */ - return -1; /* LCOV_EXCL_LINE */ - } - - bundle_add_str(b, AUL_K_WIDGET_ID, class_id); - bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id); - bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int)); - - if (extra) { - bundle_encode(extra, &raw, &len); - bundle_add_str(b, WIDGET_K_CONTENT_INFO, (const char *)raw); - aul_widget_instance_add(class_id, instance_id); - } - - _D("send update %s(%d) to %s", instance_id, status, _viewer_endpoint); - aul_app_com_send(_viewer_endpoint, b); - - switch (status) { - case WIDGET_INSTANCE_EVENT_CREATE: - lifecycle = WIDGET_LIFE_CYCLE_EVENT_CREATE; - break; - case WIDGET_INSTANCE_EVENT_DESTROY: - lifecycle = WIDGET_LIFE_CYCLE_EVENT_DESTROY; - break; - case WIDGET_INSTANCE_EVENT_PAUSE: - lifecycle = WIDGET_LIFE_CYCLE_EVENT_PAUSE; - break; - case WIDGET_INSTANCE_EVENT_RESUME: - lifecycle = WIDGET_LIFE_CYCLE_EVENT_RESUME; - break; - } - - if (lifecycle > -1) - __send_lifecycle_event(class_id, instance_id, lifecycle); - - bundle_free(b); - if (raw) - free(raw); - - return 0; -} - -static void __instance_resume(const char *class_id, const char *id, bundle *b) -{ - appcore_multiwindow_base_instance_h cxt; - - cxt = appcore_multiwindow_base_instance_find(id); - - if (!cxt) { - _E("context not found: %s", id); - return; - } - - appcore_multiwindow_base_instance_resume(cxt); - - __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_RESUME, NULL); - if (!__fg_signal) { - _D("Send fg signal to resourceD"); - aul_send_app_status_change_signal(getpid(), - __appid, - __package_id, - STATUS_FOREGROUND, - APP_TYPE_WIDGET); - __fg_signal = true; - } -} - -static void __instance_pause(const char *class_id, const char *id, bundle *b) -{ - appcore_multiwindow_base_instance_h cxt; - - cxt = appcore_multiwindow_base_instance_find(id); - - if (!cxt) { - _E("context not found: %s", id); - return; - } - - appcore_multiwindow_base_instance_pause(cxt); - - if (__fg_signal) { - _D("Send bg signal to resourceD"); - aul_send_app_status_change_signal(getpid(), - __appid, - __package_id, - STATUS_BACKGROUND, - APP_TYPE_WIDGET); - __fg_signal = false; - } -} - -static void __instance_resize(const char *class_id, const char *id, bundle *b) -{ - appcore_multiwindow_base_instance_h cxt; - struct widget_class_context *class_cxt; - const appcore_multiwindow_base_class *cls; - struct widget_extra *we; - char *remain = NULL; - char *w_str = NULL; - char *h_str = NULL; - int w = 0; - int h = 0; - - cxt = appcore_multiwindow_base_instance_find(id); - - if (!cxt) { - _E("context not found: %s", id); - return; - } - - cls = appcore_multiwindow_base_instance_get_class(cxt); - if (!cls) - return; - - class_cxt = cls->data; - if (!class_cxt) { - _E("class is NULL"); - return; - } - - we = appcore_multiwindow_base_instance_get_extra(cxt); - if (!we) { - _E("widget extra is NULL"); - return; - } - - bundle_get_str(b, WIDGET_K_WIDTH, &w_str); - bundle_get_str(b, WIDGET_K_HEIGHT, &h_str); - - if (w_str) - w = (int)g_ascii_strtoll(w_str, &remain, 10); - - if (h_str) - h = (int)g_ascii_strtoll(h_str, &remain, 10); - - if (we->win) - evas_object_resize(we->win, w, h); - else - _E("unable to find window of %s", id); - - if (class_cxt->callback.resize) - class_cxt->callback.resize(cxt, w, h, class_cxt->data); - _D("%s is resized to %dx%d", id, w, h); - __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_SIZE_CHANGED, NULL); -} - -static void __inst_cb(const char *class_id, const char *id, - appcore_multiwindow_base_instance_h cxt, void *data) -{ - struct widget_class_context *class_cxt; - const appcore_multiwindow_base_class *cls; - bundle *content = NULL; - char *content_raw = NULL; - char *force_str = NULL; - int force; - bundle *b = data; - - if (!b) { - _E("bundle is NULL"); - return; - } - - cls = appcore_multiwindow_base_instance_get_class(cxt); - if (!cls) { - _E("class is NULL"); - return; - } - - class_cxt = cls->data; - if (!class_cxt) { - _E("class context is NULL"); - return; - } - - if (!class_cxt->callback.update) { - _E("update callback is NULL"); - return; - } - - bundle_get_str(b, WIDGET_K_FORCE, &force_str); - - if (force_str && strcmp(force_str, "true") == 0) - force = 1; - else - force = 0; - - bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw); - - if (content_raw) - content = bundle_decode((const bundle_raw *)content_raw, strlen(content_raw)); - class_cxt->callback.update(cxt, content, force, class_cxt->data); - __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_UPDATE, NULL); - _D("updated:%s", id); - - if (content) - bundle_free(content); -} - -static void __instance_update(const char *class_id, const char *id, bundle *b) -{ - appcore_multiwindow_base_instance_h cxt; - - if (!id) { - appcore_multiwindow_base_instance_foreach(class_id, __inst_cb, b); - return; - } - - cxt = appcore_multiwindow_base_instance_find(id); - - if (!cxt) { - _E("context not found: %s", id); - return; - } - - __inst_cb(class_id, id, cxt, b); -} - -static void __instance_create(const char *class_id, const char *id, bundle *b) -{ - struct widget_extra *we; - char *content = NULL; - - we = (struct widget_extra *)calloc(1, sizeof(struct widget_extra)); - if (!we) { - _E("Out of memory"); - return; - } - - we->instance_id = strdup(id); - we->args = b; - appcore_multiwindow_base_instance_run(class_id, id, we); - we->args = NULL; - we->win = NULL; - bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content); - if (content) - we->content = strdup(content); - -} - -static void __check_empty_instance(void) -{ - int cnt = appcore_multiwindow_base_instance_get_cnt(); - - if (cnt == 0) - widget_app_exit(); -} - -static void __instance_destroy(const char *class_id, const char *id, bundle *b) -{ - appcore_multiwindow_base_instance_h cxt; - struct widget_extra *we; - - cxt = appcore_multiwindow_base_instance_find(id); - if (!cxt) { - _E("could not find widget obj: %s, clear amd info", id); - aul_widget_instance_del(class_id, id); - return; - } - - we = appcore_multiwindow_base_instance_get_extra(cxt); - we->args = b; - appcore_multiwindow_base_instance_exit(cxt); - free(we->instance_id); - free(we->content); - free(we); - __check_empty_instance(); -} - -static int __widget_app_control(bundle *b, void *data) -{ - char *class_id = NULL; - char *id = NULL; - char *operation = NULL; - - appcore_multiwindow_base_on_control(b); - - bundle_get_str(b, WIDGET_K_CLASS, &class_id); - /* for previous version compatibility, use appid for default class id */ - if (class_id == NULL) - class_id = __appid; - - bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id); - bundle_get_str(b, WIDGET_K_OPERATION, &operation); - - if (!operation) { - _E("operation is NULL"); - return 0; - } - - if (strcmp(operation, "create") == 0) { - __instance_create(class_id, id, b); - } else if (strcmp(operation, "resize") == 0) { - __instance_resize(class_id, id, b); - } else if (strcmp(operation, "update") == 0) { - __instance_update(class_id, id, b); - } else if (strcmp(operation, "destroy") == 0) { - __instance_destroy(class_id, id, b); - } else if (strcmp(operation, "resume") == 0) { - __instance_resume(class_id, id, b); - } else if (strcmp(operation, "pause") == 0) { - __instance_pause(class_id, id, b); - } else if (strcmp(operation, "terminate") == 0) { - __instance_destroy(class_id, id, b); - } - - return 0; -} - -static void __inst_resume_cb(const char *class_id, const char *id, - appcore_multiwindow_base_instance_h cxt, void *data) -{ - __instance_resume(class_id, id, data); -} - -static void __get_content(bundle *b) -{ - char *instance_id = NULL; - appcore_multiwindow_base_instance_h cxt; - struct widget_extra *we; - - bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &instance_id); - if (!instance_id) { - _E("instance id is NULL"); - return; - } - - cxt = appcore_multiwindow_base_instance_find(instance_id); - if (!cxt) { - _E("could not find widget obj: %s", instance_id); - return; - } - - we = appcore_multiwindow_base_instance_get_extra(cxt); - if (!we) { - _E("widget extra is NULL"); - return; - } - - if (we->content) { - bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, we->content); - _D("content info of %s found", instance_id); - } else { - bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, ""); - _D("empty content info added"); - } -} - -static int __widget_app_receive(aul_type type, bundle *b, void *data) -{ - appcore_multiwindow_base_on_receive(type, b); - - switch (type) { - case AUL_RESUME: - appcore_multiwindow_base_instance_foreach_full(__inst_resume_cb, b); - break; - case AUL_TERMINATE: - widget_app_exit(); - break; - case AUL_WIDGET_CONTENT: - __get_content(b); - break; - default: - break; - } - - return 0; -} - -static void __widget_app_init(int argc, char **argv, void *data) -{ - elm_init(argc, argv); -} - -static void __widget_app_finish(void) -{ - elm_shutdown(); - - /* Check Loader case */ - if (getenv("AUL_LOADER_INIT")) { - unsetenv("AUL_LOADER_INIT"); - elm_shutdown(); - } -} - -static void __widget_app_run(void *data) -{ - elm_run(); -} - -static void __widget_app_exit(void *data) -{ - elm_exit(); -} - -EXPORT_API int widget_app_main(int argc, char **argv, - widget_app_lifecycle_callback_s *callback, void *user_data) -{ - bundle *kb; - char *viewer_endpoint = NULL; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (argc <= 0 || argv == NULL || callback == NULL) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - - if (__context.dirty) { - _E("Already started"); - return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL); - } - - if (callback->create == NULL) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, - "widget_app_create_cb() callback must be " - "registered"); - - appcore_multiwindow_base_ops ops = appcore_multiwindow_base_get_default_ops(); - - /* override methods */ - ops.base.create = __widget_app_create; - ops.base.control = __widget_app_control; - ops.base.terminate = __widget_app_terminate; - ops.base.receive = __widget_app_receive; - ops.base.init = __widget_app_init; - ops.base.finish = __widget_app_finish; - ops.base.run = __widget_app_run; - ops.base.exit = __widget_app_exit; - - __context.callback = *callback; - __context.data = user_data; - kb = bundle_import_from_argv(argc, argv); - if (kb) { - bundle_get_str(kb, WIDGET_K_ENDPOINT, &viewer_endpoint); - if (viewer_endpoint) { - _D("viewer endpoint :%s", viewer_endpoint); - _viewer_endpoint = strdup(viewer_endpoint); - } else { - _E("endpoint is missing"); - } - - bundle_free(kb); - } else { - _E("failed to get launch argv"); /* LCOV_EXCL_LINE */ - return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL); - } - - __context.dirty = true; - appcore_multiwindow_base_init(ops, argc, argv, NULL); - appcore_multiwindow_base_fini(); - __context.dirty = false; - - return WIDGET_ERROR_NONE; -} - -EXPORT_API int widget_app_exit(void) -{ - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - appcore_multiwindow_base_exit(); - aul_widget_notify_exit(); - - return WIDGET_ERROR_NONE; -} - -static gboolean __finish_event_cb(gpointer user_data) -{ - appcore_multiwindow_base_instance_h cxt = user_data; - bundle *b; - const char *id; - const char *class_id; - - if (!cxt) { - _E("user_data is NULL"); - return FALSE; - } - - id = appcore_multiwindow_base_instance_get_id(cxt); - class_id = appcore_multiwindow_base_instance_get_class_id(cxt); - b = bundle_create(); - - if (!b) { - _E("Out-of-memory"); - return FALSE; - } - - bundle_add_str(b, WIDGET_K_OPERATION, "terminate"); - __instance_destroy(class_id, id, b); - bundle_free(b); - - return FALSE; -} - -EXPORT_API int widget_app_terminate_context(widget_context_h context) -{ - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (context == NULL) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - - g_idle_add(__finish_event_cb, context); - return WIDGET_ERROR_NONE; -} - -static void __inst_full_cb(const char *class_id, const char *id, - appcore_multiwindow_base_instance_h cxt, void *data) -{ - struct widget_foreach_context *foreach_context = data; - - if (!data) - return; - - if (foreach_context->callback) - foreach_context->callback(cxt, foreach_context->data); -} - -EXPORT_API int widget_app_foreach_context(widget_context_cb cb, void *data) -{ - struct widget_foreach_context foreach_context; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (!cb) { - _E("callback is NULL"); - return WIDGET_ERROR_INVALID_PARAMETER; - } - - foreach_context.callback = cb; - foreach_context.data = data; - appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context); - - return WIDGET_ERROR_NONE; -} - -int __event_cb(void *event, void *data) -{ - app_event_handler_h handler = data; - - struct app_event_info app_event; - - app_event.type = handler->type; - app_event.value = event; - - if (handler->cb) - handler->cb(&app_event, handler->data); - - return 0; -} - -EXPORT_API int widget_app_add_event_handler(app_event_handler_h *event_handler, - app_event_type_e event_type, app_event_cb callback, - void *user_data) -{ - int r; - bool feature; - app_event_handler_h handler; - - r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature); - if (r < 0) - return WIDGET_ERROR_FAULT; - - if (!feature) - return WIDGET_ERROR_NOT_SUPPORTED; - - if (event_handler == NULL || callback == NULL) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (event_type < APP_EVENT_LOW_MEMORY - || event_type > APP_EVENT_REGION_FORMAT_CHANGED) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED) - return widget_app_error(WIDGET_ERROR_NOT_SUPPORTED, __FUNCTION__, NULL); - - - handler = calloc(1, sizeof(struct app_event_handler)); - if (!handler) - return widget_app_error(WIDGET_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create handler"); - - handler->type = event_type; - handler->cb = callback; - handler->data = user_data; - handler->raw = appcore_base_add_event(__app_event_converter[event_type], __event_cb, handler); - *event_handler = handler; - - return WIDGET_ERROR_NONE; -} - -EXPORT_API int widget_app_remove_event_handler(app_event_handler_h - event_handler) -{ - int r; - bool feature; - - r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature); - if (r < 0) - return WIDGET_ERROR_FAULT; - - if (!feature) - return WIDGET_ERROR_NOT_SUPPORTED; - - app_event_type_e type; - - if (event_handler == NULL) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - type = event_handler->type; - if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_REGION_FORMAT_CHANGED) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - r = appcore_base_remove_event(event_handler->raw); - if (r < 0) - return widget_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid raw handler"); - - free(event_handler); - - return WIDGET_ERROR_NONE; -} - -EXPORT_API const char *widget_app_get_id(widget_context_h context) -{ - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); /* LCOV_EXCL_LINE */ - return NULL; /* LCOV_EXCL_LINE */ - } - - if (!context) { - set_last_result(WIDGET_ERROR_INVALID_PARAMETER); - return NULL; - } - - set_last_result(WIDGET_ERROR_NONE); - return appcore_multiwindow_base_instance_get_id(context); -} - -static void __win_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) -{ - char *plug_id; - plug_id = evas_object_data_del(obj, "___PLUGID"); - free(plug_id); -} - -EXPORT_API int widget_app_get_elm_win(widget_context_h context, - Evas_Object **win) -{ - Evas_Object *ret_win; - Ecore_Wl_Window *wl_win; - struct wl_surface *surface; - struct widget_extra *we; - char buffer[256]; - int rots[3] = {0}; - int win_id; - const char *id; - appcore_multiwindow_base_instance_h cxt; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (context == NULL || win == NULL) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - - cxt = (appcore_multiwindow_base_instance_h)context; - id = appcore_multiwindow_base_instance_get_id(cxt); - ret_win = elm_win_add(NULL, id, ELM_WIN_BASIC); - if (ret_win == NULL) { - _E("failed to create window"); /* LCOV_EXCL_LINE */ - goto fault; /* LCOV_EXCL_LINE */ - } - - elm_win_wm_rotation_preferred_rotation_set(ret_win, -1); - elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1); - - wl_win = elm_win_wl_window_get(ret_win); - if (wl_win == NULL) { - _E("failed to get wayland window"); /* LCOV_EXCL_LINE */ - goto fault; - } - - surface = ecore_wl_window_surface_get(wl_win); - if (surface == NULL) { - _E("failed to get surface"); /* LCOV_EXCL_LINE */ - goto fault; /* LCOV_EXCL_LINE */ - } - screen_connector_provider_remote_enable(id, surface); - - ecore_wl_window_class_name_set(wl_win, id); - elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1"); - - *win = ret_win; - we = appcore_multiwindow_base_instance_get_extra(cxt); - we->win = ret_win; - win_id = ecore_wl_window_id_get(wl_win); - - /* Set data to use in accessibility */ - snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid()); - evas_object_data_set(ret_win, "___PLUGID", strdup(buffer)); - evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL); - appcore_multiwindow_base_window_bind(cxt, wl_win); - - _D("window created: %d", win_id); - - return WIDGET_ERROR_NONE; - -fault: - if (ret_win) /* LCOV_EXCL_LINE */ - evas_object_del(ret_win); /* LCOV_EXCL_LINE */ - - return WIDGET_ERROR_FAULT; /* LCOV_EXCL_LINE */ -} - -static void __instance_drop(appcore_multiwindow_base_instance_h cxt) -{ - struct widget_extra *we; - - we = appcore_multiwindow_base_instance_get_extra(cxt); - appcore_multiwindow_base_instance_drop(cxt); - free(we->instance_id); - free(we->content); - free(we); - __check_empty_instance(); -} - -static void __stub_create(appcore_multiwindow_base_instance_h context, void *data) -{ - struct widget_class_context *cxt = data; - struct widget_extra *we; - bundle *b; - bundle *content_info = NULL; - char *id = NULL; - char *class_id = NULL; - char *operation = NULL; - char *content = NULL; - char *w_str = NULL; - char *h_str = NULL; - char *remain = NULL; - int w = 0; - int h = 0; - int ret = -1; - - appcore_multiwindow_base_class_on_create(context); - we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context); - b = we->args; - - bundle_get_str(b, WIDGET_K_CLASS, &class_id); - /* for previous version compatibility, use appid for default class id */ - if (class_id == NULL) - class_id = __appid; - - bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id); - bundle_get_str(b, WIDGET_K_OPERATION, &operation); - - if (!operation) { - _E("no operation provided"); - return; - } - - bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content); - bundle_get_str(b, WIDGET_K_WIDTH, &w_str); - bundle_get_str(b, WIDGET_K_HEIGHT, &h_str); - - if (w_str) - w = (int)g_ascii_strtoll(w_str, &remain, 10); - - if (h_str) - h = (int)g_ascii_strtoll(h_str, &remain, 10); - - if (content) - content_info = bundle_decode((const bundle_raw *)content, strlen(content)); - - if (cxt->callback.create) - ret = cxt->callback.create(context, content_info, w, h, cxt->data); - _D("%s is created", id); - - if (ret < 0) { - _W("Create callback returns error(%d)", ret); - ret = __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_CREATE_ABORTED, NULL); - __instance_drop(context); - } else { - ret = __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_CREATE, NULL); - - aul_widget_instance_add(class_id, id); - } - - if (content_info) - bundle_free(content_info); -} - -static void __stub_terminate(appcore_multiwindow_base_instance_h context, void *data) -{ - struct widget_class_context *class_cxt = data; - struct widget_extra *we; - bundle *b; - char *operation = NULL; - bundle *content_info; - widget_app_destroy_type_e reason = WIDGET_APP_DESTROY_TYPE_TEMPORARY; - int event = WIDGET_INSTANCE_EVENT_TERMINATE; - const char *id; - const char *class_id; - - id = appcore_multiwindow_base_instance_get_id(context); - class_id = appcore_multiwindow_base_instance_get_class_id(context); - we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context); - b = we->args; - - if (b) { - bundle_get_str(b, WIDGET_K_OPERATION, &operation); - if (operation && strcmp(operation, "destroy") == 0) - reason = WIDGET_APP_DESTROY_TYPE_PERMANENT; - } - - if (we->content) - content_info = bundle_decode((const bundle_raw *)we->content, strlen(we->content)); - else - content_info = bundle_create(); - - if (class_cxt->callback.destroy) - class_cxt->callback.destroy(context, reason, content_info, class_cxt->data); - _D("%s is destroyed %d", id, reason); - - if (reason == WIDGET_APP_DESTROY_TYPE_PERMANENT) { - event = WIDGET_INSTANCE_EVENT_DESTROY; - aul_widget_instance_del(class_id, id); - } else { - __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info); - } - - if (content_info) - bundle_free(content_info); - - __send_update_status(class_id, id, event, NULL); - appcore_multiwindow_base_class_on_terminate(context); -} - -static void __stub_pause(appcore_multiwindow_base_instance_h context, void *data) -{ - struct widget_class_context *class_cxt = data; - const char *id; - const char *class_id; - - appcore_multiwindow_base_class_on_pause(context); - id = appcore_multiwindow_base_instance_get_id(context); - class_id = appcore_multiwindow_base_instance_get_class_id(context); - - if (!class_cxt) { - _E("class context is NULL"); - return; - } - - if (class_cxt->callback.pause) - class_cxt->callback.pause(context, class_cxt->data); - _D("%s is paused", id); - __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_PAUSE, NULL); -} - -static void __stub_resume(appcore_multiwindow_base_instance_h context, void *data) -{ - struct widget_class_context *class_cxt = data; - const char *id; - const char *class_id; - - appcore_multiwindow_base_class_on_resume(context); - id = appcore_multiwindow_base_instance_get_id(context); - class_id = appcore_multiwindow_base_instance_get_class_id(context); - - if (!class_cxt) { - _E("class context is NULL"); - return; - } - - if (class_cxt->callback.resume) - class_cxt->callback.resume(context, class_cxt->data); - _D("%s is resumed", id); - __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_RESUME, NULL); -} - -EXPORT_API widget_class_h widget_app_class_add(widget_class_h widget_class, - const char *class_id, - widget_instance_lifecycle_callback_s callback, void *user_data) -{ - appcore_multiwindow_base_class cls; - struct widget_class_context *cxt; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); - return NULL; - } - - if (!class_id) { - _E("class is is NULL"); - set_last_result(WIDGET_ERROR_INVALID_PARAMETER); - return NULL; - } - - cxt = calloc(1, sizeof(struct widget_class_context)); - - if (!cxt) { - _E("failed to calloc : %s", __FUNCTION__); - set_last_result(WIDGET_ERROR_OUT_OF_MEMORY); - return NULL; - } - - cxt->callback = callback; - cxt->data = user_data; - - cls.id = strdup(class_id); - cls.data = cxt; - cls.create = __stub_create; - cls.terminate = __stub_terminate; - cls.pause = __stub_pause; - cls.resume = __stub_resume; - - appcore_multiwindow_base_class_add(cls); - set_last_result(WIDGET_ERROR_NONE); - - return (widget_class_h)cxt; -} - -EXPORT_API widget_class_h widget_app_class_create( - widget_instance_lifecycle_callback_s callback, void *user_data) -{ - return widget_app_class_add(NULL, __appid, callback, user_data); -} - -EXPORT_API int widget_app_context_set_tag(widget_context_h context, void *tag) -{ - struct widget_extra *we; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (!context) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - - we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context); - we->extra = tag; - - return WIDGET_ERROR_NONE; -} - -EXPORT_API int widget_app_context_get_tag(widget_context_h context, void **tag) -{ - struct widget_extra *we; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (!context || !tag) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - - we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context); - if (we == NULL) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - *tag = we->extra; - - return WIDGET_ERROR_NONE; -} - -EXPORT_API int widget_app_context_set_content_info(widget_context_h context, - bundle *content_info) -{ - int ret = 0; - bundle_raw *raw = NULL; - int len; - const char *id; - const char *class_id; - struct widget_extra *we; - appcore_multiwindow_base_instance_h cxt; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (!context || !content_info) - return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - - cxt = (appcore_multiwindow_base_instance_h)context; - id = appcore_multiwindow_base_instance_get_id(cxt); - class_id = appcore_multiwindow_base_instance_get_class_id(cxt); - we = appcore_multiwindow_base_instance_get_extra(cxt); - - if (!class_id || !id || !we) - return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL); - - ret = __send_update_status(class_id, id, - WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info); - - if (we->content) - free(we->content); - - bundle_encode(content_info, &raw, &len); - if (raw) - we->content = strdup((const char *)raw); - else - we->content = NULL; - - free(raw); - if (ret < 0) { - /* LCOV_EXCL_START */ - _E("failed to send content info: %s of %s (%d)", id, - class_id, ret); - return widget_app_error(WIDGET_ERROR_IO_ERROR, __FUNCTION__, - NULL); - /* LCOV_EXCL_STOP */ - } - - return WIDGET_ERROR_NONE; -} - -EXPORT_API int widget_app_context_set_title(widget_context_h context, - const char *title) -{ - appcore_multiwindow_base_instance_h cxt; - struct widget_extra *we; - - if (!__is_widget_feature_enabled()) { - _E("not supported"); /* LCOV_EXCL_LINE */ - return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */ - } - - if (!context || !title) { - _E("Invalid parameter %p %p", context, title); - return WIDGET_ERROR_INVALID_PARAMETER; - } - - cxt = (appcore_multiwindow_base_instance_h)context; - we = appcore_multiwindow_base_instance_get_extra(cxt); - - if (we->win) - elm_win_title_set(we->win, title); - - return WIDGET_ERROR_NONE; -} -- 2.7.4 From 77971833be97a92e33b931311dc0bfc1152e5767 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Tue, 12 Sep 2017 09:50:02 +0900 Subject: [PATCH 10/16] Release version 1.2.0 Changes: - Create widget base API set Change-Id: Ieab9ae316d562894df32fe53fc3d7d9aaa680326 Signed-off-by: Junghoon Park --- packaging/appcore-widget.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/appcore-widget.spec b/packaging/appcore-widget.spec index 9cc0e6f..bf74f68 100644 --- a/packaging/appcore-widget.spec +++ b/packaging/appcore-widget.spec @@ -1,6 +1,6 @@ Name: appcore-widget Summary: Widget Application -Version: 1.1.5 +Version: 1.2.0 Release: 1 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From fdf263c9b2470291ad6ee3c599a21ad1cd6c7231 Mon Sep 17 00:00:00 2001 From: Hyunho Kang Date: Wed, 20 Sep 2017 20:22:16 +0900 Subject: [PATCH 11/16] Fix base fini sequence Change-Id: I8cee3f3c86d9ffaeb54ecdc8d41078d27302bf4e Signed-off-by: Hyunho Kang --- src/base/widget_base.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/base/widget_base.c b/src/base/widget_base.c index 7cbba6c..9df3504 100644 --- a/src/base/widget_base.c +++ b/src/base/widget_base.c @@ -1110,10 +1110,9 @@ static void __free_class(gpointer data) EXPORT_API void widget_base_fini(void) { + appcore_multiwindow_base_fini(); g_list_free_full(__context.classes, __free_class); __context.classes = NULL; - - appcore_multiwindow_base_fini(); } EXPORT_API int widget_base_context_window_bind( -- 2.7.4 From b4dcaba71d2eb7f78055b01b7cc2acef438c5915 Mon Sep 17 00:00:00 2001 From: Hyunho Kang Date: Wed, 20 Sep 2017 20:25:34 +0900 Subject: [PATCH 12/16] Add get class exception handling logic Change-Id: Ia7098fae5c74d763b59a5853bd4801329a5d4a68 Signed-off-by: Hyunho Kang --- src/base/widget_base.c | 71 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/src/base/widget_base.c b/src/base/widget_base.c index 9df3504..6f19ce9 100644 --- a/src/base/widget_base.c +++ b/src/base/widget_base.c @@ -162,16 +162,20 @@ static gint __comp_class(gconstpointer a, gconstpointer b) return strcmp(cls->id, b); } -static widget_base_class __get_class(const char *class_id) +static widget_base_class *__get_class(const char *class_id) { widget_base_class *cls; GList *class_node; class_node = g_list_find_custom(__context.classes, class_id, __comp_class); + if (class_node == NULL) { + LOGE("empty classes"); + return NULL; + } cls = (widget_base_class *)class_node->data; - return *cls; + return cls; } static int __send_lifecycle_event(const char *class_id, const char *instance_id, @@ -313,7 +317,7 @@ static void __control_resize(const char *class_id, const char *id, bundle *b) int w = 0; int h = 0; void *class_data; - widget_base_class cls; + widget_base_class *cls; const appcore_multiwindow_base_class *raw_cls; instance_h = appcore_multiwindow_base_instance_find(id); @@ -327,6 +331,10 @@ static void __control_resize(const char *class_id, const char *id, bundle *b) return; cls = __get_class(class_id); + if (cls == NULL) { + LOGE("class not found: %s", class_id); + return; + } class_data = raw_cls->data; bundle_get_str(b, WIDGET_K_WIDTH, &w_str); bundle_get_str(b, WIDGET_K_HEIGHT, &h_str); @@ -337,8 +345,8 @@ static void __control_resize(const char *class_id, const char *id, bundle *b) if (h_str) h = (int)g_ascii_strtoll(h_str, &remain, 10); - if (cls.ops.resize) - cls.ops.resize(instance_h, w, h, class_data); + if (cls->ops.resize) + cls->ops.resize(instance_h, w, h, class_data); LOGD("%s is resized to %dx%d", id, w, h); __send_update_status(class_id, id, @@ -355,7 +363,7 @@ static void __update_cb(const char *class_id, const char *id, char *force_str = NULL; int force; bundle *b = data; - widget_base_class cls; + widget_base_class *cls; if (!b) { LOGE("bundle is NULL"); @@ -370,8 +378,12 @@ static void __update_cb(const char *class_id, const char *id, class_data = raw_cls->data; cls = __get_class(class_id); + if (cls == NULL) { + LOGE("class not found: %s", class_id); + return; + } - if (!cls.ops.update) { + if (!cls->ops.update) { LOGE("update callback is NULL"); return; } @@ -390,8 +402,8 @@ static void __update_cb(const char *class_id, const char *id, strlen(content_raw)); } - if (cls.ops.update) - cls.ops.update(instance_h, content, force, class_data); + if (cls->ops.update) + cls->ops.update(instance_h, content, force, class_data); __send_update_status(class_id, id, WIDGET_INSTANCE_EVENT_UPDATE, NULL); @@ -1186,7 +1198,7 @@ static void __multiwindow_instance_create( int w = 0; int h = 0; int ret = -1; - widget_base_class cls; + widget_base_class *cls; appcore_multiwindow_base_class_on_create(instance_h); instance_data = appcore_multiwindow_base_instance_get_extra(instance_h); @@ -1198,6 +1210,11 @@ static void __multiwindow_instance_create( class_id = __appid; cls = __get_class(class_id); + if (cls == NULL) { + LOGE("class not found: %s", class_id); + return; + } + bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id); bundle_get_str(b, WIDGET_K_OPERATION, &operation); @@ -1220,8 +1237,8 @@ static void __multiwindow_instance_create( content_info = bundle_decode((const bundle_raw *)content, strlen(content)); - if (cls.ops.create) - ret = cls.ops.create(instance_h, content_info, w, h, class_data); + if (cls->ops.create) + ret = cls->ops.create(instance_h, content_info, w, h, class_data); if (ret < 0) { LOGW("Create callback returns error(%d)", ret); @@ -1246,15 +1263,19 @@ static void __multiwindow_instance_resume( { const char *id; const char *class_id; - widget_base_class cls; + widget_base_class *cls; appcore_multiwindow_base_class_on_resume(instance_h); id = appcore_multiwindow_base_instance_get_id(instance_h); class_id = appcore_multiwindow_base_instance_get_class_id(instance_h); cls = __get_class(class_id); + if (cls == NULL) { + LOGE("class not found: %s", class_id); + return; + } - if (cls.ops.resume) - cls.ops.resume(instance_h, class_data); + if (cls->ops.resume) + cls->ops.resume(instance_h, class_data); LOGD("%s is resumed", id); __send_update_status(class_id, id, @@ -1277,15 +1298,19 @@ static void __multiwindow_instance_pause( { const char *id; const char *class_id; - widget_base_class cls; + widget_base_class *cls; appcore_multiwindow_base_class_on_pause(instance_h); id = appcore_multiwindow_base_instance_get_id(instance_h); class_id = appcore_multiwindow_base_instance_get_class_id(instance_h); cls = __get_class(class_id); + if (cls == NULL) { + LOGE("class not found: %s", class_id); + return; + } - if (cls.ops.pause) - cls.ops.pause(instance_h, class_data); + if (cls->ops.pause) + cls->ops.pause(instance_h, class_data); LOGD("%s is paused", id); __send_update_status(class_id, id, @@ -1314,7 +1339,7 @@ static void __multiwindow_instance_terminate( int event = WIDGET_INSTANCE_EVENT_TERMINATE; const char *id; const char *class_id; - widget_base_class cls; + widget_base_class *cls; id = appcore_multiwindow_base_instance_get_id(instance_h); class_id = appcore_multiwindow_base_instance_get_class_id(instance_h); @@ -1322,6 +1347,10 @@ static void __multiwindow_instance_terminate( (appcore_multiwindow_base_instance_h)instance_h); b = data->args; cls = __get_class(class_id); + if (cls == NULL) { + LOGE("class not found: %s", class_id); + return; + } if (b) { bundle_get_str(b, WIDGET_K_OPERATION, &operation); @@ -1335,8 +1364,8 @@ static void __multiwindow_instance_terminate( else content_info = bundle_create(); - if (cls.ops.destroy) - cls.ops.destroy(instance_h, reason, content_info, class_data); + if (cls->ops.destroy) + cls->ops.destroy(instance_h, reason, content_info, class_data); LOGD("%s is destroyed %d", id, reason); if (reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) { -- 2.7.4 From d991f02b6d603d98d9bed4478b31d21efc562877 Mon Sep 17 00:00:00 2001 From: Hyunho Kang Date: Wed, 28 Jun 2017 20:41:33 +0900 Subject: [PATCH 13/16] Use common normal exit notify API - aul_notify_exit https://review.tizen.org/gerrit/#/c/136199/ (amd) https://review.tizen.org/gerrit/#/c/136200/ (aul-1) https://review.tizen.org/gerrit/#/c/136201/ (appcore-widget) https://review.tizen.org/gerrit/#/c/136209/ (widget-service) Change-Id: I92863ca2c88e8ac552012a5b5c4ae4f190833029 Signed-off-by: Hyunho Kang --- src/base/widget_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/widget_base.c b/src/base/widget_base.c index 6f19ce9..8e74db9 100644 --- a/src/base/widget_base.c +++ b/src/base/widget_base.c @@ -644,7 +644,7 @@ static void __multiwindow_exit(void *data) EXPORT_API int widget_base_exit(void) { appcore_multiwindow_base_exit(); - aul_widget_notify_exit(); + aul_notify_exit(); return 0; } -- 2.7.4 From c2233b1e963b14080d8725edbde500649eb7ad52 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Wed, 19 Jul 2017 15:09:56 +0900 Subject: [PATCH 14/16] Implement periodic update - update-callabck should be invoked periodically when the value of 'update-period' is bigger then 0 - Paused widget's update-callback should be deferred until it is resumed - Require https://review.tizen.org/gerrit/#/c/139466/ Change-Id: Id30e4de0576f3cb8b35743fff0ac37989356df6d Signed-off-by: Junghoon Park Signed-off-by: Hyunho Kang --- src/base/widget_base.c | 117 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 96 insertions(+), 21 deletions(-) diff --git a/src/base/widget_base.c b/src/base/widget_base.c index 8e74db9..d479c52 100644 --- a/src/base/widget_base.c +++ b/src/base/widget_base.c @@ -84,8 +84,12 @@ typedef struct _widget_base_context { typedef struct _widget_base_instance_data { bundle *args; + char *id; char *content; void *tag; + double period; + guint periodic_timer; + bool pending_update; void *user_data; } widget_base_instance_data; @@ -94,6 +98,32 @@ static char *__appid; static char *__package_id; static bool __fg_signal; static char *__viewer_endpoint; +static void __call_update_cb(const char *class_id, const char *id, int force, + const char *content_raw); + +static gboolean __timeout_cb(gpointer user_data) +{ + widget_base_instance_data *data = + (widget_base_instance_data *)user_data; + appcore_multiwindow_base_instance_h cxt; + const char *class_id; + + cxt = appcore_multiwindow_base_instance_find(data->id); + if (appcore_multiwindow_base_instance_is_resumed(cxt)) { + LOGD("Periodic update!"); + class_id = appcore_multiwindow_base_instance_get_class_id(cxt); + __call_update_cb(class_id, data->id, 0, NULL); + } else { + data->pending_update = true; + if (data->periodic_timer) { + LOGD("Remove timer!"); + g_source_remove(data->periodic_timer); + data->periodic_timer = 0; + } + } + + return G_SOURCE_CONTINUE; +} static bool __is_widget_feature_enabled(void) { @@ -151,6 +181,7 @@ static void __instance_drop(appcore_multiwindow_base_instance_h instance_h) data = appcore_multiwindow_base_instance_get_extra(instance_h); appcore_multiwindow_base_instance_drop(instance_h); free(data->content); + free(data->id); free(data); __check_empty_instance(); } @@ -260,6 +291,9 @@ static void __control_create(const char *class_id, const char *id, bundle *b) { widget_base_instance_data *data; char *content = NULL; + double *period = NULL; + size_t size; + int ret; data = (widget_base_instance_data *) calloc(1, sizeof(widget_base_instance_data)); @@ -268,7 +302,14 @@ static void __control_create(const char *class_id, const char *id, bundle *b) return; } + data->id = strdup(id); data->args = b; + ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period, &size); + if (ret == BUNDLE_ERROR_NONE) { + data->period = *period; + data->periodic_timer = g_timeout_add_seconds(data->period, + __timeout_cb, data); + } /* call stub create */ appcore_multiwindow_base_instance_run(class_id, id, data); @@ -353,20 +394,18 @@ static void __control_resize(const char *class_id, const char *id, bundle *b) WIDGET_INSTANCE_EVENT_SIZE_CHANGED, NULL); } -static void __update_cb(const char *class_id, const char *id, - appcore_multiwindow_base_instance_h instance_h, void *data) +static void __call_update_cb(const char *class_id, const char *id, int force, + const char *content_raw) { void *class_data; + widget_base_class *cls; const appcore_multiwindow_base_class *raw_cls; + appcore_multiwindow_base_instance_h instance_h; bundle *content = NULL; - char *content_raw = NULL; - char *force_str = NULL; - int force; - bundle *b = data; - widget_base_class *cls; - if (!b) { - LOGE("bundle is NULL"); + instance_h = appcore_multiwindow_base_instance_find(id); + if (!instance_h) { + LOGE("context not found: %s", id); return; } @@ -388,15 +427,6 @@ static void __update_cb(const char *class_id, const char *id, return; } - bundle_get_str(b, WIDGET_K_FORCE, &force_str); - - if (force_str && strcmp(force_str, "true") == 0) - force = 1; - else - force = 0; - - bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw); - if (content_raw) { content = bundle_decode((const bundle_raw *)content_raw, strlen(content_raw)); @@ -413,13 +443,37 @@ static void __update_cb(const char *class_id, const char *id, bundle_free(content); } +static void __update_process(const char *class_id, const char *id, + appcore_multiwindow_base_instance_h instance_h, void *data) +{ + char *content_raw = NULL; + char *force_str = NULL; + int force; + bundle *b = data; + + if (!b) { + LOGE("bundle is NULL"); + return; + } + + bundle_get_str(b, WIDGET_K_FORCE, &force_str); + + if (force_str && strcmp(force_str, "true") == 0) + force = 1; + else + force = 0; + + bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw); + __call_update_cb(class_id, id, force, content_raw); +} + static void __control_update(const char *class_id, const char *id, bundle *b) { appcore_multiwindow_base_instance_h instance_h; if (!id) { appcore_multiwindow_base_instance_foreach(class_id, - __update_cb, b); + __update_process, b); return; } @@ -429,7 +483,7 @@ static void __control_update(const char *class_id, const char *id, bundle *b) return; } - __update_cb(class_id, id, instance_h, b); + __update_process(class_id, id, instance_h, b); } static void __control_destroy(const char *class_id, const char *id, bundle *b) @@ -451,6 +505,7 @@ static void __control_destroy(const char *class_id, const char *id, bundle *b) /* call stub terminate */ appcore_multiwindow_base_instance_exit(instance_h); free(data->content); + free(data->id); free(data); __check_empty_instance(); } @@ -1122,9 +1177,10 @@ static void __free_class(gpointer data) EXPORT_API void widget_base_fini(void) { - appcore_multiwindow_base_fini(); g_list_free_full(__context.classes, __free_class); __context.classes = NULL; + + appcore_multiwindow_base_fini(); } EXPORT_API int widget_base_context_window_bind( @@ -1264,6 +1320,7 @@ static void __multiwindow_instance_resume( const char *id; const char *class_id; widget_base_class *cls; + widget_base_instance_data *data; appcore_multiwindow_base_class_on_resume(instance_h); id = appcore_multiwindow_base_instance_get_id(instance_h); @@ -1274,6 +1331,21 @@ static void __multiwindow_instance_resume( return; } + data = (widget_base_instance_data *) + appcore_multiwindow_base_instance_get_extra(instance_h); + + if (data->pending_update) { + LOGD("pending update!"); + data->pending_update = false; + __control_update(class_id, data->id, data->args); + if (data->period > 0) { + LOGD("Restart timer!"); + data->periodic_timer = g_timeout_add_seconds( + data->period, + __timeout_cb, data); + } + } + if (cls->ops.resume) cls->ops.resume(instance_h, class_data); @@ -1380,6 +1452,9 @@ static void __multiwindow_instance_terminate( if (content_info) bundle_free(content_info); + if (data->periodic_timer) + g_source_remove(data->periodic_timer); + __send_update_status(class_id, id, event, NULL); appcore_multiwindow_base_class_on_terminate(instance_h); } -- 2.7.4 From cc471d913591dde16c9d4e88df5d31aa29b3d63f Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Thu, 20 Jul 2017 14:23:36 +0900 Subject: [PATCH 15/16] Implement widget operation for 'period' - This patch is associated with widget_service_change_period() - This operation is responsible for changing current update-period Change-Id: I32abe9b865941040d223d467984dac8e72e9d748 Signed-off-by: Junghoon Park Signed-off-by: Hyunho Kang --- src/base/widget_base.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/base/widget_base.c b/src/base/widget_base.c index d479c52..c10cd8d 100644 --- a/src/base/widget_base.c +++ b/src/base/widget_base.c @@ -510,6 +510,48 @@ static void __control_destroy(const char *class_id, const char *id, bundle *b) __check_empty_instance(); } +static void __control_change_period(const char *class_id, const char *id, + bundle *b) +{ + appcore_multiwindow_base_instance_h instance_h; + widget_base_instance_data *data; + double *period = NULL; + size_t size; + int ret; + + instance_h = appcore_multiwindow_base_instance_find(id); + if (!instance_h) { + LOGE("context not found: %s", id); + return; + } + + data = (widget_base_instance_data *) + appcore_multiwindow_base_instance_get_extra(instance_h); + + if (!data) { + LOGE("could not find instance data: %s", id); + return; + } + + if (data->periodic_timer) { + LOGD("Remove timer!"); + g_source_remove(data->periodic_timer); + data->periodic_timer = 0; + } + + ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period, &size); + if (ret == BUNDLE_ERROR_NONE) + data->period = *period; + + if (data->period > 0) { + LOGD("Restart timer!"); + data->periodic_timer = g_timeout_add_seconds(data->period, + __timeout_cb, data); + } + + return; +} + static int __multiwindow_create(void *data) { char pkgid[256] = {0, }; @@ -601,6 +643,8 @@ static int __multiwindow_control(bundle *b, void *data) __control_pause(class_id, id, b); else if (strcmp(operation, "terminate") == 0) __control_destroy(class_id, id, b); + else if (strcmp(operation, "period") == 0) + __control_change_period(class_id, id, b); return 0; } -- 2.7.4 From b92069e837cbd5ebc51c7b8f4c50fdf94fcedde3 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 4 Aug 2017 19:53:49 +0900 Subject: [PATCH 16/16] Add an exception handling about permanent deletion Change-Id: Iea0e8dc778532174c618f07273f793cbee74d35b Signed-off-by: Hwankyu Jhun Signed-off-by: Hyunho Kang --- src/base/widget_base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/base/widget_base.c b/src/base/widget_base.c index c10cd8d..0cf602c 100644 --- a/src/base/widget_base.c +++ b/src/base/widget_base.c @@ -98,6 +98,7 @@ static char *__appid; static char *__package_id; static bool __fg_signal; static char *__viewer_endpoint; +static bool __is_permanent; static void __call_update_cb(const char *class_id, const char *id, int force, const char *content_raw); @@ -743,7 +744,8 @@ static void __multiwindow_exit(void *data) EXPORT_API int widget_base_exit(void) { appcore_multiwindow_base_exit(); - aul_notify_exit(); + if (appcore_multiwindow_base_instance_get_cnt() != 0 && __is_permanent) + aul_notify_exit(); return 0; } @@ -1485,9 +1487,11 @@ static void __multiwindow_instance_terminate( LOGD("%s is destroyed %d", id, reason); if (reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) { + __is_permanent = true; event = WIDGET_INSTANCE_EVENT_DESTROY; aul_widget_instance_del(class_id, id); } else { + __is_permanent = false; __send_update_status(class_id, id, WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info); -- 2.7.4