From: jh9216.park Date: Thu, 11 Mar 2021 01:29:38 +0000 (-0500) Subject: Refactor appcore-widget X-Git-Tag: submit/tizen/20220111.072059~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fappfw%2Fappcore-widget.git;a=commitdiff_plain;h=9f6ac8d189d1bf5b0253c3c052168a19fa811a4d Refactor appcore-widget - Use app-core for C++ Requires: - https://review.tizen.org/gerrit/#/c/platform/core/appfw/app-core/+/247812/ - https://review.tizen.org/gerrit/#/c/platform/core/api/app-common/+/253882/ Change-Id: Ib0b43977c3334cb3942f26bf93c42de933448c24 Signed-off-by: jh9216.park --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dc63e6..a35ef8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,12 +8,15 @@ SET(LIBDIR ${LIB_INSTALL_DIR}) SET(INCLUDEDIR "\${prefix}/include") ## Compiler flags -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -g -Wall -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") ## Linker flags SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed,--gc-sections -pie") -SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") ## Targets SET(TARGET_WIDGET_BASE "appcore-widget-base") @@ -28,26 +31,21 @@ INCLUDE(ApplyPkgConfig) ADD_DEFINITIONS("-DPROJECT_TAG=\"TIZEN_APPCORE_WIDGET\"") ## Find all needed packages once +PKG_CHECK_MODULES(APPCORE_COMMON_DEPS REQUIRED app-core-cpp) +PKG_CHECK_MODULES(APPCORE_MULTIWINDOW_DEPS REQUIRED app-core-multi-window-cpp) +PKG_CHECK_MODULES(APPCORE_MULTIWINDOW_OLD_DEPS REQUIRED appcore-multiwindow) +PKG_CHECK_MODULES(AUL_DEP REQUIRED aul) PKG_CHECK_MODULES(BUNDLE_DEPS REQUIRED bundle) +PKG_CHECK_MODULES(CAPI_APP_COMMON_DEP REQUIRED capi-appfw-app-common) PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog) -PKG_CHECK_MODULES(APPCORE_COMMON_DEPS REQUIRED appcore-common) -PKG_CHECK_MODULES(WIDGET_SERVICE_DEPS REQUIRED widget_service) -PKG_CHECK_MODULES(SYSTEM_INFO_DEPS REQUIRED capi-system-info) PKG_CHECK_MODULES(ECORE_WL2_DEPS REQUIRED ecore-wl2) -PKG_CHECK_MODULES(SCREEN_CONNECTOR_PROVIDER_DEPS REQUIRED screen_connector_provider) -PKG_CHECK_MODULES(APPCORE_MULTIWINDOW_DEPS REQUIRED appcore-multiwindow) -PKG_CHECK_MODULES(AUL_DEP REQUIRED aul) PKG_CHECK_MODULES(ELEMENTARY_DEP REQUIRED elementary) -PKG_CHECK_MODULES(CAPI_APP_COMMON_DEP REQUIRED capi-appfw-app-common) PKG_CHECK_MODULES(GLIB_DEPS REQUIRED glib-2.0) -PKG_CHECK_MODULES(GOBJECT_DEPS REQUIRED gobject-2.0) PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock) +PKG_CHECK_MODULES(GOBJECT_DEPS REQUIRED gobject-2.0) +PKG_CHECK_MODULES(SCREEN_CONNECTOR_PROVIDER_DEPS REQUIRED screen_connector_provider) +PKG_CHECK_MODULES(SYSTEM_INFO_DEPS REQUIRED capi-system-info) +PKG_CHECK_MODULES(WIDGET_SERVICE_DEPS REQUIRED widget_service) ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(test) - - - - - - diff --git a/include/widget_app.h b/include/widget_app.h old mode 100755 new mode 100644 diff --git a/include/widget_base.h b/include/widget_base.h index 80e1a57..769c566 100644 --- a/include/widget_base.h +++ b/include/widget_base.h @@ -29,6 +29,10 @@ extern "C" { #endif +/* Deprecated APIs. Please use widget_base.hh */ + +#define WIDGE_BASE_DEPRECATED __attribute__ ((deprecated)) + typedef enum widget_base_destroy_type { WIDGET_BASE_DESTROY_TYPE_PERMANENT = 0x00, WIDGET_BASE_DESTROY_TYPE_TEMPORARY = 0x01, @@ -85,50 +89,50 @@ typedef struct _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_foreach_context(widget_base_instance_cb cb, void *data) WIDGE_BASE_DEPRECATED; +int widget_base_terminate_context(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED; 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); + void *user_data) WIDGE_BASE_DEPRECATED; int widget_base_remove_event_handler(app_event_handler_h - event_handler); + event_handler) WIDGE_BASE_DEPRECATED; 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); + bundle *content_info) WIDGE_BASE_DEPRECATED; +int widget_base_context_get_tag(widget_base_instance_h instance_h, void **tag) WIDGE_BASE_DEPRECATED; +int widget_base_context_set_tag(widget_base_instance_h instance_h, void *tag) WIDGE_BASE_DEPRECATED; +void *widget_base_context_get_user_data(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED; 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); -int widget_base_on_trim_memory(void); -widget_base_ops widget_base_get_default_ops(void); -void widget_base_fini(void); -int widget_base_exit(void); + void *user_data) WIDGE_BASE_DEPRECATED; +int widget_base_context_get_id(widget_base_instance_h instance_h, char **id) WIDGE_BASE_DEPRECATED; +const char *widget_base_get_viewer_endpoint(void) WIDGE_BASE_DEPRECATED; +int widget_base_init(widget_base_ops ops, int argc, char **argv, void *data) WIDGE_BASE_DEPRECATED; +int widget_base_on_create(void) WIDGE_BASE_DEPRECATED; +int widget_base_on_terminate(void) WIDGE_BASE_DEPRECATED; +int widget_base_on_init(int argc, char **argv) WIDGE_BASE_DEPRECATED; +void widget_base_on_finish(void) WIDGE_BASE_DEPRECATED; +void widget_base_on_run(void) WIDGE_BASE_DEPRECATED; +void widget_base_on_exit(void) WIDGE_BASE_DEPRECATED; +int widget_base_on_trim_memory(void) WIDGE_BASE_DEPRECATED; +widget_base_ops widget_base_get_default_ops(void) WIDGE_BASE_DEPRECATED; +void widget_base_fini(void) WIDGE_BASE_DEPRECATED; +int widget_base_exit(void) WIDGE_BASE_DEPRECATED; int widget_base_context_window_bind( widget_base_instance_h instance_h, const char *id, - Ecore_Wl2_Window *wl_win); + Ecore_Wl2_Window *wl_win) WIDGE_BASE_DEPRECATED; 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); + bundle *content, int w, int h) WIDGE_BASE_DEPRECATED; +int widget_base_class_on_pause(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED; +int widget_base_class_on_resume(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED; int widget_base_class_on_resize(widget_base_instance_h instance_h, - int w, int h); + int w, int h) WIDGE_BASE_DEPRECATED; int widget_base_class_on_update(widget_base_instance_h instance_h, - bundle *content, int force); + bundle *content, int force) WIDGE_BASE_DEPRECATED; 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_destroy_type_e reason, bundle *content) WIDGE_BASE_DEPRECATED; +widget_base_class widget_base_class_get_default(void) WIDGE_BASE_DEPRECATED; widget_base_class *widget_base_class_add(widget_base_class cls, - const char *class_id, void *class_data); + const char *class_id, void *class_data) WIDGE_BASE_DEPRECATED; #ifdef __cplusplus } diff --git a/include/widget_base.hh b/include/widget_base.hh new file mode 100644 index 0000000..8f0c043 --- /dev/null +++ b/include/widget_base.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef WIDGET_BASE_HH_ +#define WIDGET_BASE_HH_ + +#include + +#include +#include + +#include + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +namespace tizen_cpp { + +class EXPORT_API WidgetBase : public AppCoreMultiWindowBase { + public: + WidgetBase(); + virtual ~WidgetBase(); + + std::string GetViewerEndpoint(); + void Run(int argc, char** argv) override; + void Exit() override; + int OnControl(tizen_base::Bundle b) override; + int OnCreate() override; + int OnTerminate() override; + int OnReceive(aul_type type, tizen_base::Bundle b) override; + void ExitContext(std::shared_ptr context) override; + + protected: + void Dispose() override; + + private: + friend class WidgetContext; + class Impl; + std::unique_ptr impl_; +}; + +class EXPORT_API WidgetContext : public AppCoreMultiWindowBase::Context { + public: + enum class DestroyType { + PERMANENT, + TEMPORARY + }; + + WidgetContext(std::string context_id, std::string inst_id, + AppCoreMultiWindowBase* app); + virtual ~WidgetContext(); + virtual bool OnCreate(const tizen_base::Bundle& contents, int w, int h) = 0; + virtual void OnDestroy(DestroyType reason, + const tizen_base::Bundle& contents) = 0; + virtual void OnPause(); + virtual void OnResume(); + virtual void OnResize(int w, int h); + virtual void OnUpdate(const tizen_base::Bundle& contents, bool force); + void ExitAsync(); + int SetContents(const tizen_base::Bundle& contents); + int WindowBind(std::string id, Ecore_Wl2_Window* wl_win); + + private: + using AppCoreMultiWindowBase::Context::WindowBind; + void OnCreate() override; + void OnTerminate() override; + + private: + friend class WidgetBase; + class Impl; + std::unique_ptr impl_; +}; + +} // namespace tizen_cpp + +#endif // WIDGET_BASE_HH_ diff --git a/appcore-widget.manifest b/packaging/appcore-widget.manifest similarity index 100% rename from appcore-widget.manifest rename to packaging/appcore-widget.manifest diff --git a/packaging/appcore-widget.spec b/packaging/appcore-widget.spec index b84fa32..a750a1a 100644 --- a/packaging/appcore-widget.spec +++ b/packaging/appcore-widget.spec @@ -4,15 +4,17 @@ Version: 1.3.14 Release: 1 Group: Application Framework/Libraries License: Apache-2.0 -Source0: appcore-widget-%{version}.tar.gz +Source0: %{name}-%{version}.tar.gz +Source1001: %{name}.manifest BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(elementary) -BuildRequires: pkgconfig(appcore-common) +BuildRequires: pkgconfig(app-core-cpp) BuildRequires: pkgconfig(capi-appfw-app-common) BuildRequires: pkgconfig(widget_service) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(ecore-wl2) +BuildRequires: pkgconfig(app-core-multi-window-cpp) BuildRequires: pkgconfig(appcore-multiwindow) BuildRequires: pkgconfig(screen_connector_provider) BuildRequires: pkgconfig(gmock) @@ -71,6 +73,7 @@ gcov objects of a widget application library %prep %setup -q +cp %{SOURCE1001} . %build %if 0%{?gcov:1} @@ -99,9 +102,6 @@ mkdir -p %{buildroot}%{_datadir}/gcov/obj install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %endif -mkdir -p %{buildroot}%{_libdir}/pkgconfig -cp capi-appfw-widget-application.pc %{buildroot}%{_libdir}/pkgconfig - %check export LD_LIBRARY_PATH=../../src/base:../../src/efl_base ctest -V @@ -123,11 +123,11 @@ install -m 0644 appcore-widget.zip %{buildroot}%{_datadir}/gcov/ %license LICENSE %files -n appcore-widget-base-devel +/usr/include/appfw/widget_base.hh /usr/include/appfw/widget_base.h %{_libdir}/pkgconfig/appcore-widget-base.pc %{_libdir}/libappcore-widget-base.so - %files -n appcore-widget %manifest %{name}.manifest %defattr(-,root,root,-) diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 13314c5..eccf4f2 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -4,8 +4,12 @@ ADD_LIBRARY(${TARGET_WIDGET_BASE} SHARED ${WIDGET_BASE_SRCS}) SET_TARGET_PROPERTIES(${TARGET_WIDGET_BASE} PROPERTIES SOVERSION ${MAJORVER}) SET_TARGET_PROPERTIES(${TARGET_WIDGET_BASE} PROPERTIES VERSION ${FULLVER}) -TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_BASE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) -TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_BASE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../include/) +TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_BASE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/ + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../include/ + ${CMAKE_CURRENT_SOURCE_DIR}/../common/) APPLY_PKG_CONFIG(${TARGET_WIDGET_BASE} PUBLIC DLOG_DEPS @@ -15,9 +19,13 @@ APPLY_PKG_CONFIG(${TARGET_WIDGET_BASE} PUBLIC ECORE_WL2_DEPS SCREEN_CONNECTOR_PROVIDER_DEPS APPCORE_MULTIWINDOW_DEPS + APPCORE_MULTIWINDOW_OLD_DEPS CAPI_APP_COMMON_DEP ) -CONFIGURE_FILE(../../appcore-widget-base.pc.in ../../appcore-widget-base.pc @ONLY) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/appcore-widget-base.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/appcore-widget-base.pc @ONLY) INSTALL(TARGETS ${TARGET_WIDGET_BASE} DESTINATION ${LIB_INSTALL_DIR}) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../appcore-widget-base.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/appcore-widget-base.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/appfw/) diff --git a/appcore-widget-base.pc.in b/src/base/appcore-widget-base.pc.in similarity index 90% rename from appcore-widget-base.pc.in rename to src/base/appcore-widget-base.pc.in index f2d3717..53779bf 100644 --- a/appcore-widget-base.pc.in +++ b/src/base/appcore-widget-base.pc.in @@ -8,6 +8,6 @@ includedir=@INCLUDEDIR@ Name: appcore-widget-base Description: widget base library Version: @VERSION@ -Requires: aul dlog capi-appfw-app-common widget_service appcore-multiwindow +Requires: aul dlog capi-appfw-app-common widget_service appcore-multiwindow app-core-multi-window-cpp Libs: -L${libdir} -lappcore-widget-base Cflags: -I${includedir} -I${includedir}/appfw diff --git a/src/base/widget_base.cc b/src/base/widget_base.cc new file mode 100644 index 0000000..45ec082 --- /dev/null +++ b/src/base/widget_base.cc @@ -0,0 +1,781 @@ +/* + * Copyright (c) 2021 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 "common/log_private.hh" +#include "include/widget_base.hh" + +namespace tizen_cpp { +namespace { + +constexpr const char kStatusForeground[] = "fg"; +constexpr const char kStatusBackground[] = "bg"; + +class AppContext { + public: + void SetAppId(const std::string& app_id) { + app_id_ = app_id; + } + + const std::string& GetAppId() const { + return app_id_; + } + + void SetPackageId(const std::string& package_id) { + package_id_ = package_id; + } + + const std::string& GetPackageId() const { + return package_id_; + } + + void SetViewerEndpoint(const std::string& viewer_endpoint) { + viewer_endpoint_ = viewer_endpoint; + } + + const std::string& GetViewerEndpoint() const { + return viewer_endpoint_; + } + + void SetPermanent(bool permanent) { + permanent_ = permanent; + } + + bool IsPermanent() const { + return permanent_; + } + + void SetFgSignal(bool fg_signal) { + fg_signal_ = fg_signal; + } + + bool IsFgSignal() const { + return fg_signal_; + } + + int SendUpdateStatus(const std::string& class_id, + const std::string& instance_id, int status, int err, + bundle* extra) { + int ret = aul_widget_send_status_to_viewer(class_id.c_str(), + instance_id.c_str(), viewer_endpoint_.c_str(), status, err, extra); + if (ret != AUL_R_OK) + return ret; + + int lifecycle = widget_instance_convert_event_to_lifecycle_status(status); + if (lifecycle > -1) { + ret = aul_widget_send_status_to_service(class_id.c_str(), + instance_id.c_str(), package_id_.c_str(), lifecycle); + } + + return ret; + } + + private: + std::string app_id_; + std::string package_id_; + std::string viewer_endpoint_; + bool permanent_ = false; + bool fg_signal_ = false; +}; + +AppContext __context; + +} // namespace + +class WidgetBase::Impl { + public: + explicit Impl(WidgetBase* parent) : parent_(parent) {} + + private: + friend class WidgetBase; + WidgetBase* parent_; + + void ControlCreate(const std::string& class_id, const std::string& id, + const tizen_base::Bundle& b); + void ControlDestroy(const std::string& class_id, const std::string& id, + const tizen_base::Bundle& b); + void ControlResume(const std::string& class_id, const std::string& id, + const tizen_base::Bundle& b); + void ControlPause(const std::string& class_id, const std::string& id, + const tizen_base::Bundle& b); + void ControlChangePeriod(const std::string& class_id, const std::string& id, + const tizen_base::Bundle& b); + void ControlUpdate(const std::string& class_id, const std::string& id, + const tizen_base::Bundle& b); + void ControlResize(const std::string& class_id, const std::string& id, + const tizen_base::Bundle& b); + void GetContent(tizen_base::Bundle& b); +}; + +WidgetBase* __widget; + +class WidgetContext::Impl { + public: + explicit Impl(WidgetContext* parent) : parent_(parent) {} + + ~Impl() { + UnsetPeriodicTimer(); + } + + private: + void UpdateProcess(const tizen_base::Bundle& b); + void OnUpdate(bool force); + void SetPeriod(double period); + void SetPeriodicTimer(); + void UnsetPeriodicTimer(); + static gboolean TimedOutCb(gpointer user_data); + + private: + friend class WidgetContext; + friend class WidgetBase; + friend class WidgetBase::Impl; + + WidgetContext* parent_; + + std::unique_ptr args_; + std::string content_; + double period_; + guint periodic_timer_ = 0; + bool pending_update_; + std::string pending_content_; +}; + +void WidgetBase::Impl::ControlCreate(const std::string& class_id, + const std::string& id, const tizen_base::Bundle& b) { + if (parent_->FindById(id).get() != nullptr) { + _E("Already exists. ID(%s)", id.c_str()); + return; + } + + std::shared_ptr context; + try { + context = parent_->CreateContext(class_id, id); + } catch (std::runtime_error& e) { + _E("runtime_error exception occurs"); + return; + } + + WidgetContext* wc = dynamic_cast(context.get()); + if (wc == nullptr) + return; + + wc->impl_->args_.reset(new tizen_base::Bundle(b)); + auto ctx = parent_->RunContext(context); + if (ctx.get() == nullptr) + return; + + wc->impl_->args_.reset(); + wc->impl_->content_ = b.GetString(WIDGET_K_CONTENT_INFO); +} + +void WidgetBase::Impl::ControlDestroy(const std::string& class_id, + const std::string& id, const tizen_base::Bundle& b) { + auto context = parent_->FindById(id); + if (context.get() == nullptr) { + _E("Failed to find widget context. ID(%s)", id.c_str()); + aul_widget_instance_del(class_id.c_str(), id.c_str()); + return; + } + + WidgetContext* wc = dynamic_cast(context.get()); + if (wc == nullptr) + return; + + wc->impl_->args_.reset(new tizen_base::Bundle(b)); + parent_->ExitContext(context); +} + +void WidgetBase::Impl::ControlResume(const std::string& class_id, + const std::string& id, const tizen_base::Bundle& b) { + auto context = parent_->FindById(id); + if (context.get() == nullptr) { + _E("Failed to find widget context. ID(%s)", id.c_str()); + return; + } + + context->Resume(); +} + +void WidgetBase::Impl::ControlPause(const std::string& class_id, + const std::string& id, const tizen_base::Bundle& b) { + auto context = parent_->FindById(id); + if (context.get() == nullptr) { + _E("Failed to find widget context. ID(%s)", id.c_str()); + return; + } + + context->Pause(); +} + +void WidgetBase::Impl::ControlUpdate(const std::string& class_id, + const std::string& id, const tizen_base::Bundle& b) { + if (id.empty()) { + for (auto& i : parent_->GetContexts()) { + if (i->GetContextId() == class_id) { + WidgetContext* cxt = dynamic_cast(i.get()); + if (cxt == nullptr) + continue; + + cxt->impl_->UpdateProcess(b); + } + } + return; + } + + auto context = parent_->FindById(id); + if (context.get() == nullptr) { + _E("Failed to find widget context. ID(%s)", id.c_str()); + return; + } + + WidgetContext* wc = dynamic_cast(context.get()); + if (wc == nullptr) + return; + + wc->impl_->UpdateProcess(b); +} + +void WidgetBase::Impl::ControlResize(const std::string& class_id, + const std::string& id, const tizen_base::Bundle& b) { + auto context = parent_->FindById(id); + if (context.get() == nullptr) { + _E("Failed to find widget context. ID(%s)", id.c_str()); + return; + } + + int w = 0; + std::string w_str = b.GetString(WIDGET_K_WIDTH); + if (!w_str.empty()) { + char* remain = nullptr; + w = static_cast(g_ascii_strtoll(w_str.c_str(), &remain, 10)); + } + + int h = 0; + std::string h_str = b.GetString(WIDGET_K_HEIGHT); + if (!h_str.empty()) { + char* remain = nullptr; + h = static_cast(g_ascii_strtoll(h_str.c_str(), &remain, 10)); + } + + WidgetContext* wc = dynamic_cast(context.get()); + if (wc == nullptr) + return; + + wc->OnResize(w, h); + + _D("WidgetContext(%s) is resized to %dx%d", id.c_str(), w, h); + __context.SendUpdateStatus(class_id, id, + WIDGET_INSTANCE_EVENT_SIZE_CHANGED, 0, nullptr); +} + +void WidgetBase::Impl::ControlChangePeriod(const std::string& class_id, + const std::string& id, const tizen_base::Bundle& b) { + auto context = parent_->FindById(id); + if (context.get() == nullptr) { + _E("Failed to find widget context. ID(%s)", id.c_str()); + return; + } + + WidgetContext* wc = dynamic_cast(context.get()); + if (wc == nullptr) + return; + + wc->impl_->UnsetPeriodicTimer(); + + auto v = b.GetByte(WIDGET_K_PERIOD); + if (v.empty()) + return; + + const double* period = reinterpret_cast(v.data()); + wc->impl_->SetPeriod(*period); + wc->impl_->SetPeriodicTimer(); +} + +void WidgetBase::Impl::GetContent(tizen_base::Bundle& b) { + std::string instance_id = b.GetString(AUL_K_WIDGET_INSTANCE_ID); + if (instance_id.empty()) { + _E("Instance ID is nullptr"); + return; + } + + auto context = parent_->FindById(instance_id); + if (context.get() == nullptr) { + _E("Failed to find widget context. ID(%s)", instance_id.c_str()); + return; + } + + WidgetContext* wc = dynamic_cast(context.get()); + if (wc == nullptr) + return; + + if (!wc->impl_->content_.empty()) { + b.Add(AUL_K_WIDGET_CONTENT_INFO, wc->impl_->content_); + _D("Content info of %s found", instance_id.c_str()); + } else { + b.Add(AUL_K_WIDGET_CONTENT_INFO, ""); + _D("Empty content info added"); + } +} + +WidgetBase::WidgetBase() : impl_(std::make_unique(this)) { +} + +WidgetBase::~WidgetBase() = default; + +std::string WidgetBase::GetViewerEndpoint() { + return __context.GetViewerEndpoint(); +} + +void WidgetBase::Run(int argc, char** argv) { + bundle* kb = bundle_import_from_argv(argc, argv); + if (kb) { + tizen_base::Bundle b(kb, false, true); + __context.SetViewerEndpoint(b.GetString(AUL_K_WIDGET_VIEWER)); + if (!__context.GetViewerEndpoint().empty()) + _D("Viewer endpoint :%s", __context.GetViewerEndpoint().c_str()); + else + _E("Endpoint is missing"); + } else { + _E("Failed to get launch argv"); + throw std::runtime_error("Failed to get launch argv"); + } + + AppCoreMultiWindowBase::Run(argc, argv); +} + +void WidgetBase::Dispose() { + AppCoreMultiWindowBase::Dispose(); + if (getenv("AUL_LOADER_INIT")) { + unsetenv("AUL_LOADER_INIT"); + OnLoopFinish(); + } +} + +void WidgetBase::ExitContext( + std::shared_ptr context) { + AppCoreMultiWindowBase::ExitContext(context); + int cnt = GetContextCnt(); + if (cnt == 0) + Exit(); + + aul_widget_write_log(LOG_TAG, + "[%s:%d] instance_id(%s)", __FUNCTION__, __LINE__, + context->GetInstId().c_str()); +} + +void WidgetBase::Exit() { + AppCoreMultiWindowBase::Exit(); + int cnt = GetContextCnt(); + int ret = 0; + if (cnt == 0 && __context.IsPermanent()) + ret = aul_notify_exit(); + + aul_widget_write_log(LOG_TAG, + "[%s:%d] exit : ret(%d), cnt(%d), permanent(%d)", + __FUNCTION__, __LINE__, ret, cnt, __context.IsPermanent()); +} + +int WidgetBase::OnCreate() { + AppCoreMultiWindowBase::OnCreate(); + + char appid[256] = { 0, }; + int ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid)); + if (ret != AUL_R_OK) { + _E("aul_app_get_appid_bypid() is failed. error(%d)", ret); + return -1; + } + + __context.SetAppId(appid); + + char pkgid[256] = { 0, }; + ret = aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)); + if (ret != AUL_R_OK) { + _E("aul_app_get_pkgid_bypid() is failed. error(%d)", ret); + return -1; + } + + __context.SetPackageId(pkgid); + + screen_connector_provider_init(); + _D("Widget base is created"); + __widget = this; + return 0; +} + +int WidgetBase::OnTerminate() { + screen_connector_provider_fini(); + __widget = nullptr; + + AppCoreMultiWindowBase::OnTerminate(); + _D("Widget base is terminated"); + return 0; +} + +int WidgetBase::OnReceive(aul_type type, tizen_base::Bundle b) { + AppCoreMultiWindowBase::OnReceive(type, + tizen_base::Bundle(b.GetHandle(), false, false)); + + switch (type) { + case AUL_RESUME: { + for (auto& i : GetContexts()) + i->Resume(); + } + break; + case AUL_TERMINATE: + Exit(); + break; + case AUL_WIDGET_CONTENT: + impl_->GetContent(b); + break; + default: + break; + } + + return 0; +} + +int WidgetBase::OnControl(tizen_base::Bundle b) { + AppCoreMultiWindowBase::OnControl( + tizen_base::Bundle(b.GetHandle(), false, false)); + + std::string class_id = b.GetString(WIDGET_K_CLASS); + /* for previous version compatibility, use appid for default class id */ + if (class_id.empty()) + class_id = __context.GetAppId(); + + std::string id = b.GetString(AUL_K_WIDGET_INSTANCE_ID); + std::string operation = b.GetString(WIDGET_K_OPERATION); + if (operation.empty()) { + _E("Operation is empty"); + return 0; + } + + _I("Operation(%s)", operation.c_str()); + if (operation == "create") + impl_->ControlCreate(class_id, id, b); + else if (operation == "resize") + impl_->ControlResize(class_id, id, b); + else if (operation == "update") + impl_->ControlUpdate(class_id, id, b); + else if (operation == "destroy") + impl_->ControlDestroy(class_id, id, b); + else if (operation == "resume") + impl_->ControlResume(class_id, id, b); + else if (operation == "pause") + impl_->ControlPause(class_id, id, b); + else if (operation == "terminate") + impl_->ControlDestroy(class_id, id, b); + else if (operation == "period") + impl_->ControlChangePeriod(class_id, id, b); + + return 0; +} + +void WidgetContext::Impl::OnUpdate(bool force) { + parent_->OnUpdate(pending_content_.empty() ? tizen_base::Bundle() : + tizen_base::Bundle(pending_content_), force); + + std::string class_id = parent_->GetContextId(); + std::string id = parent_->GetInstId(); + __context.SendUpdateStatus(class_id, id, + WIDGET_INSTANCE_EVENT_UPDATE, 0, nullptr); + _D("Updated: %s", id.c_str()); +} + +void WidgetContext::Impl::UpdateProcess(const tizen_base::Bundle& b) { + bool force; + std::string force_str = b.GetString(WIDGET_K_FORCE); + if (force_str == "true") + force = true; + else + force = false; + + std::string content_raw = b.GetString(WIDGET_K_CONTENT_INFO); + if (!parent_->IsResumed() && !force) { + pending_content_ = content_raw; + pending_update_ = true; + } else { + parent_->OnUpdate(content_raw.empty() ? tizen_base::Bundle() : + tizen_base::Bundle(content_raw), force); + + std::string class_id = parent_->GetContextId(); + std::string id = parent_->GetInstId(); + __context.SendUpdateStatus(class_id, id, + WIDGET_INSTANCE_EVENT_UPDATE, 0, nullptr); + _D("Updated: %s", id.c_str()); + } +} + +void WidgetContext::Impl::SetPeriod(double period) { + period_ = period; +} + +void WidgetContext::Impl::SetPeriodicTimer() { + if (periodic_timer_) + return; + + if (period_ > 0) { + _D("Restart timer!"); + periodic_timer_ = g_timeout_add_seconds(period_, + TimedOutCb, parent_); + } +} + +void WidgetContext::Impl::UnsetPeriodicTimer() { + if (periodic_timer_) { + _D("Remove timer!"); + g_source_remove(periodic_timer_); + periodic_timer_ = 0; + } +} + +gboolean WidgetContext::Impl::TimedOutCb(gpointer user_data) { + WidgetContext* wc = reinterpret_cast(user_data); + if (wc->IsResumed()) { + _D("Periodic update!"); + wc->OnUpdate(tizen_base::Bundle(), false); + + __context.SendUpdateStatus(wc->GetContextId(), wc->GetInstId(), + WIDGET_INSTANCE_EVENT_UPDATE, 0, nullptr); + _D("Updated: %s", wc->GetInstId().c_str()); + } else { + wc->impl_->pending_update_ = true; + wc->impl_->UnsetPeriodicTimer(); + } + + return G_SOURCE_CONTINUE; +} + +WidgetContext::WidgetContext(std::string context_id, std::string inst_id, + AppCoreMultiWindowBase* app) + : AppCoreMultiWindowBase::Context( + std::move(context_id), std::move(inst_id), app), + impl_(std::make_unique(this)) { +} + +WidgetContext::~WidgetContext() = default; + +void WidgetContext::OnPause() { + std::string id = GetInstId(); + _D("WidgetContext(%s) is paused", id.c_str()); + std::string class_id = GetContextId(); + __context.SendUpdateStatus(class_id.c_str(), id.c_str(), + WIDGET_INSTANCE_EVENT_PAUSE, 0, nullptr); + + if (__context.IsFgSignal()) { + _D("Send bg signal to resourceD"); + aul_widget_instance_change_status(class_id.c_str(), kStatusBackground); + __context.SetFgSignal(false); + } +} + +void WidgetContext::OnResume() { + if (impl_->pending_update_) { + _D("Pending update!"); + impl_->pending_update_ = false; + impl_->OnUpdate(false); + impl_->SetPeriodicTimer(); + } + + std::string id = GetInstId(); + _D("WidgetContext(%s) is resumed", id.c_str()); + std::string class_id = GetContextId(); + __context.SendUpdateStatus(class_id.c_str(), id.c_str(), + WIDGET_INSTANCE_EVENT_RESUME, 0, nullptr); + + if (!__context.IsFgSignal()) { + _D("Send fg signal to resourceD"); + aul_widget_instance_change_status(class_id.c_str(), kStatusForeground); + __context.SetFgSignal(true); + } +} + +void WidgetContext::OnResize(int w, int h) { +} + +void WidgetContext::OnUpdate(const tizen_base::Bundle& contents, bool force) { +} + +void WidgetContext::ExitAsync() { + tizen_base::Bundle b; + b.Add(WIDGET_K_OPERATION, "terminate"); + + impl_->args_.reset(new tizen_base::Bundle(std::move(b))); + g_idle_add([](gpointer user_data) -> gboolean { + if (__widget == nullptr) + return G_SOURCE_REMOVE; + + WidgetContext* wc = static_cast(user_data); + + std::string id = wc->GetInstId(); + auto context = __widget->FindById(id); + if (context.get() == nullptr) { + _E("Failed to find context. ID(%s)", id.c_str()); + return G_SOURCE_REMOVE; + } + + __widget->ExitContext(context); + return G_SOURCE_REMOVE; + }, this); +} + +int WidgetContext::SetContents(const tizen_base::Bundle& contents) { + std::string id = GetInstId(); + if (id.empty()) + return WIDGET_ERROR_FAULT; + + std::string class_id = GetContextId(); + if (class_id.empty()) + return WIDGET_ERROR_FAULT; + + int ret = __context.SendUpdateStatus(class_id, id, + WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0, contents.GetHandle()); + if (ret < 0) { + _E("Failed to send content info: %s of %s (%d)", + id.c_str(), class_id.c_str(), ret); + return WIDGET_ERROR_FAULT; + } + + return WIDGET_ERROR_NONE; +} + +int WidgetContext::WindowBind(std::string id, Ecore_Wl2_Window* wl_win) { + wl_surface* surface = ecore_wl2_window_surface_get(wl_win); + if (surface == nullptr) { + _E("Failed to get surface, wl_win(%p)", wl_win); + return -1; + } + + screen_connector_provider_remote_enable(id.c_str(), surface); + WindowBind(wl_win); + return 0; +} + +void WidgetContext::OnCreate() { + auto& b = impl_->args_; + std::string class_id = b->GetString(WIDGET_K_CLASS); + /* For previous version compatibility, use appid for default class id */ + if (class_id.empty()) + class_id = __context.GetAppId(); + + std::string id = b->GetString(AUL_K_WIDGET_INSTANCE_ID); + std::string operation = b->GetString(WIDGET_K_OPERATION); + if (operation.empty()) { + _E("Operation is empty"); + return; + } + + std::string w_str = b->GetString(WIDGET_K_WIDTH); + int w = 0; + if (!w_str.empty()) { + char* remain = nullptr; + w = static_cast(g_ascii_strtoll(w_str.c_str(), &remain, 10)); + } + + std::string h_str = b->GetString(WIDGET_K_HEIGHT); + int h = 0; + if (!h_str.empty()) { + char* remain = nullptr; + h = static_cast(g_ascii_strtoll(h_str.c_str(), &remain, 10)); + } + + tizen_base::Bundle content_info; + std::string content = b->GetString(WIDGET_K_CONTENT_INFO); + try { + if (!content.empty()) + content_info = tizen_base::Bundle(content); + } catch (std::bad_alloc& e) { + _W("Failed to decode content info(%s)", content.c_str()); + } + + bool r = OnCreate(content_info, w, h); + if (!r) { + _W("Create callback returns error"); + int ret = __context.SendUpdateStatus(class_id, id, + WIDGET_INSTANCE_EVENT_CREATE_ABORTED, WIDGET_ERROR_CANCELED, nullptr); + if (ret != 0) + _E("Failed to send abrot status. error(%d)", ret); + + throw std::runtime_error("Create callback returns error"); + } else { + _D("WidgetContext(%s) is created", id.c_str()); + aul_widget_instance_add(class_id.c_str(), id.c_str()); + int ret = __context.SendUpdateStatus(class_id, id, + WIDGET_INSTANCE_EVENT_CREATE, 0, nullptr); + if (ret != 0) + _E("Failed to send create status. error(%d)", ret); + + auto v = b->GetByte(WIDGET_K_PERIOD); + if (v.empty()) + return; + + const double* period = reinterpret_cast(v.data()); + if (*period > 0) { + _I("Set periodic update timer. period(%lf)", *period); + impl_->SetPeriod(*period); + impl_->SetPeriodicTimer(); + } + } +} + +void WidgetContext::OnTerminate() { + DestroyType reason = DestroyType::TEMPORARY; + int event = WIDGET_INSTANCE_EVENT_TERMINATE; + std::string id = GetInstId(); + std::string class_id = GetContextId(); + auto& b = impl_->args_; + if (b.get()) { + std::string operation = b->GetString(WIDGET_K_OPERATION); + if (operation == "destroy") + reason = DestroyType::PERMANENT; + } + + tizen_base::Bundle content_info = impl_->content_.empty() ? + tizen_base::Bundle() : tizen_base::Bundle(impl_->content_); + + OnDestroy(reason, content_info); + + _W("WidgetContext(%s) is destroyed. reason(%s)", id.c_str(), + reason == DestroyType::TEMPORARY ? "TEMPORARY" : "PERMANENT"); + if (reason == DestroyType::PERMANENT) { + __context.SetPermanent(true); + event = WIDGET_INSTANCE_EVENT_DESTROY; + aul_widget_instance_del(class_id.c_str(), id.c_str()); + } else { + __context.SetPermanent(false); + __context.SendUpdateStatus(class_id.c_str(), id.c_str(), + WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0, content_info.GetHandle()); + } + + impl_->UnsetPeriodicTimer(); + + __context.SendUpdateStatus(class_id.c_str(), id.c_str(), event, 0, nullptr); +} + +} // namespace tizen_cpp diff --git a/src/base/widget_base.c b/src/base/widget_base_legacy.c similarity index 99% rename from src/base/widget_base.c rename to src/base/widget_base_legacy.c index ec0d02d..40115b7 100644 --- a/src/base/widget_base.c +++ b/src/base/widget_base_legacy.c @@ -1,46 +1,42 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved * - * Licensed under the Apache License, Version 2.0 (the License); + * 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, + * 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 #include #include #include -#include -#include -#include -#include -#include - -#include "widget_base.h" -#ifdef LOG_TAG -#undef LOG_TAG -#endif +#include "common/export_private.hh" +#include "common/log_private.hh" +#include "include/widget_base.h" -#define LOG_TAG "CAPI_WIDGET_APPLICATION" #define APP_TYPE_WIDGET "widgetapp" #define STATUS_FOREGROUND "fg" #define STATUS_BACKGROUND "bg" diff --git a/src/common/export_private.hh b/src/common/export_private.hh new file mode 100644 index 0000000..1102d02 --- /dev/null +++ b/src/common/export_private.hh @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef COMMON_EXPORT_PRIVATE_HH_ +#define COMMON_EXPORT_PRIVATE_HH_ + +#undef EXPORT_API +#define EXPORT_API __attribute__ ((visibility("default"))) + +#undef API +#define API extern "C" EXPORT_API + +#endif // COMMON_EXPORT_PRIVATE_HH_ diff --git a/src/common/log_private.hh b/src/common/log_private.hh new file mode 100644 index 0000000..52b17e6 --- /dev/null +++ b/src/common/log_private.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef COMMON_LOG_PRIVATE_HH_ +#define COMMON_LOG_PRIVATE_HH_ + +#include + +#undef LOG_TAG +#define LOG_TAG "CAPI_WIDGET_APPLICATION" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // COMMON_LOG_PRIVATE_HH_ diff --git a/src/efl_base/CMakeLists.txt b/src/efl_base/CMakeLists.txt index 610bb00..357f9cc 100644 --- a/src/efl_base/CMakeLists.txt +++ b/src/efl_base/CMakeLists.txt @@ -1,25 +1,38 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} WIDGET_APPLICATION_SRCS) ADD_LIBRARY(${TARGET_WIDGET_APPLICATION} SHARED ${WIDGET_APPLICATION_SRCS}) -SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION} PROPERTIES SOVERSION ${MAJORVER}) -SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION} PROPERTIES VERSION ${FULLVER}) -TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION} PRIVATE ${TARGET_WIDGET_BASE}) -TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) -TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../include/) +SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION} + PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION} + PROPERTIES VERSION ${FULLVER}) +TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION} + PRIVATE ${TARGET_WIDGET_BASE}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/ + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../include/ + ${CMAKE_CURRENT_SOURCE_DIR}/../base/ + ${CMAKE_CURRENT_SOURCE_DIR}/../common/) APPLY_PKG_CONFIG(${TARGET_WIDGET_APPLICATION} PUBLIC AUL_DEP DLOG_DEPS APPCORE_COMMON_DEPS ELEMENTARY_DEP + SYSTEM_INFO_DEPS WIDGET_SERVICE_DEPS CAPI_APP_COMMON_DEP ) -CONFIGURE_FILE(../../capi-appfw-widget-application.pc.in ../../capi-appfw-widget-application.pc @ONLY) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/capi-appfw-widget-application.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/capi-appfw-widget-application.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/capi-appfw-widget-application.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + INSTALL(TARGETS ${TARGET_WIDGET_APPLICATION} DESTINATION ${LIB_INSTALL_DIR}) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../capi-appfw-widget-application.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/appfw/ FILES_MATCHING PATTERN "*.h*" diff --git a/capi-appfw-widget-application.pc.in b/src/efl_base/capi-appfw-widget-application.pc.in similarity index 100% rename from capi-appfw-widget-application.pc.in rename to src/efl_base/capi-appfw-widget-application.pc.in diff --git a/src/efl_base/widget-log.h b/src/efl_base/widget-log.h deleted file mode 100644 index a316028..0000000 --- a/src/efl_base/widget-log.h +++ /dev/null @@ -1,83 +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. - */ - - -#ifndef __APPFW_WIDGET_LOG_H__ -#define __APPFW_WIDGET_LOG_H__ - -#include - -#define _E(fmt, arg...) LOGE(fmt, ##arg) -#define _I(fmt, arg...) LOGI(fmt, ##arg) -#define _D(fmt, arg...) LOGD(fmt, ##arg) -#define _W(fmt, arg...) LOGW(fmt, ##arg) - -#ifndef EXPORT_API -#define EXPORT_API __attribute__ ((visibility("default"))) -#endif - -#ifndef _E -#define _E(fmt, arg...) LOGE(fmt, ##arg) -#endif - -#ifndef _I -#define _I(...) LOGI(__VA_ARGS__) -#endif - -#ifndef _D -#define _D(...) LOGD(__VA_ARGS__) -#endif - -#ifndef _W -#define _W(...) LOGW(__VA_ARGS__) -#endif - -#define _warn_if(expr, fmt, arg...) \ - do { \ - if (expr) \ - _ERR(fmt, ##arg); \ - } while (0) - -#define _ret_if(expr) \ - do { \ - if (expr) \ - return; \ - } while (0) - -#define _retv_if(expr, val) \ - do { \ - if (expr) \ - return (val); \ - } while (0) - -#define _retm_if(expr, fmt, arg...) \ - do { \ - if (expr) { \ - _ERR(fmt, ##arg); \ - return; \ - } \ - } while (0) - -#define _retvm_if(expr, val, fmt, arg...) \ - do { \ - if (expr) { \ - _ERR(fmt, ##arg); \ - return (val); \ - } \ - } while (0) - -#endif /* __APPFW_WIDGET_LOG_H_ */ - diff --git a/src/efl_base/widget-private.h b/src/efl_base/widget-private.h deleted file mode 100644 index 34fdc5f..0000000 --- a/src/efl_base/widget-private.h +++ /dev/null @@ -1,32 +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. - */ - - -#ifndef __APPCORE_WIDGET_PRIVATE_H__ -#define __APPCORE_WIDGET_PRIVATE_H__ - -#include - -#include -#include -#include -#include - -int widget_app_error(widget_error_e error, const char *function, - const char *description); - -#endif /* __APPCORE_WIDGET_PRIVATE_H__ */ - diff --git a/src/efl_base/widget_app.c b/src/efl_base/widget_app.c deleted file mode 100644 index 174195f..0000000 --- a/src/efl_base/widget_app.c +++ /dev/null @@ -1,595 +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 "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" -#define ICONIFY_TIMEOUT 500 - -struct instance_data { - Evas_Object *win; - guint iconify_timer; - bool is_iconified; -}; - -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 GList *__class_data_list; - -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) { - _E("widget_base_context_get_user_data() returns null"); - - return -1; - } - - 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); - aul_widget_write_log(LOG_TAG, "[%s:%d] ret : %d", - __FUNCTION__, __LINE__, ret); - } - 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); - aul_widget_write_log(LOG_TAG, "[%s:%d] ret : %d", - __FUNCTION__, __LINE__, ret); - } - - data = (struct instance_data *)widget_base_context_get_user_data(instance_h); - if (data != NULL) { - widget_base_context_set_user_data(instance_h, NULL); - if (data->iconify_timer > 0) - g_source_remove(data->iconify_timer); - free(data); - } - - widget_base_class_on_destroy(instance_h, reason, content); - - return ret; -} - -static gboolean __iconify_timeout_cb(gpointer user_data) -{ - struct instance_data *data = user_data; - Ecore_Wl2_Window *win = ecore_evas_wayland2_window_get( - ecore_evas_ecore_evas_get(evas_object_evas_get(data->win))); - - if (win) { - ecore_wl2_window_iconified_set(win, EINA_TRUE); - data->is_iconified = true; - _D("set iconify true"); - } - - data->iconify_timer = 0; - - return G_SOURCE_REMOVE; -} - -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; - struct instance_data *data = (struct instance_data *) - widget_base_context_get_user_data(instance_h); - - if (data->iconify_timer > 0) - g_source_remove(data->iconify_timer); - - data->iconify_timer = g_timeout_add(ICONIFY_TIMEOUT, - __iconify_timeout_cb, 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; - Ecore_Wl2_Window *win; - struct instance_data *data = (struct instance_data *) - widget_base_context_get_user_data(instance_h); - - if (data->iconify_timer > 0) { - g_source_remove(data->iconify_timer); - data->iconify_timer = 0; - } - - if (data->is_iconified) { - win = ecore_evas_wayland2_window_get( - ecore_evas_ecore_evas_get(evas_object_evas_get(data->win))); - if (win) { - ecore_wl2_window_iconified_set(win, EINA_FALSE); - data->is_iconified = false; - _D("set iconify false"); - } - } - - 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"); - aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__); - 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"); - aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__); - 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(); -} - -static void __widget_app_trim_memory(void *data) -{ - _D("Trim memory"); - elm_cache_all_flush(); - widget_base_on_trim_memory(); -} - -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; - ops.trim_memory = __widget_app_trim_memory; - - cb_info.callback = callback; - cb_info.user_data = user_data; - - r = widget_base_init(ops, argc, argv, &cb_info); - widget_base_fini(); - - if (__class_data_list) { - g_list_free_full(__class_data_list, free); - __class_data_list = NULL; - } - - 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_Wl2_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 = ecore_evas_wayland2_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(ret_win))); - if (wl_win == NULL) { - _E("failed to get wayland window"); /* LCOV_EXCL_LINE */ - goto fault; - } - - ecore_wl2_window_class_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_wl2_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; - } - - __class_data_list = g_list_append(__class_data_list, callback_data); - 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/efl_base/widget_app.cc b/src/efl_base/widget_app.cc new file mode 100644 index 0000000..17cd02f --- /dev/null +++ b/src/efl_base/widget_app.cc @@ -0,0 +1,718 @@ +/* +* Copyright (c) 2015 - 2021 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 "common/export_private.hh" +#include "common/log_private.hh" +#include "include/widget_app.h" +#include "include/widget_app_internal.h" +#include "include/widget_base.hh" + +using namespace tizen_cpp; +namespace { + +constexpr const int kIconifyTimeout = 500; +constexpr const char kFeatureShellAppWidget[] = + "http://tizen.org/feature/shell.appwidget"; +constexpr int APP_EVENT_MAX = 7; +constexpr IAppCore::IEvent::Type __app_event_converter[APP_EVENT_MAX] = { + [APP_EVENT_LOW_MEMORY] = IAppCore::IEvent::Type::LOW_MEMORY, + [APP_EVENT_LOW_BATTERY] = IAppCore::IEvent::Type::LOW_BATTERY, + [APP_EVENT_LANGUAGE_CHANGED] = IAppCore::IEvent::Type::LANG_CHANGE, + [APP_EVENT_DEVICE_ORIENTATION_CHANGED] + = IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, + [APP_EVENT_REGION_FORMAT_CHANGED] = IAppCore::IEvent::Type::REGION_CHANGE, + [APP_EVENT_SUSPENDED_STATE_CHANGED] + = IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE, +}; + +class AppWidget : public WidgetBase { + public: + AppWidget(widget_app_lifecycle_callback_s* callback, void* user_data) + : callback_(callback), user_data_(user_data) {} + + int OnCreate() override { + WidgetBase::OnCreate(); + if (callback_ && callback_->create) { + if (callback_->create(user_data_) == nullptr) { + _E("Failed to create widget"); + return -1; + } + + _D("Widget app is created"); + aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__); + return 0; + } + + return -1; + } + + int OnTerminate() override { + if (callback_ && callback_->terminate) { + callback_->terminate(user_data_); + WidgetBase::OnTerminate(); + _D("Widget app is terminated"); + aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__); + return 0; + } + + WidgetBase::OnTerminate(); + return -1; + } + + void OnLoopInit(int argc, char** argv) override { + elm_init(argc, argv); + } + + void OnLoopFinish() override { + elm_shutdown(); + } + + void OnLoopRun() override { + elm_run(); + } + + void OnLoopExit() override { + elm_exit(); + } + + int OnTrimMemory() override { + _D("Trim memory"); + elm_cache_all_flush(); + return WidgetBase::OnTrimMemory(); + } + + private: + widget_app_lifecycle_callback_s* callback_; + void* user_data_; +}; + +class AppWidgetContext : public WidgetContext { + public: + class Factory : public AppCoreMultiWindowBase::Context::IFactory { + public: + Factory(std::string widget_id, + widget_instance_lifecycle_callback_s callback, void* user_data) + : widget_id_(std::move(widget_id)), + callback_(callback), + user_data_(user_data) { + } + + std::unique_ptr Create(std::string inst_id, + AppCoreMultiWindowBase* app) override { + return std::unique_ptr( + new AppWidgetContext(widget_id_, std::move(inst_id), app, + callback_, user_data_)); + } + + private: + std::string widget_id_; + widget_instance_lifecycle_callback_s callback_; + void* user_data_; + }; + + AppWidgetContext(std::string context_id, std::string inst_id, + AppCoreMultiWindowBase* app, + widget_instance_lifecycle_callback_s callback, void* user_data) + : WidgetContext(std::move(context_id), std::move(inst_id), app), + callback_(callback), user_data_(user_data) {} + + bool OnCreate(const tizen_base::Bundle& contents, int w, int h) override { + int ret = -1; + if (callback_.create) { + ret = callback_.create(reinterpret_cast(this), + contents.GetHandle(), w, h, user_data_); + aul_widget_write_log(LOG_TAG, "[%s:%d] ret : %d", + __FUNCTION__, __LINE__, ret); + } + + return ret == 0; + } + + void OnDestroy(DestroyType reason, + const tizen_base::Bundle& contents) override { + if (callback_.destroy) { + callback_.destroy(reinterpret_cast(this), + reason == DestroyType::PERMANENT ? WIDGET_APP_DESTROY_TYPE_PERMANENT : + WIDGET_APP_DESTROY_TYPE_TEMPORARY, contents.GetHandle(), user_data_); + aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__); + } + + UnsetIconifyTimer(); + } + + void OnPause() override { + UnsetIconifyTimer(); + SetIconifyTimer(); + + WidgetContext::OnPause(); + if (callback_.pause) { + callback_.pause(reinterpret_cast(this), user_data_); + } + } + + void OnResume() override { + UnsetIconifyTimer(); + + if (is_iconified_) { + Ecore_Wl2_Window* win = ecore_evas_wayland2_window_get( + ecore_evas_ecore_evas_get(evas_object_evas_get(win_))); + if (win) { + ecore_wl2_window_iconified_set(win, EINA_FALSE); + is_iconified_ = false; + _D("Set iconify false"); + } + } + + WidgetContext::OnResume(); + if (callback_.resume) { + callback_.resume(reinterpret_cast(this), user_data_); + } + } + + void OnResize(int w, int h) override { + WidgetContext::OnResize(w, h); + + if (win_) + evas_object_resize(win_, w, h); + else + _E("Failed to find window"); + + if (callback_.resize) { + callback_.resize(reinterpret_cast(this), + w, h, user_data_); + } + } + + void OnUpdate(const tizen_base::Bundle& contents, bool force) override { + WidgetContext::OnUpdate(contents, force); + if (callback_.update) { + callback_.update(reinterpret_cast(this), + contents.GetHandle(), force, user_data_); + } + } + + void SetTag(void* tag) { + tag_ = tag; + } + + void* GetTag() const { + return tag_; + } + + Evas_Object* GetWindow() const { + return win_; + } + + void SetWindow(Evas_Object* win) { + win_ = win; + } + + private: + void SetIconifyTimer() { + if (iconify_timer_) + return; + + iconify_timer_ = g_timeout_add(kIconifyTimeout, + [](gpointer user_data) -> gboolean{ + AppWidgetContext* cxt = static_cast(user_data); + Ecore_Wl2_Window* win = ecore_evas_wayland2_window_get( + ecore_evas_ecore_evas_get(evas_object_evas_get(cxt->win_))); + if (win) { + ecore_wl2_window_iconified_set(win, EINA_TRUE); + cxt->is_iconified_ = true; + _D("Set iconify true"); + } + + cxt->iconify_timer_ = 0; + return G_SOURCE_REMOVE; + }, this); + } + + void UnsetIconifyTimer() { + if (iconify_timer_) { + g_source_remove(iconify_timer_); + iconify_timer_ = 0; + } + } + + private: + widget_instance_lifecycle_callback_s callback_; + void* user_data_; + Evas_Object* win_ = nullptr; + guint iconify_timer_ = 0; + bool is_iconified_ = false; + void* tag_ = nullptr; +}; + +std::unique_ptr __app_widget; +std::list> __pending_app_events; + +} // namespace + +API int widget_app_main(int argc, char** argv, + widget_app_lifecycle_callback_s* callback, void* user_data) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (argc <= 0 || argv == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + if (callback->create == nullptr) { + _E("widget_app_create_cb() callback must be registered"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + try { + __app_widget = std::make_unique(callback, user_data); + for (auto& i : __pending_app_events) + __app_widget->AddEvent(i); + + __app_widget->Run(argc, argv); + } catch (std::runtime_error& e) { + return WIDGET_ERROR_FAULT; + } + + return WIDGET_ERROR_NONE; +} + +API int widget_app_exit(void) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (__app_widget.get() == nullptr) + return WIDGET_ERROR_FAULT; + + __app_widget->Exit(); + return WIDGET_ERROR_NONE; +} + +API int widget_app_terminate_context(widget_context_h context) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (context == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + auto* cxt = reinterpret_cast(context); + cxt->ExitAsync(); + return WIDGET_ERROR_NONE; +} + +API int widget_app_foreach_context(widget_context_cb cb, void* data) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (cb == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + if (__app_widget.get() == nullptr) + return WIDGET_ERROR_FAULT; + + auto l = __app_widget->GetContexts(); + for (auto& i : l) { + if (!cb(reinterpret_cast(i.get()), data)) + break; + } + + return WIDGET_ERROR_NONE; +} + +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) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (event_handler == nullptr || callback == nullptr) + return WIDGET_ERROR_INVALID_PARAMETER; + + if (event_type < APP_EVENT_LOW_MEMORY || + event_type > APP_EVENT_REGION_FORMAT_CHANGED) + return WIDGET_ERROR_INVALID_PARAMETER; + + if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED) + return WIDGET_ERROR_NOT_SUPPORTED; + + auto* app_event = new (std::nothrow) AppEvent( + ::__app_event_converter[event_type], callback, user_data); + if (app_event == nullptr) { + _E("Out of memory"); + return WIDGET_ERROR_OUT_OF_MEMORY; + } + + auto* h = new (std::nothrow) std::shared_ptr(app_event); + if (h == nullptr) { + _E("Out of memory"); + delete app_event; + return WIDGET_ERROR_OUT_OF_MEMORY; + } + + if (__app_widget.get() != nullptr) + __app_widget->AddEvent(*h); + else + __pending_app_events.push_back(*h); + + *event_handler = reinterpret_cast(h); + return WIDGET_ERROR_NONE; +} + +API int widget_app_remove_event_handler(app_event_handler_h event_handler) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (event_handler == nullptr) + return WIDGET_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast*>(event_handler); + + if (__app_widget.get() != nullptr) { + if (!__app_widget->RemoveEvent(*h)) + return WIDGET_ERROR_INVALID_PARAMETER; + } else { + __pending_app_events.remove(*h); + } + + delete h; + return WIDGET_ERROR_NONE; +} + +API const char* widget_app_get_id(widget_context_h context) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) { + set_last_result(WIDGET_ERROR_FAULT); + return nullptr; + } + + if (!feature) { + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return nullptr; + } + + if (context == nullptr) { + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return nullptr; + } + + auto* cxt = reinterpret_cast(context); + const std::string& id = cxt->GetInstId(); + set_last_result(WIDGET_ERROR_NONE); + return id.c_str(); +} + +API int widget_app_get_elm_win(widget_context_h context, Evas_Object** win) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (context == nullptr || win == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + auto* cxt = reinterpret_cast(context); + const std::string& id = cxt->GetInstId(); + + Evas_Object* ret_win = elm_win_add(nullptr, id.c_str(), ELM_WIN_BASIC); + if (ret_win == nullptr) { + _E("Failed to create window"); + return WIDGET_ERROR_FAULT; + } + + elm_win_wm_rotation_preferred_rotation_set(ret_win, -1); + int rots[3] = { 0, }; + elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1); + + Ecore_Wl2_Window* wl_win = ecore_evas_wayland2_window_get( + ecore_evas_ecore_evas_get(evas_object_evas_get(ret_win))); + if (wl_win == nullptr) { + _E("Failed to get wayland window"); + evas_object_del(ret_win); + return WIDGET_ERROR_FAULT; + } + + ecore_wl2_window_class_set(wl_win, id.c_str()); + elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1"); + cxt->WindowBind(id, wl_win); + + /* Set data to use in accessibility */ + std::string plug_id = id + ":" + std::to_string(getpid()); + evas_object_data_set(ret_win, "___PLUGID", strdup(plug_id.c_str())); + evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, + [](void *data, Evas *e, Evas_Object *obj, void *event_info) { + char* plug_id = static_cast( + evas_object_data_del(obj, "___PLUGID")); + free(plug_id); + }, nullptr); + + int win_id = ecore_wl2_window_id_get(wl_win); + _D("Window created: %d", win_id); + + cxt->SetWindow(ret_win); + *win = ret_win; + return WIDGET_ERROR_NONE; +} + +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) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) { + set_last_result(WIDGET_ERROR_FAULT); + return nullptr; + } + + if (!feature) { + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return nullptr; + } + + if (class_id == nullptr || callback.create == nullptr) { + _E("Invalid parameter"); + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return nullptr; + } + + if (__app_widget.get() == nullptr) { + set_last_result(WIDGET_ERROR_FAULT); + return nullptr; + } + + auto factory = std::shared_ptr( + new (std::nothrow) AppWidgetContext::Factory( + class_id, callback, user_data)); + if (factory.get() == nullptr) { + set_last_result(WIDGET_ERROR_OUT_OF_MEMORY); + return nullptr; + } + + __app_widget->AddContextFactory(std::move(factory), class_id); + set_last_result(WIDGET_ERROR_NONE); + int dummy; + widget_class_h cls = reinterpret_cast(&dummy); + return cls; +} + +API widget_class_h widget_app_class_create( + widget_instance_lifecycle_callback_s callback, void* user_data) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) { + set_last_result(WIDGET_ERROR_FAULT); + return nullptr; + } + + if (!feature) { + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return nullptr; + } + + if (callback.create == nullptr) { + _E("Invalid parameter"); + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return nullptr; + } + + char* appid = nullptr; + app_get_id(&appid); + if (appid == nullptr) { + LOGE("app_get_id() is failed"); + return nullptr; + } + std::unique_ptr ptr(appid, std::free); + + return static_cast( + widget_app_class_add(nullptr, appid, callback, user_data)); +} + +API int widget_app_context_set_tag(widget_context_h context, void* tag) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (context == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + auto* cxt = reinterpret_cast(context); + cxt->SetTag(tag); + return WIDGET_ERROR_NONE; +} + +API int widget_app_context_get_tag(widget_context_h context, void** tag) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (context == nullptr || tag == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + auto* cxt = reinterpret_cast(context); + *tag = cxt->GetTag(); + return WIDGET_ERROR_NONE; +} + +API int widget_app_context_set_content_info(widget_context_h context, + bundle* content_info) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (context == nullptr || content_info == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + auto* cxt = reinterpret_cast(context); + ret = cxt->SetContents(tizen_base::Bundle(content_info)); + if (ret != WIDGET_ERROR_NONE) { + _E("Failed to set content"); + return static_cast(ret); + } + + return WIDGET_ERROR_NONE; +} + +API int widget_app_context_set_title(widget_context_h context, + const char* title) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (context == nullptr || title == nullptr) { + _E("Invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + auto* cxt = reinterpret_cast(context); + if (cxt->GetWindow()) + elm_win_title_set(cxt->GetWindow(), title); + + return WIDGET_ERROR_NONE; +} + +API int widget_app_restart(void) { + bool feature; + int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature); + if (ret < 0) + return WIDGET_ERROR_FAULT; + + if (!feature) + return WIDGET_ERROR_NOT_SUPPORTED; + + if (__app_widget.get() == nullptr) + return WIDGET_ERROR_IO_ERROR; + + std::string class_id; + auto l = __app_widget->GetContexts(); + for (auto& i : l) { + class_id = i->GetContextId(); + break; + } + + if (class_id.empty()) + return WIDGET_ERROR_IO_ERROR; + + tizen_base::Bundle b; + int status = AUL_WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST; + std::vector v; + auto* p = reinterpret_cast(&status); + std::copy(p, p + sizeof(int), std::back_inserter(v)); + + b.Add(AUL_K_WIDGET_ID, class_id); + b.Add(AUL_K_WIDGET_STATUS, v); + + std::string endpoint = __app_widget->GetViewerEndpoint(); + ret = aul_app_com_send(endpoint.empty() ? nullptr : endpoint.c_str(), + b.GetHandle()); + if (ret != AUL_R_OK) { + _E("Failed to send restart request"); + return WIDGET_ERROR_IO_ERROR; + } + + return WIDGET_ERROR_NONE; +} diff --git a/src/efl_base/widget_app_internal.c b/src/efl_base/widget_app_internal.c deleted file mode 100644 index cbd7e4c..0000000 --- a/src/efl_base/widget_app_internal.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 "widget_app.h" -#include "widget-log.h" -#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" -static char *__class_id; - -/* LCOV_EXCL_START */ -static void __inst_cb(const char *class_id, const char *id, - appcore_multiwindow_base_instance_h cxt, void *data) -{ - if (!__class_id) - __class_id = strdup(class_id); -} -/* LCOV_EXCL_STOP */ - -EXPORT_API int widget_app_restart(void) -{ - int ret; - int status = AUL_WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST; - bundle *kb; - - appcore_multiwindow_base_instance_foreach_full(__inst_cb, NULL); - - 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(widget_base_get_viewer_endpoint(), kb); - bundle_free(kb); - if (__class_id) { - free(__class_id); - __class_id = NULL; - } - - if (ret != AUL_R_OK) { - _E("failed to kill app"); - return WIDGET_ERROR_IO_ERROR; - } - return WIDGET_ERROR_NONE; -} - diff --git a/src/efl_base/widget_error.c b/src/efl_base/widget_error.c deleted file mode 100644 index cd79e5f..0000000 --- a/src/efl_base/widget_error.c +++ /dev/null @@ -1,84 +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 "widget-private.h" - -#ifdef LOG_TAG -#undef LOG_TAG -#endif - -#define LOG_TAG "CAPI_WIDGET_APPLICATION" - -static const char *widget_app_error_to_string(widget_error_e error) -{ - switch (error) { - case WIDGET_ERROR_NONE: - return "NONE"; - case WIDGET_ERROR_INVALID_PARAMETER: - return "INVALID_PARAMETER"; - case WIDGET_ERROR_OUT_OF_MEMORY: - return "OUT_OF_MEMORY"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_RESOURCE_BUSY: - return "RESOURCE_BUSY"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_PERMISSION_DENIED: - return "PERMISSION_DENIED"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_CANCELED: - return "CANCELED"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_IO_ERROR: - return "IO_ERROR"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_TIMED_OUT: - return "TIMED_OUT"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_NOT_SUPPORTED: - return "NOT_SUPPORTED"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_FILE_NO_SPACE_ON_DEVICE: - return "FILE_NO_SPACE_ON_DEVICE"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_FAULT: - return "FAULT"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_ALREADY_EXIST: - return "ALREADY_EXIST"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_ALREADY_STARTED: - return "ALREADY_STARTED"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_NOT_EXIST: - return "NOT_EXIST"; /* LCOV_EXCL_LINE */ - case WIDGET_ERROR_DISABLED: - return "DISABLED"; /* LCOV_EXCL_LINE */ - default: - return "UNKNOWN"; /* LCOV_EXCL_LINE */ - } -} - -int widget_app_error(widget_error_e error, const char *function, - const char *description) -{ - if (description) { - LOGE("[%s] %s(0x%08x) : %s", function, - widget_app_error_to_string(error), error, - description); - } else { - LOGE("[%s] %s(0x%08x)", function, - widget_app_error_to_string(error), error); - } - - return error; -} - diff --git a/test/unit_tests/CMakeLists.txt b/test/unit_tests/CMakeLists.txt index 64fd8a4..7a2beb7 100644 --- a/test/unit_tests/CMakeLists.txt +++ b/test/unit_tests/CMakeLists.txt @@ -1,25 +1,40 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ UNIT_TESTS_SRCS) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/mock/ UNIT_TESTS_SRCS) -ADD_EXECUTABLE(${TARGET_WIDGET_APPLICATION_UNIT_TEST} - ${UNIT_TESTS_SRCS} -) + +ADD_EXECUTABLE(${TARGET_WIDGET_APPLICATION_UNIT_TEST} ${UNIT_TESTS_SRCS}) TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/../" - "${CMAKE_CURRENT_SOURCE_DIR}/../../include" - "${CMAKE_CURRENT_SOURCE_DIR}/../../src/efl_base" + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/ + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/base + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/efl_base ) APPLY_PKG_CONFIG(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC + APPCORE_COMMON_DEPS + APPCORE_MULTIWINDOW_DEPS + APPCORE_MULTIWINDOW_OLD_DEPS + AUL_DEP + BUNDLE_DEPS + CAPI_APP_COMMON_DEP + DLOG_DEPS + ECORE_WL2_DEPS + ELEMENTARY_DEP GLIB_DEPS GMOCK_DEPS - BUNDLE_DEPS - GOBJECT_DEPS + SCREEN_CONNECTOR_PROVIDER_DEPS + SYSTEM_INFO_DEPS + WIDGET_SERVICE_DEPS ) -TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC ${TARGET_WIDGET_BASE} ${TARGET_WIDGET_APPLICATION}) -SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PROPERTIES COMPILE_FLAGS "-fPIE") -SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PROPERTIES LINK_FLAGS "-pie") +TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC + ${TARGET_WIDGET_APPLICATION}) +SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} + PROPERTIES COMPILE_FLAGS "-fPIE") +SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} + PROPERTIES LINK_FLAGS "-pie") ADD_TEST( NAME ${TARGET_WIDGET_APPLICATION_UNIT_TEST} diff --git a/test/unit_tests/mock/app_common_mock.h b/test/unit_tests/mock/app_common_mock.h index 5fa214e..7219d89 100644 --- a/test/unit_tests/mock/app_common_mock.h +++ b/test/unit_tests/mock/app_common_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ #define UNIT_TESTS_MOCK_APP_COMMON_MOCK_H_ #include -#include #include "mock/module_mock.h" diff --git a/test/unit_tests/mock/appcore_multiwindow_base_mock.cc b/test/unit_tests/mock/appcore_multiwindow_base_mock.cc index fe09a24..c66bd8e 100644 --- a/test/unit_tests/mock/appcore_multiwindow_base_mock.cc +++ b/test/unit_tests/mock/appcore_multiwindow_base_mock.cc @@ -21,69 +21,17 @@ #include "unit_tests/mock/mock_hook.h" #include "unit_tests/mock/test_fixture.h" -extern "C" int appcore_multiwindow_base_init( - appcore_multiwindow_base_ops ops, int argc, char **argv, void *data) { - return MOCK_HOOK_P4(MultiWindowBaseMock, appcore_multiwindow_base_init, - ops, argc, argv, data); -} - -extern "C" const char *appcore_multiwindow_base_instance_get_id( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_get_id, context); -} - -extern "C" void *appcore_multiwindow_base_instance_get_extra( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_get_extra, context); -} - -extern "C" const char* appcore_multiwindow_base_instance_get_class_id( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_get_class_id, context); -} -extern "C" void appcore_multiwindow_base_class_add( - appcore_multiwindow_base_class cls) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_class_add, cls); -} +namespace tizen_cpp { -extern "C" void appcore_multiwindow_base_instance_drop( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_drop, context); +void AppCoreMultiWindowBase::Run(int argc, char** argv) { + TestFixture::GetMock().real_ = this; + TestFixture::GetMock().Run(argc, argv); + TestFixture::GetMock().real_ = nullptr; } -extern "C" appcore_multiwindow_base_instance_h - appcore_multiwindow_base_instance_find(const char *id) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_find, id); +int AppCoreMultiWindowBase::OnCreate() { + return TestFixture::GetMock().OnCreate(); } -extern "C" const appcore_multiwindow_base_class * - appcore_multiwindow_base_instance_get_class( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_get_class, context); -} - -extern "C" void appcore_multiwindow_base_instance_exit( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_exit, context); -} - -extern "C" void appcore_multiwindow_base_instance_pause( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_pause, context); -} - -extern "C" void appcore_multiwindow_base_instance_resume( - appcore_multiwindow_base_instance_h context) { - return MOCK_HOOK_P1(MultiWindowBaseMock, - appcore_multiwindow_base_instance_resume, context); -} +} // namespace tizen_cpp diff --git a/test/unit_tests/mock/appcore_multiwindow_base_mock.h b/test/unit_tests/mock/appcore_multiwindow_base_mock.h index 06ec917..0f044f8 100644 --- a/test/unit_tests/mock/appcore_multiwindow_base_mock.h +++ b/test/unit_tests/mock/appcore_multiwindow_base_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ #define UNIT_TESTS_MOCK_APPCORE_MULTIWINDOW_BASE_MOCK_H_ #include -#include +#include #include "mock/module_mock.h" @@ -26,28 +26,10 @@ class MultiWindowBaseMock : public virtual ModuleMock { public: virtual ~MultiWindowBaseMock() {} - MOCK_METHOD4(appcore_multiwindow_base_init, - int(appcore_multiwindow_base_ops, int, char **, void *)); - MOCK_METHOD1(appcore_multiwindow_base_instance_get_id, - const char *(appcore_multiwindow_base_instance_h)); - MOCK_METHOD1(appcore_multiwindow_base_instance_get_extra, - void *(appcore_multiwindow_base_instance_h)); - MOCK_METHOD1(appcore_multiwindow_base_instance_get_class_id, - const char *(appcore_multiwindow_base_instance_h)); - MOCK_METHOD1(appcore_multiwindow_base_class_add, - void(appcore_multiwindow_base_class)); - MOCK_METHOD1(appcore_multiwindow_base_instance_drop, - void(appcore_multiwindow_base_instance_h)); - MOCK_METHOD1(appcore_multiwindow_base_instance_find, - appcore_multiwindow_base_instance_h(const char *)); - MOCK_METHOD1(appcore_multiwindow_base_instance_get_class, - const appcore_multiwindow_base_class *(appcore_multiwindow_base_instance_h)); - MOCK_METHOD1(appcore_multiwindow_base_instance_exit, - void(appcore_multiwindow_base_instance_h)); - MOCK_METHOD1(appcore_multiwindow_base_instance_pause, - void(appcore_multiwindow_base_instance_h)); - MOCK_METHOD1(appcore_multiwindow_base_instance_resume, - void(appcore_multiwindow_base_instance_h)); + MOCK_METHOD2(Run, void(int, char**)); + MOCK_METHOD0(OnCreate, int()); + + tizen_cpp::AppCoreMultiWindowBase* real_ = nullptr; }; #endif // UNIT_TESTS_MOCK_APPCORE_MULTIWINDOW_BASE_MOCK_H_ diff --git a/test/unit_tests/mock/aul_mock.cc b/test/unit_tests/mock/aul_mock.cc index 76ed247..65f947c 100644 --- a/test/unit_tests/mock/aul_mock.cc +++ b/test/unit_tests/mock/aul_mock.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,40 @@ #include "unit_tests/mock/mock_hook.h" #include "unit_tests/mock/test_fixture.h" -extern "C" int aul_app_get_pkgid_bypid(int pid, char *pkgid, int len) { +extern "C" int aul_app_get_appid_bypid(int pid, char* appid, int len) { + return MOCK_HOOK_P3(AulMock, aul_app_get_appid_bypid, pid, appid, len); +} + +extern "C" int aul_app_get_pkgid_bypid(int pid, char* pkgid, int len) { return MOCK_HOOK_P3(AulMock, aul_app_get_pkgid_bypid, pid, pkgid, len); } + +extern "C" int aul_widget_send_status_to_service(const char* class_id, + const char *instance_id, const char *sender_pkgid, int status) { + return MOCK_HOOK_P4(AulMock, aul_widget_send_status_to_service, + class_id, instance_id, sender_pkgid, status); +} + +extern "C" int aul_widget_send_status_to_viewer(const char* class_id, + const char *instance_id, const char *viewer_endpoint, + int status, int err, bundle *extra) { + return MOCK_HOOK_P6(AulMock, aul_widget_send_status_to_viewer, + class_id, instance_id, viewer_endpoint, status, err, extra); +} + +extern "C" int aul_notify_exit(void) { + return MOCK_HOOK_P0(AulMock, aul_notify_exit); +} + +extern "C" int aul_widget_write_log(const char* tag, const char* format, ...) { + return 0; +} + +extern "C" int aul_widget_instance_del(const char* widget_id, + const char* instance_id) { + return 0; +} + +extern "C" int aul_status_update(int status) { + return 0; +} diff --git a/test/unit_tests/mock/aul_mock.h b/test/unit_tests/mock/aul_mock.h index 359db71..ef0f1e4 100644 --- a/test/unit_tests/mock/aul_mock.h +++ b/test/unit_tests/mock/aul_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ #define UNIT_TESTS_MOCK_AUL_MOCK_H_ #include -#include +#include #include "mock/module_mock.h" @@ -26,7 +26,13 @@ class AulMock : public virtual ModuleMock { public: virtual ~AulMock() {} + MOCK_METHOD3(aul_app_get_appid_bypid, int (int , char *, int)); MOCK_METHOD3(aul_app_get_pkgid_bypid, int (int , char *, int)); + MOCK_METHOD4(aul_widget_send_status_to_service, int (const char*, + const char*, const char*, int)); + MOCK_METHOD6(aul_widget_send_status_to_viewer, int (const char*, + const char*, const char*, int, int, bundle*)); + MOCK_METHOD0(aul_notify_exit, int ()); }; #endif // UNIT_TESTS_MOCK_AUL_MOCK_H_ diff --git a/test/unit_tests/mock/elm_mock.cc b/test/unit_tests/mock/elm_mock.cc index 05bf369..632e754 100644 --- a/test/unit_tests/mock/elm_mock.cc +++ b/test/unit_tests/mock/elm_mock.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,25 +22,28 @@ #include "unit_tests/mock/test_fixture.h" -extern "C" Evas_Object * elm_win_add(Evas_Object *parent, - const char *name, Elm_Win_Type type) { +extern "C" Evas_Object* elm_win_add(Evas_Object* parent, + const char* name, Elm_Win_Type type) { return MOCK_HOOK_P3(ElmMock, elm_win_add, parent, name, type); } extern "C" void elm_win_wm_rotation_preferred_rotation_set( - Evas_Object *obj, int rotation) { + Evas_Object* obj, int rotation) { return MOCK_HOOK_P2( ElmMock, elm_win_wm_rotation_preferred_rotation_set, obj, rotation); } -extern "C" void elm_win_wm_rotation_available_rotations_set(Elm_Win *obj, - const int *rotations, unsigned int count) { +extern "C" void elm_win_wm_rotation_available_rotations_set(Elm_Win* obj, + const int* rotations, unsigned int count) { return MOCK_HOOK_P3( ElmMock, elm_win_wm_rotation_available_rotations_set, obj, rotations, count); } -extern "C" int elm_win_aux_hint_add(Evas_Object *obj, - const char *hint, const char *val) { +extern "C" int elm_win_aux_hint_add(Evas_Object* obj, + const char* hint, const char* val) { return MOCK_HOOK_P3(ElmMock, elm_win_aux_hint_add, obj, hint, val); } + +extern "C" void elm_exit(void) { +} diff --git a/test/unit_tests/mock/widget_service_mock.cc b/test/unit_tests/mock/widget_service_mock.cc new file mode 100644 index 0000000..36803b4 --- /dev/null +++ b/test/unit_tests/mock/widget_service_mock.cc @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * 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 "unit_tests/mock/widget_service_mock.h" + +#include + +#include "unit_tests/mock/mock_hook.h" +#include "unit_tests/mock/test_fixture.h" + +extern "C" int widget_instance_convert_event_to_lifecycle_status(int event) { + return MOCK_HOOK_P1(WidgetServiceMock, + widget_instance_convert_event_to_lifecycle_status, event); +} diff --git a/test/unit_tests/mock/widget_service_mock.h b/test/unit_tests/mock/widget_service_mock.h new file mode 100644 index 0000000..477777f --- /dev/null +++ b/test/unit_tests/mock/widget_service_mock.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef UNIT_TESTS_MOCK_WIDGET_SERVICE_MOCK_H_ +#define UNIT_TESTS_MOCK_WIDGET_SERVICE_MOCK_H_ + +#include + +#include "mock/module_mock.h" + +class WidgetServiceMock : public virtual ModuleMock { + public: + virtual ~WidgetServiceMock() {} + + MOCK_METHOD1(widget_instance_convert_event_to_lifecycle_status, int (int)); +}; + +#endif // UNIT_TESTS_MOCK_WIDGET_SERVICE_MOCK_H_ + diff --git a/test/unit_tests/test_widget_app.cc b/test/unit_tests/test_widget_app.cc index 3b3d2dc..7c73261 100644 --- a/test/unit_tests/test_widget_app.cc +++ b/test/unit_tests/test_widget_app.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,25 +14,26 @@ * limitations under the License. */ -#include -#include -#include #include #include +#include +#include +#include #include #include -#include "widget_app.h" -#include "widget_app_efl.h" -#include "unit_tests/mock/gio_mock.h" -#include "unit_tests/mock/ecore_wl2_mock.h" -#include "unit_tests/mock/system_info_mock.h" -#include "unit_tests/mock/appcore_multiwindow_base_mock.h" +#include "include/widget_app.h" +#include "include/widget_app_efl.h" #include "unit_tests/mock/app_common_mock.h" -#include "unit_tests/mock/elm_mock.h" +#include "unit_tests/mock/appcore_multiwindow_base_mock.h" #include "unit_tests/mock/aul_mock.h" +#include "unit_tests/mock/ecore_wl2_mock.h" +#include "unit_tests/mock/elm_mock.h" +#include "unit_tests/mock/gio_mock.h" +#include "unit_tests/mock/system_info_mock.h" #include "unit_tests/mock/test_fixture.h" +#include "unit_tests/mock/widget_service_mock.h" using ::testing::_; using ::testing::DoAll; @@ -40,41 +41,7 @@ using ::testing::Return; using ::testing::SetArgPointee; using ::testing::Invoke; -typedef struct _widget_base_instance_data { - bundle* args; - char* id; - char* content; - void* tag; - double period; - guint periodic_timer; - bool pending_update; - char* pending_content; - void* user_data; -} widget_base_instance_data; - -struct _widget_context { - int context; -}; - -class Mocks : public ::testing::NiceMock, - public ::testing::NiceMock, - public ::testing::NiceMock, - public ::testing::NiceMock, - public ::testing::NiceMock, - public ::testing::NiceMock, - public ::testing::NiceMock {}; - -class WidgetAppTest : public TestFixture { - public: - WidgetAppTest() : TestFixture(std::make_unique()) {} - virtual ~WidgetAppTest() {} - - virtual void SetUp() { - } - - virtual void TearDown() { - } -}; +namespace { int __instance_create_cb(widget_context_h context, bundle* content, int w, int h, void* user_data) { @@ -104,10 +71,6 @@ int __instance_update_cb(widget_context_h context, return 0; } -widget_class_h __app_create_cb(void* user_data) { - return nullptr; -} - void __app_terminate_cb(void* user_data) { } @@ -116,187 +79,178 @@ int __app_get_id_fake(char** id) { return 0; } -int __aul_app_get_pkgid_bypid_fake(int pid, char* pkgid, int len) { - snprintf(pkgid, 10, "%s", "test"); +int __aul_app_get_appid_bypid_fake(int pid, char* appid, int len) { + snprintf(appid, len, "%s", "test"); return 0; } -struct instance_data { - Evas_Object* win; - guint iconify_timer; - bool is_iconified; -}; - -void* __appcore_multiwindow_base_instance_get_extra_fake( - appcore_multiwindow_base_instance_h handle) { - widget_base_instance_data* data = (widget_base_instance_data*) - calloc(1, sizeof(widget_base_instance_data)); - data->args = bundle_create(); - bundle_add_str(data->args, "__AUL_WIDGET_ID__", "test"); - bundle_add_str(data->args, "__WIDGET_OP__", "optest"); - bundle_add_str(data->args, "__WIDGET_WIDTH__", "320"); - bundle_add_str(data->args, "__WIDGET_HEIGHT__", "320"); - data->pending_content = strdup("test"); - data->content = strdup("test"); - data->id = strdup("id"); - data->user_data = calloc(1, sizeof (struct instance_data)); - - return data; -} - -const char* __appcore_multiwindow_base_instance_get_id_fake( - appcore_multiwindow_base_instance_h handle) { - return strdup("test"); +int __aul_app_get_pkgid_bypid_fake(int pid, char* pkgid, int len) { + snprintf(pkgid, len, "%s", "test"); + return 0; } -const char* __appcore_multiwindow_base_instance_get_class_id_fake( - appcore_multiwindow_base_instance_h context) { - return strdup("test"); +void __app_event_cb(app_event_info_h event_info, void *user_data) { } -appcore_multiwindow_base_class __cls; -void __appcore_multiwindow_base_class_add_fake( - appcore_multiwindow_base_class cls) { - __cls = cls; - cls.create(nullptr, nullptr); - cls.terminate(nullptr, nullptr); - cls.pause((appcore_multiwindow_base_instance_h) - calloc(1, sizeof(char)), nullptr); - cls.resume((appcore_multiwindow_base_instance_h) - calloc(1, sizeof(char)), nullptr); +bool __widget_context_cb(widget_context_h context, void *user_data) { + return true; } -int __appcore_multiwindow_base_init_fake(appcore_multiwindow_base_ops ops, - int argc, char** argv, void* data) { - tizen_base::Bundle b; - - b.Add("__WIDGET_WIDTH__", "320"); - b.Add("__WIDGET_HEIGHT__", "320"); - b.Add("__AUL_WIDGET_INSTANCE_ID__", "instance_id"); - b.Add("__AUL_WIDGET_ID__", "test"); - b.Add("__WIDGET_OP__", "create"); - ops.base.control(b.GetHandle(), nullptr); - - b.Delete("__WIDGET_OP__"); - b.Add("__WIDGET_OP__", "resize"); - ops.base.control(b.GetHandle(), nullptr); +} // namespace - b.Delete("__WIDGET_OP__"); - b.Add("__WIDGET_OP__", "update"); - ops.base.control(b.GetHandle(), nullptr); - - b.Delete("__WIDGET_OP__"); - b.Add("__WIDGET_OP__", "destroy"); - ops.base.control(b.GetHandle(), nullptr); - - b.Delete("__WIDGET_OP__"); - b.Add("__WIDGET_OP__", "resume"); - ops.base.control(b.GetHandle(), nullptr); - - b.Delete("__WIDGET_OP__"); - b.Add("__WIDGET_OP__", "pause"); - ops.base.control(b.GetHandle(), nullptr); - - b.Delete("__WIDGET_OP__"); - b.Add("__WIDGET_OP__", "terminate"); - ops.base.control(b.GetHandle(), nullptr); - - b.Delete("__WIDGET_OP__"); - b.Add("__WIDGET_OP__", "period"); - ops.base.control(b.GetHandle(), nullptr); +class Mocks : public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock {}; - ops.base.create(nullptr); - ops.base.terminate(nullptr); +class WidgetAppTest : public TestFixture { + public: + WidgetAppTest() : TestFixture(std::make_unique()) {} + virtual ~WidgetAppTest() {} - return 0; -} + virtual void SetUp() { + } -TEST_F(WidgetAppTest, widget_app_main) { - tizen_base::Bundle b; - b.Add("__AUL_WIDGET_VIEWER__", "test"); - int ret = bundle_add_str(b.GetHandle(), "KEY", "VALUE"); - ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + virtual void TearDown() { + } - char** argv = nullptr; - int argc = bundle_export_to_argv(b.GetHandle(), &argv); - ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); - ASSERT_NE(argv, nullptr); - ASSERT_NE(argc, 0); + void PrepareTest(widget_app_create_cb created_cb, void* data) { + tizen_base::Bundle b; + b.Add("__AUL_WIDGET_VIEWER__", "test"); + int ret = bundle_add_str(b.GetHandle(), "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char** argv = nullptr; + int argc = bundle_export_to_argv(b.GetHandle(), &argv); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(argv, nullptr); + ASSERT_NE(argc, 0); + + widget_app_lifecycle_callback_s callback; + callback.create = created_cb; + callback.terminate = __app_terminate_cb; + + EXPECT_CALL(GetMock(), + system_info_get_platform_bool(_, _)). + WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(0))); + + EXPECT_CALL(GetMock(), + aul_app_get_appid_bypid(_, _, _)). + WillOnce(Invoke(__aul_app_get_appid_bypid_fake)); + EXPECT_CALL(GetMock(), + aul_app_get_pkgid_bypid(_, _, _)). + WillOnce(Invoke(__aul_app_get_pkgid_bypid_fake)); + EXPECT_CALL(GetMock(), + aul_widget_send_status_to_service(_, _, _, _)). + WillRepeatedly(Return(0)); + EXPECT_CALL(GetMock(), + aul_widget_send_status_to_viewer(_, _, _, _, _, _)). + WillRepeatedly(Return(0)); + EXPECT_CALL(GetMock(), + widget_instance_convert_event_to_lifecycle_status(_)). + WillRepeatedly(Return(0)); + + EXPECT_CALL(GetMock(), + app_get_id(_)).WillRepeatedly(Invoke(__app_get_id_fake)); + + EXPECT_CALL(GetMock(), + Run(_, _)).WillOnce(Invoke(this, &WidgetAppTest::__run_fake)); + + ret = widget_app_main(argc, argv, &callback, data); + bundle_free_exported_argv(argc, &argv); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + } - widget_app_lifecycle_callback_s callback; - callback.create = __app_create_cb; - callback.terminate = __app_terminate_cb; + void PrepareContext(widget_instance_create_cb created_cb) { + PrepareTest([](void* user_data) -> widget_class_h { + widget_instance_lifecycle_callback_s lifecycle; + lifecycle.create = reinterpret_cast(user_data); + lifecycle.destroy = __instance_destroy_cb; + lifecycle.pause = __instance_pause_cb; + lifecycle.resume = __instance_resume_cb; + lifecycle.resize = __instance_resize_cb; + lifecycle.update = __instance_update_cb; + widget_class_h cls = widget_app_class_create(lifecycle, nullptr); + EXPECT_NE(cls, nullptr); + return cls; + }, reinterpret_cast(created_cb)); + } - EXPECT_CALL(GetMock(), ecore_wl2_display_disconnect(_)). - Times(1); + void __run_fake(int argc, char** argv) { + tizen_base::Bundle b; + auto* p = GetMock().real_; - EXPECT_CALL(GetMock(), ecore_wl2_shutdown()). - Times(1); + p->OnCreate(); - EXPECT_CALL(GetMock(), - system_info_get_platform_bool(_, _)). - WillOnce(DoAll( - SetArgPointee<1>(true), - Return(0))); + b.Add("__WIDGET_WIDTH__", "320"); + b.Add("__WIDGET_HEIGHT__", "320"); + b.Add("__AUL_WIDGET_INSTANCE_ID__", "instance_id"); + b.Add("__AUL_WIDGET_ID__", "test"); + b.Add("__WIDGET_OP__", "create"); + p->OnControl(b); - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_init(_, _, _, _)). - WillOnce(Invoke(__appcore_multiwindow_base_init_fake)); + b.Delete("__WIDGET_OP__"); + b.Add("__WIDGET_OP__", "resize"); + p->OnControl(b); - EXPECT_CALL(GetMock(), - aul_app_get_pkgid_bypid(_, _, _)). - WillOnce(Invoke(__aul_app_get_pkgid_bypid_fake)); + b.Delete("__WIDGET_OP__"); + b.Add("__WIDGET_OP__", "update"); + p->OnControl(b); - EXPECT_CALL(GetMock(), app_get_id(_)). - WillOnce(Invoke(__app_get_id_fake)); + b.Delete("__WIDGET_OP__"); + b.Add("__WIDGET_OP__", "destroy"); + p->OnControl(b); - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_find(_)). - WillRepeatedly( - Return( - (appcore_multiwindow_base_instance_h)calloc(1, sizeof(char)))); + b.Delete("__WIDGET_OP__"); + b.Add("__WIDGET_OP__", "resume"); + p->OnControl(b); - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_class(_)). - WillRepeatedly( - Return(&__cls)); + b.Delete("__WIDGET_OP__"); + b.Add("__WIDGET_OP__", "pause"); + p->OnControl(b); - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_extra(_)). - WillRepeatedly( - Invoke(__appcore_multiwindow_base_instance_get_extra_fake)); + b.Delete("__WIDGET_OP__"); + b.Add("__WIDGET_OP__", "terminate"); + p->OnControl(b); - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_exit(_)).Times(2); + b.Delete("__WIDGET_OP__"); + b.Add("__WIDGET_OP__", "period"); + p->OnControl(b); - ret = widget_app_main(argc, argv, &callback, nullptr); - bundle_free_exported_argv(argc, &argv); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); -} + p->OnTerminate(); + } +}; -TEST_F(WidgetAppTest, widget_app_exit) { +TEST_F(WidgetAppTest, widget_app_exit_n) { int ret = widget_app_exit(); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); -} - -TEST_F(WidgetAppTest, widget_app_terminate_context) { - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); - int ret = widget_app_terminate_context(context); - free(context); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); -} - -bool __widget_context_cb(widget_context_h context, void *user_data) { - return true; + EXPECT_NE(ret, WIDGET_ERROR_NONE); } -TEST_F(WidgetAppTest, widget_app_foreach_context) { - int ret = widget_app_foreach_context(__widget_context_cb, nullptr); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); +TEST_F(WidgetAppTest, widget_app_exit) { + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + EXPECT_CALL(GetMock(), + aul_notify_exit()).WillRepeatedly(Return(0)); + int ret = widget_app_exit(); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + return 0; + }); } -void __app_event_cb(app_event_info_h event_info, void *user_data) { +TEST_F(WidgetAppTest, widget_app_main) { + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + EXPECT_CALL(GetMock(), + aul_notify_exit()).WillRepeatedly(Return(0)); + widget_app_exit(); + return 0; + }); } TEST_F(WidgetAppTest, widget_app_add_event_handler) { @@ -308,7 +262,7 @@ TEST_F(WidgetAppTest, widget_app_add_event_handler) { Return(0))); int ret = widget_app_add_event_handler(&handle, APP_EVENT_LOW_MEMORY, __app_event_cb, nullptr); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); } TEST_F(WidgetAppTest, widget_app_remove_event_handler) { @@ -321,195 +275,158 @@ TEST_F(WidgetAppTest, widget_app_remove_event_handler) { int ret = widget_app_add_event_handler(&handle, APP_EVENT_LOW_MEMORY, __app_event_cb, nullptr); ret = widget_app_remove_event_handler(handle); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); } -TEST_F(WidgetAppTest, widget_app_get_id) { - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_id(_)). - WillOnce(Return("test")); - - const char *id = widget_app_get_id(context); - free(context); - EXPECT_STREQ(id, "test"); +TEST_F(WidgetAppTest, widget_app_terminate_context) { + PrepareContext([](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + int ret = widget_app_terminate_context(context); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + return 0; + }); } -TEST_F(WidgetAppTest, widget_app_class_create) { - widget_instance_lifecycle_callback_s lifecycle; +TEST_F(WidgetAppTest, widget_app_foreach_context) { + PrepareTest([](void* user_data) -> widget_class_h { + widget_instance_lifecycle_callback_s lifecycle; + lifecycle.create = __instance_create_cb; + lifecycle.destroy = __instance_destroy_cb; + lifecycle.pause = __instance_pause_cb; + lifecycle.resume = __instance_resume_cb; + lifecycle.resize = __instance_resize_cb; + lifecycle.update = __instance_update_cb; - lifecycle.create = __instance_create_cb; - lifecycle.destroy = __instance_destroy_cb; - lifecycle.pause = __instance_pause_cb; - lifecycle.resume = __instance_resume_cb; - lifecycle.resize = __instance_resize_cb; - lifecycle.update = __instance_update_cb; + widget_class_h cls = widget_app_class_create(lifecycle, nullptr); + EXPECT_NE(cls, nullptr); - EXPECT_CALL(GetMock(), app_get_id(_)). - WillOnce(Invoke(__app_get_id_fake)); + int ret = widget_app_foreach_context(__widget_context_cb, nullptr); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); - widget_class_h cls = widget_app_class_create(lifecycle, nullptr); - EXPECT_NE(nullptr, cls); + return cls; + }, nullptr); } -TEST_F(WidgetAppTest, widget_app_context_set_tag) { - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); +TEST_F(WidgetAppTest, widget_app_get_id) { + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + const char *id = widget_app_get_id(context); + EXPECT_STREQ(id, "instance_id"); + return 0; + }); +} - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_extra(_)). - WillOnce(Invoke(__appcore_multiwindow_base_instance_get_extra_fake)); +TEST_F(WidgetAppTest, widget_app_class_create) { + PrepareContext(__instance_create_cb); +} - int ret = widget_app_context_set_tag(context, (void*)"test"); - free(context); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); +TEST_F(WidgetAppTest, widget_app_context_set_tag) { + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + int ret = widget_app_context_set_tag(context, + reinterpret_cast(const_cast("test"))); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + return 0; + }); } TEST_F(WidgetAppTest, widget_app_context_get_tag) { - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_extra(_)). - WillOnce(Invoke(__appcore_multiwindow_base_instance_get_extra_fake)); - - void* tag; - int ret = widget_app_context_get_tag(context, &tag); - free(context); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + int ret = widget_app_context_set_tag(context, + reinterpret_cast(const_cast("test"))); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + void* tag = nullptr; + ret = widget_app_context_get_tag(context, &tag); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + return 0; + }); } TEST_F(WidgetAppTest, widget_app_context_set_content_info) { - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_extra(_)). - WillOnce(Invoke(__appcore_multiwindow_base_instance_get_extra_fake)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_id(_)). - WillOnce(Invoke(__appcore_multiwindow_base_instance_get_id_fake)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_class_id(_)). - WillOnce(Invoke(__appcore_multiwindow_base_instance_get_class_id_fake)); - - bundle* content_info = bundle_create(); - int ret = widget_app_context_set_content_info(context, content_info); - free(context); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + bundle* content_info = bundle_create(); + EXPECT_NE(content_info, nullptr); + int ret = widget_app_context_set_content_info(context, content_info); + bundle_free(content_info); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + return 0; + }); } TEST_F(WidgetAppTest, widget_app_context_set_title) { - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_extra(_)). - WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_extra_fake)); - - int ret = widget_app_context_set_title(context, "title"); - free(context); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + int ret = widget_app_context_set_title(context, "title"); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + return 0; + }); } TEST_F(WidgetAppTest, widget_app_class_add) { - widget_instance_lifecycle_callback_s lifecycle; - lifecycle.create = __instance_create_cb; - lifecycle.destroy = __instance_destroy_cb; - lifecycle.pause = __instance_pause_cb; - lifecycle.resume = __instance_resume_cb; - lifecycle.resize = __instance_resize_cb; - lifecycle.update = __instance_update_cb; - - widget_class_h cls = widget_app_class_add( - nullptr, "test", lifecycle, nullptr); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_class_add(_)). - WillOnce(Invoke(__appcore_multiwindow_base_class_add_fake)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_extra(_)). - WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_extra_fake)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_class_id(_)). - WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_class_id_fake)); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_drop(_)). - Times(1); - - cls = widget_app_class_add( - nullptr, "test", lifecycle, nullptr); - EXPECT_NE(nullptr, cls); - - tizen_base::Bundle b; - b.Add("__AUL_WIDGET_VIEWER__", "test"); - int ret = bundle_add_str(b.GetHandle(), "KEY", "VALUE"); - ASSERT_EQ(ret, BUNDLE_ERROR_NONE); - - char** argv = nullptr; - int argc = bundle_export_to_argv(b.GetHandle(), &argv); - ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); - ASSERT_NE(argv, nullptr); - ASSERT_NE(argc, 0); - - widget_app_lifecycle_callback_s callback; - callback.create = __app_create_cb; - callback.terminate = __app_terminate_cb; - - ret = widget_app_main(argc, argv, &callback, nullptr); - bundle_free_exported_argv(argc, &argv); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); + PrepareTest( + [](void* user_data) -> widget_class_h { + widget_instance_lifecycle_callback_s lifecycle; + lifecycle.create = __instance_create_cb; + lifecycle.destroy = __instance_destroy_cb; + lifecycle.pause = __instance_pause_cb; + lifecycle.resume = __instance_resume_cb; + lifecycle.resize = __instance_resize_cb; + lifecycle.update = __instance_update_cb; + + widget_class_h cls = widget_app_class_add( + nullptr, "test", lifecycle, nullptr); + EXPECT_NE(cls, nullptr); + return cls; + }, nullptr); } TEST_F(WidgetAppTest, widget_app_get_elm_win_negative) { - Evas_Object* win; - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); - int ret = widget_app_get_elm_win(context, &win); - free(context); - EXPECT_EQ(WIDGET_ERROR_FAULT, ret); + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + Evas_Object* win = nullptr; + int ret = widget_app_get_elm_win(context, &win); + EXPECT_EQ(ret, WIDGET_ERROR_FAULT); + return 0; + }); } TEST_F(WidgetAppTest, widget_app_get_elm_win) { - EXPECT_CALL(GetMock(), - elm_win_add(_, _, _)). - WillOnce(Return((Evas_Object*)calloc(1, sizeof(char)))); - - EXPECT_CALL(GetMock(), - ecore_evas_wayland2_window_get(_)). - WillOnce(Return((Ecore_Wl2_Window*)calloc(1, sizeof(char)))); - - EXPECT_CALL(GetMock(), - elm_win_aux_hint_add(_, _, _)). - WillOnce(Return(0)); - - EXPECT_CALL(GetMock(), - ecore_wl2_window_surface_get(_)). - WillOnce(Return(nullptr)); - - EXPECT_CALL(GetMock(), - evas_object_event_callback_add(_, _, _, _)). - Times(1); - - EXPECT_CALL(GetMock(), - evas_object_data_set(_, _, _)). - Times(1); - - EXPECT_CALL(GetMock(), - appcore_multiwindow_base_instance_get_extra(_)). - WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_extra_fake)); - - Evas_Object* win; - widget_context_h context = - (widget_context_h)calloc(1, sizeof(struct _widget_context)); - int ret = widget_app_get_elm_win(context, &win); - free(context); - EXPECT_EQ(WIDGET_ERROR_NONE, ret); + PrepareContext( + [](widget_context_h context, bundle* content, + int w, int h, void* user_data) -> int { + EXPECT_CALL(GetMock(), + elm_win_add(_, _, _)). + WillOnce(Return(reinterpret_cast( + calloc(1, sizeof(char))))); + + EXPECT_CALL(GetMock(), + ecore_evas_wayland2_window_get(_)). + WillOnce(Return(reinterpret_cast( + calloc(1, sizeof(char))))); + + EXPECT_CALL(GetMock(), + elm_win_aux_hint_add(_, _, _)).WillOnce(Return(0)); + + EXPECT_CALL(GetMock(), + ecore_wl2_window_surface_get(_)).WillOnce(Return(nullptr)); + + EXPECT_CALL(GetMock(), + evas_object_event_callback_add(_, _, _, _)).Times(1); + + EXPECT_CALL(GetMock(), + evas_object_data_set(_, _, _)).Times(1); + + Evas_Object* win = nullptr; + int ret = widget_app_get_elm_win(context, &win); + EXPECT_EQ(ret, WIDGET_ERROR_NONE); + return -1; + }); } diff --git a/test/unit_tests/test_widget_app_cpp.cc b/test/unit_tests/test_widget_app_cpp.cc index b41c249..8d5fca5 100644 --- a/test/unit_tests/test_widget_app_cpp.cc +++ b/test/unit_tests/test_widget_app_cpp.cc @@ -15,9 +15,41 @@ */ #include +#include + #include -namespace { +#include "include/widget_app.h" +#include "include/widget_app_efl.h" +#include "unit_tests/mock/app_common_mock.h" +#include "unit_tests/mock/appcore_multiwindow_base_mock.h" +#include "unit_tests/mock/aul_mock.h" +#include "unit_tests/mock/ecore_wl2_mock.h" +#include "unit_tests/mock/elm_mock.h" +#include "unit_tests/mock/gio_mock.h" +#include "unit_tests/mock/system_info_mock.h" +#include "unit_tests/mock/test_fixture.h" +#include "unit_tests/mock/widget_service_mock.h" + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Invoke; +using ::testing::Return; +using ::testing::SetArgPointee; + +class Mocks : public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock, + public ::testing::NiceMock {}; + +class WidgetAppCppTest : public TestFixture { + public: + WidgetAppCppTest() : TestFixture(std::make_unique()) {} +}; class WidgetApp : public tizen_appfw::WidgetAppBase { public: @@ -30,7 +62,7 @@ class WidgetApp : public tizen_appfw::WidgetAppBase { } }; - Instance(widget_context_h h) : InstanceBase(h) {} + explicit Instance(widget_context_h h) : InstanceBase(h) {} void OnCreate(const tizen_base::Bundle& content, int w, int h) override {} void OnDestroy(DestroyType reason, tizen_base::Bundle* content) override {} void OnPause() override {} @@ -44,13 +76,15 @@ class WidgetApp : public tizen_appfw::WidgetAppBase { void OnTerminate() override {} }; -} // namespace +TEST_F(WidgetAppCppTest, Run_InvalidParameter) { + EXPECT_CALL(GetMock(), + system_info_get_platform_bool(_, _)). + WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(0))); -TEST(WidgetAppCppTest, Run_InvalidParameter) { WidgetApp app; std::unique_ptr factory( new WidgetApp::Instance::Factory()); int ret = app.Run(0, nullptr, std::move(factory)); EXPECT_EQ(ret, APP_ERROR_INVALID_PARAMETER); -} \ No newline at end of file +}