diff options
Diffstat (limited to 'dali/internal')
17 files changed, 2680 insertions, 1370 deletions
diff --git a/dali/internal/adaptor/common/framework.h b/dali/internal/adaptor/common/framework.h index ad89efec3..c47bd14a5 100644 --- a/dali/internal/adaptor/common/framework.h +++ b/dali/internal/adaptor/common/framework.h @@ -331,6 +331,26 @@ public: mArgv = argv; } + Observer& GetObserver() + { + return mObserver; + } + + int* GetArgc() + { + return mArgc; + } + + char*** GetArgv() + { + return mArgv; + } + + TaskObserver& GetTaskObserver() + { + return mTaskObserver; + } + private: /** * Called if the application is aborted. diff --git a/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp b/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp index 50a1a532e..8a24537d1 100644 --- a/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp +++ b/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp @@ -18,40 +18,20 @@ #include <dali/internal/adaptor/tizen-wayland/framework-tizen.h> // EXTERNAL INCLUDES -#include <app_common.h> -#include <app_control_internal.h> -#include <bundle.h> -#include <bundle_internal.h> +#include <dlfcn.h> #include <dlog.h> -#include <glib.h> #include <system_info.h> #include <system_settings.h> -#include <widget_base.h> -#include <app_core_ui_base.hh> -#include <app_event_internal.hh> +#include <tizen.h> #ifdef UI_THREAD_AVAILABLE #include <app_core_ui_thread_base.hh> #endif -// CONDITIONAL INCLUDES -#ifdef APPCORE_WATCH_AVAILABLE -#include <appcore-watch/watch_app.h> -#endif -#ifdef DALI_ELDBUS_AVAILABLE -#include <Eldbus.h> -#endif // DALI_ELDBUS_AVAILABLE - -#ifdef COMPONENT_APPLICATION_SUPPORT -#include <component_based_app_base.h> -#endif - +// INTERNAL INCLUDES #include <dali/integration-api/debug.h> #include <dali/integration-api/trace.h> -// INTERNAL INCLUDES -#include <dali/internal/system/linux/dali-ecore.h> - using namespace tizen_cpp; namespace Dali @@ -62,758 +42,154 @@ namespace Adaptor { namespace { +constexpr char const* const kApplicationNamePrefix = "libdali2-adaptor-application-"; +constexpr char const* const kApplicationNamePostfix = ".so"; + +std::string MakePluginName(const char* appModelName) +{ + std::stringstream fullName; + fullName << kApplicationNamePrefix << appModelName << kApplicationNamePostfix; + return fullName.str(); +} + #if defined(DEBUG_ENABLED) Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS"); #endif DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_FRAMEWORK, true); -bool IsWidgetFeatureEnabled() -{ - static bool feature = false; - static bool retrieved = false; - int ret; - - if(retrieved == true) - { - return feature; - } - - ret = system_info_get_platform_bool("http://tizen.org/feature/shell.appwidget", &feature); - if(ret != SYSTEM_INFO_ERROR_NONE) - { - DALI_LOG_ERROR("failed to get system info"); - return false; - } - - retrieved = true; - return feature; -} - // Note : tizen appfw don't consider zero-arguments case. // If framework argc & argv is nullptr, We should add at least one argv. const int gTizenDummyArgc = 1; const char* gTizenDummyArgv[1] = {"dali-tizen-app"}; - } // anonymous namespace -namespace AppCore -{ -typedef enum -{ - LOW_MEMORY, //< The low memory event - LOW_BATTERY, //< The low battery event - LANGUAGE_CHANGED, //< The system language changed event - DEVICE_ORIENTATION_CHANGED, //< The device orientation changed event - REGION_FORMAT_CHANGED, //< The region format changed event - SUSPENDED_STATE_CHANGED, //< The suspended state changed event of the application - UPDATE_REQUESTED, //< The update requested event. This event can occur when an app needs to be updated. It is dependent on target devices. -} AppEventType; - -static int AppEventConverter[APPCORE_BASE_EVENT_MAX] = - { - [LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY, - [LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY, - [LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE, - [DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED, - [REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE, - [SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE, -}; - -struct AppEventInfo -{ - AppEventType type; - void* value; -}; - -typedef struct AppEventInfo* AppEventInfoPtr; - -typedef void (*AppEventCallback)(AppEventInfoPtr eventInfo, void* userData); - -struct AppEventHandler -{ - AppEventType type; - AppEventCallback cb; - void* data; - void* raw; -}; - -typedef struct AppEventHandler* AppEventHandlerPtr; - -int EventCallback(void* event, void* data) -{ - AppEventHandlerPtr handler = static_cast<AppEventHandlerPtr>(data); - - struct AppEventInfo appEvent; - - appEvent.type = handler->type; - appEvent.value = event; - - if(handler->cb) - handler->cb(&appEvent, handler->data); - - return 0; -} - -int AppAddEventHandler(AppEventHandlerPtr* eventHandler, AppEventType eventType, AppEventCallback callback, void* userData) -{ - AppEventHandlerPtr handler; - - handler = static_cast<AppEventHandlerPtr>(calloc(1, sizeof(struct AppEventHandler))); - if(!handler) - { - DALI_LOG_ERROR("failed to create handler"); - return TIZEN_ERROR_UNKNOWN; - } - else - { - handler->type = eventType; - handler->cb = callback; - handler->data = userData; - handler->raw = appcore_base_add_event(static_cast<appcore_base_event>(AppEventConverter[static_cast<int>(eventType)]), EventCallback, handler); - - *eventHandler = handler; - - return TIZEN_ERROR_NONE; - } -} - -DeviceStatus::Memory::Status GetMemoryStatus(app_event_low_memory_status_e memoryStatus) -{ - switch(memoryStatus) - { - case APP_EVENT_LOW_MEMORY_SOFT_WARNING: // 0x02 - { - return Dali::DeviceStatus::Memory::Status::LOW; - } - case APP_EVENT_LOW_MEMORY_HARD_WARNING: // 0x04 - { - return Dali::DeviceStatus::Memory::Status::CRITICALLY_LOW; - } - default: // APP_EVENT_LOW_MEMORY_NORMAL 0x01 - { - return Dali::DeviceStatus::Memory::Status::NORMAL; - } - } -} - -DeviceStatus::Battery::Status GetBatteryStatus(app_event_low_battery_status_e batteryStatus) -{ - switch(batteryStatus) - { - case APP_EVENT_LOW_BATTERY_POWER_OFF: // 1 - { - return Dali::DeviceStatus::Battery::Status::POWER_OFF; - } - case APP_EVENT_LOW_BATTERY_CRITICAL_LOW: // 2 - { - return Dali::DeviceStatus::Battery::Status::CRITICALLY_LOW; - } - default: - { - return Dali::DeviceStatus::Battery::Status::NORMAL; - } - } -} - -DeviceStatus::Orientation::Status GetOrientationStatus(app_device_orientation_e orientationStatus) -{ - switch(orientationStatus) - { - case APP_DEVICE_ORIENTATION_0: - { - return Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; - } - case APP_DEVICE_ORIENTATION_90: - { - return Dali::DeviceStatus::Orientation::Status::ORIENTATION_90; - } - case APP_DEVICE_ORIENTATION_180: - { - return Dali::DeviceStatus::Orientation::Status::ORIENTATION_180; - } - case APP_DEVICE_ORIENTATION_270: - { - return Dali::DeviceStatus::Orientation::Status::ORIENTATION_270; - } - default: - { - return Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; - } - } -} - -} // namespace AppCore - /** * Impl to hide EFL data members */ struct FrameworkTizen::Impl { - class UiAppContext : public AppCoreUiBase + // Constructor + Impl(void* data, Type type, bool isUiThread) { - public: - class Task : public AppCoreTaskBase + mFramework = static_cast<FrameworkTizen*>(data); + mUiThread = isUiThread; +#ifndef APPCORE_WATCH_AVAILABLE + if(type == WATCH) { - public: - explicit Task(FrameworkTizen* framework) - : mFramework(framework), - mNewBatteryStatus(Dali::DeviceStatus::Battery::Status::NORMAL), - mNewMemoryStatus(Dali::DeviceStatus::Memory::NORMAL), - mNewDeviceOrientationStatus(Dali::DeviceStatus::Orientation::ORIENTATION_0) - { - } - - virtual ~Task() - { - } - - int OnCreate() override - { - // On the main thread, the log functions are not set. So print_log() is used directly. - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnCreate() emitted", __MODULE__, __func__, __LINE__); - mFramework->mTaskObserver.OnTaskInit(); - return AppCoreTaskBase::OnCreate(); - } - - int OnTerminate() override - { - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnTerminate() emitted", __MODULE__, __func__, __LINE__); - mFramework->mTaskObserver.OnTaskTerminate(); - return AppCoreTaskBase::OnTerminate(); - } - - int OnControl(tizen_base::Bundle b) override - { - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnControl() emitted", __MODULE__, __func__, __LINE__); - AppCoreTaskBase::OnControl(b); - - app_control_h appControl = nullptr; - - auto* bundleData = b.GetHandle(); - if(bundleData) - { - if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE) - { - print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle with Bundle", __MODULE__, __func__, __LINE__); - } - } - else - { - if(app_control_create(&appControl) != TIZEN_ERROR_NONE) - { - print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle", __MODULE__, __func__, __LINE__); - } - } - mFramework->mTaskObserver.OnTaskAppControl(appControl); - - app_control_destroy(appControl); - return 0; - } - - void OnUiEvent(AppCoreTaskBase::UiState state) override - { - // This event is emitted when the UI thread is paused or resumed. - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnUiEvent() emitted", __MODULE__, __func__, __LINE__); - - // Note: This isn't implemented. - AppCoreTaskBase::OnUiEvent(state); - } - - void OnLowMemory(AppCoreTaskBase::LowMemoryState state) override - { - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowMemory() emitted", __MODULE__, __func__, __LINE__); - - mNewMemoryStatus = AppCore::GetMemoryStatus(static_cast<app_event_low_memory_status_e>(state)); - - PostToUiThread( - [](gpointer userData) -> gboolean { - auto* task = static_cast<Task*>(userData); - auto* framework = static_cast<FrameworkTizen*>(task->mFramework); - framework->mObserver.OnMemoryLow(task->mNewMemoryStatus); - return G_SOURCE_REMOVE; - }); - mFramework->mTaskObserver.OnTaskMemoryLow(mNewMemoryStatus); - AppCoreTaskBase::OnLowMemory(state); - } - - void OnDeviceOrientationChanged(AppCoreTaskBase::DeviceOrientationState state) override - { - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnDeviceOrientationChanged() emitted, orientation :%d", __MODULE__, __func__, __LINE__, state); - - mNewDeviceOrientationStatus = AppCore::GetOrientationStatus(static_cast<app_device_orientation_e>(state)); - - PostToUiThread( - [](gpointer userData) -> gboolean { - auto* task = static_cast<Task*>(userData); - auto* framework = static_cast<FrameworkTizen*>(task->mFramework); - framework->mObserver.OnDeviceOrientationChanged(task->mNewDeviceOrientationStatus); - return G_SOURCE_REMOVE; - }); - - mFramework->mTaskObserver.OnTaskDeviceOrientationChanged(mNewDeviceOrientationStatus); - - AppCoreTaskBase::OnDeviceOrientationChanged(state); - } - void OnLowBattery(AppCoreTaskBase::LowBatteryState state) override - { - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowBattery() emitted", __MODULE__, __func__, __LINE__); - mNewBatteryStatus = AppCore::GetBatteryStatus(static_cast<app_event_low_battery_status_e>(state)); - - PostToUiThread( - [](gpointer userData) -> gboolean { - auto* task = static_cast<Task*>(userData); - auto* framework = static_cast<FrameworkTizen*>(task->mFramework); - framework->mObserver.OnBatteryLow(task->mNewBatteryStatus); - return G_SOURCE_REMOVE; - }); - mFramework->mTaskObserver.OnTaskBatteryLow(mNewBatteryStatus); - AppCoreTaskBase::OnLowBattery(state); - } - - void OnLangChanged(const std::string& lang) override - { - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted", __MODULE__, __func__, __LINE__); - mNewLanguage = lang; - mFramework->SetLanguage(mNewLanguage); - - PostToUiThread( - [](gpointer userData) -> gboolean { - auto* task = static_cast<Task*>(userData); - auto* framework = static_cast<FrameworkTizen*>(task->mFramework); - framework->mObserver.OnLanguageChanged(); - return G_SOURCE_REMOVE; - }); - - mFramework->mTaskObserver.OnTaskLanguageChanged(); - AppCoreTaskBase::OnLangChanged(lang); - } - - void OnRegionChanged(const std::string& region) override - { - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > nRegionChanged() emitted", __MODULE__, __func__, __LINE__); - mNewRegion = region; - mFramework->SetRegion(mNewRegion); - - PostToUiThread( - [](gpointer userData) -> gboolean { - auto* task = static_cast<Task*>(userData); - auto* framework = static_cast<FrameworkTizen*>(task->mFramework); - framework->mObserver.OnRegionChanged(); - return G_SOURCE_REMOVE; - }); - - mFramework->mTaskObserver.OnTaskRegionChanged(); - AppCoreTaskBase::OnRegionChanged(mNewRegion); - } - - private: - GMainContext* GetTizenGlibContext() - { - GMainContext* context; - const char* env = getenv("TIZEN_GLIB_CONTEXT"); - if(env) - { - context = (GMainContext*)strtoul(env, nullptr, 10); - } - else - { - context = nullptr; - } - - return context; - } - - void PostToUiThread(GSourceFunc func) - { - GSource* source = g_idle_source_new(); - g_source_set_callback(source, func, this, nullptr); - g_source_attach(source, GetTizenGlibContext()); - g_source_unref(source); - } - - private: - FrameworkTizen* mFramework; - std::string mNewLanguage; - std::string mNewRegion; - Dali::DeviceStatus::Battery::Status mNewBatteryStatus; - Dali::DeviceStatus::Memory::Status mNewMemoryStatus; - Dali::DeviceStatus::Orientation::Status mNewDeviceOrientationStatus; - }; + throw Dali::DaliException("", "Watch Application is not supported."); + } +#endif + mApplicationType = type; - explicit UiAppContext(unsigned int hint, FrameworkTizen* framework) - : AppCoreUiBase(hint), - mFramework(framework), - mUseUiThread(false) + std::string pluginName; + switch(mApplicationType) { - if(hint & AppCoreUiBase::HINT_DUAL_THREAD) - { - mUseUiThread = true; - } - - if(!mUseUiThread) + case NORMAL: { - mLanguageChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LANG_CHANGE, OnLanguageChanged, this); - AddEvent(mLanguageChanged); - - mDeviceOrientationChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, OnDeviceOrientationChanged, this); - AddEvent(mDeviceOrientationChanged); - - mRegionFormatChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::REGION_CHANGE, OnRegionFormatChanged, this); - AddEvent(mRegionFormatChanged); - - mLowMemory = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_MEMORY, OnLowMemory, this); - AddEvent(mLowMemory); - - mLowBattery = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_BATTERY, OnLowBattery, this); - AddEvent(mLowBattery); + pluginName = MakePluginName("normal"); + break; } - } - - virtual ~UiAppContext() - { - if(!mUseUiThread) + case WIDGET: { - RemoveEvent(mLowBattery); - RemoveEvent(mLowMemory); - RemoveEvent(mRegionFormatChanged); - RemoveEvent(mDeviceOrientationChanged); - RemoveEvent(mLanguageChanged); + pluginName = MakePluginName("widget"); + break; } - } - - std::unique_ptr<AppCoreTaskBase> CreateTask() override - { - return std::unique_ptr<AppCoreTaskBase>( - new Task(mFramework)); - } - - int OnCreate() override - { - AppCoreUiBase::OnCreate(); - mFramework->Create(); - return 0; - } - - int OnTerminate() override - { - AppCoreUiBase::OnTerminate(); - auto* observer = &mFramework->mObserver; - observer->OnTerminate(); - return 0; - } - - int OnPause() override - { - AppCoreUiBase::OnPause(); - auto* observer = &mFramework->mObserver; - observer->OnPause(); - return 0; - } - - int OnResume() override - { - AppCoreUiBase::OnResume(); - auto* observer = &mFramework->mObserver; - observer->OnResume(); - return 0; - } - - int OnControl(tizen_base::Bundle b) override - { - AppCoreUiBase::OnControl(b); - - app_control_h appControl = nullptr; - - auto* bundleData = b.GetHandle(); - if(bundleData) + case WATCH: { - if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE) - { - DALI_LOG_ERROR("Failed to create an app_control handle"); - return 0; - } + pluginName = MakePluginName("watch"); + break; } - else +#ifdef COMPONENT_APPLICATION_SUPPORT + case COMPONENT: { - if(app_control_create(&appControl) != TIZEN_ERROR_NONE) - { - DALI_LOG_ERROR("Failed to create an app_control handle"); - return 0; - } + pluginName = MakePluginName("component-based"); + break; } - - auto* observer = &mFramework->mObserver; - ProcessBundle(mFramework, bundleData); - observer->OnReset(); - observer->OnAppControl(appControl); - app_control_destroy(appControl); - return 0; - } - - void OnLoopInit(int argc, char** argv) override - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" - ecore_init(); - ecore_app_args_set(argc, (const char**)argv); -#pragma GCC diagnostic pop - -#ifdef DALI_ELDBUS_AVAILABLE - // Initialize ElDBus. - DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n"); - eldbus_init(); #endif - } - - void OnLoopFinish() override - { - ecore_shutdown(); - - if(getenv("AUL_LOADER_INIT")) + default: { - setenv("AUL_LOADER_INIT", "0", 1); - ecore_shutdown(); + DALI_LOG_ERROR("Invalid app type : %d\n", static_cast<int>(mApplicationType)); + pluginName = MakePluginName("normal"); } - -#ifdef DALI_ELDBUS_AVAILABLE - // Shutdown ELDBus. - DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n"); - eldbus_shutdown(); -#endif } - void OnLoopRun() override + mHandle = dlopen(pluginName.c_str(), RTLD_LAZY); + if(mHandle == nullptr) { - ecore_main_loop_begin(); + print_log(DLOG_INFO, "DALI", "error : %s", dlerror() ); + return; } - void OnLoopExit() override + createFunctionPtr = reinterpret_cast<CreateFunction>(dlsym(mHandle, "Create")); + if(createFunctionPtr == nullptr) { - ecore_main_loop_quit(); + DALI_LOG_ERROR("createFunctionPtr is null\n"); } - - private: - static void OnLanguageChanged(app_event_info_h event_info, void* user_data) + destroyFunctionPtr = reinterpret_cast<DestroyFunction>(dlsym(mHandle, "Destroy")); + if(destroyFunctionPtr == nullptr) { - auto* context = static_cast<UiAppContext*>(user_data); - auto* framework = context->mFramework; - Observer* observer = &framework->mObserver; - - char* lang = nullptr; - auto appEventReturn = app_event_get_language(event_info, &lang); - if(appEventReturn == APP_ERROR_NONE && lang) - { - framework->SetLanguage(std::string(lang)); - observer->OnLanguageChanged(); - free(lang); - } - else - { - DALI_LOG_ERROR("NULL pointer in Language changed event. Error code : %d\n", static_cast<int>(appEventReturn)); - } + DALI_LOG_ERROR("destroyFunctionPtr is null\n"); } - - static void OnRegionFormatChanged(app_event_info_h event_info, void* user_data) + appMainFunctionPtr = reinterpret_cast<AppMainFunction>(dlsym(mHandle, "AppMain")); + if(appMainFunctionPtr == nullptr) { - auto* context = static_cast<UiAppContext*>(user_data); - auto* framework = context->mFramework; - Observer* observer = &framework->mObserver; - - char* region = nullptr; - auto appEventReturn = app_event_get_region_format(event_info, ®ion); - if(appEventReturn == APP_ERROR_NONE && region) - { - framework->SetRegion(std::string(region)); - observer->OnRegionChanged(); - free(region); - } - else - { - DALI_LOG_ERROR("NULL pointer in Region changed event. Error code : %d\n", static_cast<int>(appEventReturn)); - } + DALI_LOG_ERROR("appMainFunctionPtr is null\n"); } - - static void OnLowBattery(app_event_info_h event_info, void* user_data) + appExitFunctionPtr = reinterpret_cast<AppExitFunction>(dlsym(mHandle, "AppExit")); + if(appExitFunctionPtr == nullptr) { - auto* context = static_cast<UiAppContext*>(user_data); - auto* framework = context->mFramework; - Observer* observer = &framework->mObserver; - - app_event_low_battery_status_e status; - auto appEventReturn = app_event_get_low_battery_status(event_info, &status); - if(appEventReturn == APP_ERROR_NONE) - { - Dali::DeviceStatus::Battery::Status result = AppCore::GetBatteryStatus(status); - observer->OnBatteryLow(result); - } - else - { - DALI_LOG_ERROR("Fail to get low battery status event. Error code : %d\n", static_cast<int>(appEventReturn)); - } + DALI_LOG_ERROR("appExitFunctionPtr is null\n"); } + } - static void OnLowMemory(app_event_info_h event_info, void* user_data) + ~Impl() + { + if(mHandle != NULL) { - auto* context = static_cast<UiAppContext*>(user_data); - auto* framework = context->mFramework; - Observer* observer = &framework->mObserver; - - app_event_low_memory_status_e status; - auto appEventReturn = app_event_get_low_memory_status(event_info, &status); - if(appEventReturn == APP_ERROR_NONE) + if(destroyFunctionPtr != NULL) { - Dali::DeviceStatus::Memory::Status result = AppCore::GetMemoryStatus(status); - observer->OnMemoryLow(result); - } - else - { - DALI_LOG_ERROR("Fail to get low memory status event. Error code : %d\n", static_cast<int>(appEventReturn)); + destroyFunctionPtr(baseAppPtr); } + + dlclose(mHandle); } + } - static void OnDeviceOrientationChanged(app_event_info_h event_info, void* user_data) + int AppMain() + { + if(mHandle == nullptr) { - auto* context = static_cast<UiAppContext*>(user_data); - auto* framework = context->mFramework; - Observer* observer = &framework->mObserver; - - app_device_orientation_e status; - auto appEventReturn = app_event_get_device_orientation(event_info, &status); - if(appEventReturn == APP_ERROR_NONE) - { - Dali::DeviceStatus::Orientation::Status result = AppCore::GetOrientationStatus(status); - observer->OnDeviceOrientationChanged(result); - } - else - { - DALI_LOG_ERROR("Fail to get device orientation event. Error code : %d\n", static_cast<int>(appEventReturn)); - } + print_log(DLOG_INFO, "DALI", "mHandle is null"); + return TIZEN_ERROR_NOT_SUPPORTED; } - void ProcessBundle(FrameworkTizen* framework, bundle* bundleData) + if(createFunctionPtr != nullptr) { - if(bundleData == nullptr) - { - return; - } - - // get bundle name - char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name")); - if(bundleName != nullptr) - { - framework->SetBundleName(bundleName); - } - - // get bundle? id - char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id")); - if(bundleId != nullptr) - { - framework->SetBundleId(bundleId); - } + baseAppPtr = createFunctionPtr(); } - private: - FrameworkTizen* mFramework; - std::shared_ptr<AppEvent> mLanguageChanged; - std::shared_ptr<AppEvent> mDeviceOrientationChanged; - std::shared_ptr<AppEvent> mRegionFormatChanged; - std::shared_ptr<AppEvent> mLowBattery; - std::shared_ptr<AppEvent> mLowMemory; - bool mUseUiThread; - }; - - // Constructor - Impl(void* data, Type type, bool useUiThread) - : handlers{nullptr, nullptr, nullptr, nullptr, nullptr}, - mUseUiThread(useUiThread) -#ifdef APPCORE_WATCH_AVAILABLE - , - mWatchCallback() -#endif - { - mFramework = static_cast<FrameworkTizen*>(data); - -#ifndef APPCORE_WATCH_AVAILABLE - if(type == WATCH) + if(baseAppPtr == nullptr) { - throw Dali::DaliException("", "Watch Application is not supported."); + DALI_LOG_ERROR("p is null\n"); + return TIZEN_ERROR_NOT_SUPPORTED; } -#endif - mApplicationType = type; - } - - ~Impl() - { - } - int AppMain() - { - // TODO: The app-core-cpp has to be applied to the other app types. - int ret; - switch(mApplicationType) + int ret = 0; + if(appMainFunctionPtr != nullptr) { - case NORMAL: - { - ret = AppNormalMain(); - break; - } - case WIDGET: - { - ret = AppWidgetMain(); - break; - } - case WATCH: - { - ret = AppWatchMain(); - break; - } -#ifdef COMPONENT_APPLICATION_SUPPORT - case COMPONENT: - { - ret = AppComponentMain(); - break; - } -#endif - default: - { - DALI_LOG_ERROR("Invalid app type : %d\n", static_cast<int>(mApplicationType)); - ret = APP_ERROR_NOT_SUPPORTED; - } + ret = appMainFunctionPtr(mUiThread, mFramework, baseAppPtr); } return ret; } void AppExit() { - switch(mApplicationType) + if(baseAppPtr == nullptr) { - case NORMAL: - { - AppNormalExit(); - break; - } - case WIDGET: - { - AppWidgetExit(); - break; - } - case WATCH: - { - AppWatchExit(); - break; - } -#ifdef COMPONENT_APPLICATION_SUPPORT - case COMPONENT: - { - AppComponentExit(); - break; - } -#endif - default: - { - DALI_LOG_ERROR("Invalid app type : %d\n", static_cast<int>(mApplicationType)); - } + DALI_LOG_ERROR("baseAppPtr is null\n"); + return; } + appExitFunctionPtr(baseAppPtr); } void SetLanguage(const std::string& language) @@ -858,450 +234,26 @@ struct FrameworkTizen::Impl return mRegion; } - // Data - Type mApplicationType; - std::string mLanguage{}; - std::string mRegion{}; - - FrameworkTizen* mFramework; - AppCore::AppEventHandlerPtr handlers[5]; - std::unique_ptr<UiAppContext> mUiAppContext{nullptr}; - bool mUseUiThread{false}; -#ifdef APPCORE_WATCH_AVAILABLE - watch_app_lifecycle_callback_s mWatchCallback; -#endif - - static void ProcessBundle(FrameworkTizen* framework, bundle* bundleData) - { - if(bundleData == NULL) - { - return; - } - - // get bundle name - char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name")); - if(bundleName != NULL) - { - framework->SetBundleName(bundleName); - } + using CreateFunction = void* (*)(); + using DestroyFunction = void (*)(void*); - // get bundle? id - char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id")); - if(bundleId != NULL) - { - framework->SetBundleId(bundleId); - } - } + using AppMainFunction = int (*)(bool, void*, void*); + using AppExitFunction = void (*)(void*); - static void AppInit(int argc, char** argv, void* data) - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" - ecore_init(); - ecore_app_args_set(argc, (const char**)argv); -#pragma GCC diagnostic pop - -#ifdef DALI_ELDBUS_AVAILABLE - // Initialize ElDBus. - DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n"); - eldbus_init(); -#endif - } - - static void AppFinish(void) - { - ecore_shutdown(); - - if(getenv("AUL_LOADER_INIT")) - { - setenv("AUL_LOADER_INIT", "0", 1); - ecore_shutdown(); - } - -#ifdef DALI_ELDBUS_AVAILABLE - // Shutdown ELDBus. - DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n"); - eldbus_shutdown(); -#endif - } - - static void AppRun(void* data) - { - ecore_main_loop_begin(); - } - - static void AppExit(void* data) - { - ecore_main_loop_quit(); - } - - static void AppLanguageChanged(AppCore::AppEventInfoPtr event, void* data) - { - FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); - Observer* observer = &framework->mObserver; - - if(event && event->value) - { - framework->SetLanguage(std::string(static_cast<const char*>(event->value))); - observer->OnLanguageChanged(); - } - else - { - DALI_LOG_ERROR("NULL pointer in Language changed event\n"); - } - } - - static void AppRegionChanged(AppCore::AppEventInfoPtr event, void* data) - { - FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); - Observer* observer = &framework->mObserver; - - if(event && event->value) - { - framework->SetRegion(std::string(static_cast<const char*>(event->value))); - observer->OnRegionChanged(); - } - else - { - DALI_LOG_ERROR("NULL pointer in Region changed event\n"); - } - } - - static void AppBatteryLow(AppCore::AppEventInfoPtr event, void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - int status = *static_cast<int*>(event->value); - Dali::DeviceStatus::Battery::Status result = Dali::DeviceStatus::Battery::Status::NORMAL; - - // convert to dali battery status - switch(status) - { - case 1: - { - result = Dali::DeviceStatus::Battery::POWER_OFF; - break; - } - case 2: - { - result = Dali::DeviceStatus::Battery::CRITICALLY_LOW; - break; - } - default: - break; - } - observer->OnBatteryLow(result); - } - - static void AppMemoryLow(AppCore::AppEventInfoPtr event, void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - int status = *static_cast<int*>(event->value); - Dali::DeviceStatus::Memory::Status result = Dali::DeviceStatus::Memory::Status::NORMAL; - - // convert to dali memmory status - switch(status) - { - case 1: - { - result = Dali::DeviceStatus::Memory::NORMAL; - break; - } - case 2: - { - result = Dali::DeviceStatus::Memory::LOW; - break; - } - case 4: - { - result = Dali::DeviceStatus::Memory::CRITICALLY_LOW; - break; - } - default: - break; - } - observer->OnMemoryLow(result); - } - - static void AppDeviceOrientationChanged(AppCore::AppEventInfoPtr event, void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - int status = *static_cast<int*>(event->value); - Dali::DeviceStatus::Orientation::Status result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; + void* mHandle{nullptr}; + CreateFunction createFunctionPtr; + DestroyFunction destroyFunctionPtr; + AppMainFunction appMainFunctionPtr; + AppExitFunction appExitFunctionPtr; + void* baseAppPtr = nullptr; + bool mUiThread; - switch(status) - { - case APP_DEVICE_ORIENTATION_0: - { - result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; - break; - } - case APP_DEVICE_ORIENTATION_90: - { - result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_90; - break; - } - case APP_DEVICE_ORIENTATION_180: - { - result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_180; - break; - } - case APP_DEVICE_ORIENTATION_270: - { - result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_270; - break; - } - - default: - break; - } - observer->OnDeviceOrientationChanged(result); - } - - int AppNormalMain() - { - if(mUiAppContext.get() == nullptr) - { - unsigned int hint = AppCoreUiBase::HINT_WINDOW_GROUP_CONTROL | - AppCoreUiBase::HINT_WINDOW_STACK_CONTROL | - AppCoreUiBase::HINT_BG_LAUNCH_CONTROL | - AppCoreUiBase::HINT_HW_ACC_CONTROL | - AppCoreUiBase::HINT_WINDOW_AUTO_CONTROL; - -#ifdef UI_THREAD_AVAILABLE - // For testing UIThread model, This code turns on the UI Thread feature forcibly. - // ex) app_launcher -e [APPID] __K_UI_THREAD enable - // This code doesn't change mUseUiThread in Internal::Application - bundle* b = bundle_import_from_argv(*mFramework->mArgc, *mFramework->mArgv); - if(b != nullptr) - { - const char* val = bundle_get_val(b, "__K_UI_THREAD"); - if(val != nullptr && strcmp(val, "enable") == 0) - { - mUseUiThread = true; - } - - bundle_free(b); - } - - if(mUseUiThread) - { - hint |= AppCoreUiBase::HINT_DUAL_THREAD; - } -#endif - - mUiAppContext = std::make_unique<UiAppContext>(hint, mFramework); - } - - mUiAppContext->Run(*mFramework->mArgc, *mFramework->mArgv); - return APP_ERROR_NONE; - } - - void AppNormalExit() - { - if(mUiAppContext.get() == nullptr) - { - return; - } - - mUiAppContext->Exit(); - } - - void AppWidgetExit() - { - widget_base_exit(); - } - - static int WidgetAppCreate(void* data) - { - widget_base_on_create(); - return static_cast<int>(static_cast<FrameworkTizen*>(data)->Create()); - } - - static int WidgetAppTerminate(void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - observer->OnTerminate(); - - widget_base_on_terminate(); - return 0; - } - - int AppWidgetMain() - { - if(!IsWidgetFeatureEnabled()) - { - DALI_LOG_ERROR("widget feature is not supported"); - return APP_ERROR_NOT_SUPPORTED; - } - - AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework); - AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework); - AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceOrientationChanged, mFramework); - AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework); - AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework); - - widget_base_ops ops = widget_base_get_default_ops(); - - /* override methods */ - ops.create = WidgetAppCreate; - ops.terminate = WidgetAppTerminate; - ops.init = AppInit; - ops.finish = AppFinish; - ops.run = AppRun; - ops.exit = AppExit; - - int result = widget_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework); - - widget_base_fini(); - - return result; - } - -#ifdef APPCORE_WATCH_AVAILABLE - static bool WatchAppCreate(int width, int height, void* data) - { - return static_cast<FrameworkTizen*>(data)->Create(); - } - - static void WatchAppTimeTick(watch_time_h time, void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - WatchTime curTime(time); - - observer->OnTimeTick(curTime); - } - - static void WatchAppAmbientTick(watch_time_h time, void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - WatchTime curTime(time); - - observer->OnAmbientTick(curTime); - } - - static void WatchAppAmbientChanged(bool ambient, void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - - observer->OnAmbientChanged(ambient); - } - - static void WatchAppControl(app_control_h app_control, void* data) - { - FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); - Observer* observer = &framework->mObserver; - bundle* bundleData = NULL; - - app_control_to_bundle(app_control, &bundleData); - ProcessBundle(framework, bundleData); - - observer->OnReset(); - observer->OnAppControl(app_control); - } - - static void WatchAppTerminate(void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - - observer->OnTerminate(); - } - - static void WatchAppPause(void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - - observer->OnPause(); - } - - static void WatchAppResume(void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - - observer->OnResume(); - } - -#endif - - int AppWatchMain() - { - int ret = APP_ERROR_NOT_SUPPORTED; - -#ifdef APPCORE_WATCH_AVAILABLE - mWatchCallback.create = WatchAppCreate; - mWatchCallback.app_control = WatchAppControl; - mWatchCallback.terminate = WatchAppTerminate; - mWatchCallback.pause = WatchAppPause; - mWatchCallback.resume = WatchAppResume; - mWatchCallback.time_tick = WatchAppTimeTick; - mWatchCallback.ambient_tick = WatchAppAmbientTick; - mWatchCallback.ambient_changed = WatchAppAmbientChanged; - - AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework); - AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework); - AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework); - AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework); - - ret = watch_app_main(*mFramework->mArgc, *mFramework->mArgv, &mWatchCallback, mFramework); -#else - DALI_LOG_ERROR("watch feature is not supported"); -#endif - return ret; - } - - void AppWatchExit() - { -#ifdef APPCORE_WATCH_AVAILABLE - watch_app_exit(); -#endif - } - -#ifdef COMPONENT_APPLICATION_SUPPORT - int AppComponentMain() - { - /*Crate component_based_app_base_lifecycle_callback*/ - component_based_app_base_lifecycle_callback_s callback; - callback.init = AppInit; - callback.run = AppRun; - callback.exit = AppExit; - callback.create = ComponentAppCreate; - callback.terminate = ComponentAppTerminate; - callback.fini = ComponentAppFinish; - - return component_based_app_base_main(*mFramework->mArgc, *mFramework->mArgv, &callback, mFramework); - } - - static void* ComponentAppCreate(void* data) - { - FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); - Observer* observer = &framework->mObserver; - observer->OnInit(); - - return Dali::AnyCast<void*>(observer->OnCreate()); - } - - static void ComponentAppTerminate(void* data) - { - Observer* observer = &static_cast<FrameworkTizen*>(data)->mObserver; - observer->OnTerminate(); - } - - static void ComponentAppFinish(void* data) - { - ecore_shutdown(); - - if(getenv("AUL_LOADER_INIT")) - { - setenv("AUL_LOADER_INIT", "0", 1); - ecore_shutdown(); - } - } - - void AppComponentExit() - { - component_based_app_base_exit(); - } + // Data + Type mApplicationType; + std::string mLanguage{}; + std::string mRegion{}; -#endif + FrameworkTizen* mFramework; private: // Undefined @@ -1361,7 +313,7 @@ void FrameworkTizen::Run() DALI_TRACE_BEGIN(gTraceFilter, "DALI_APPMAIN"); ret = mImpl->AppMain(); DALI_TRACE_END(gTraceFilter, "DALI_APPMAIN"); - if(ret != APP_ERROR_NONE) + if(ret != TIZEN_ERROR_NONE) { DALI_LOG_ERROR("Framework::Run(), ui_app_main() is failed. err = %d\n", ret); } @@ -1424,7 +376,6 @@ struct UIThreadLoader::Impl #ifdef UI_THREAD_AVAILABLE mUIThreadLoader = static_cast<UIThreadLoader*>(data); mAppCoreUiThreadBase = new AppCoreUiThreadBase(); - print_log(DLOG_INFO, "DALI", "%s: %s(%d) > Create mAppCoreUiThreadBase(%p)", __MODULE__, __func__, __LINE__, mAppCoreUiThreadBase); #endif } diff --git a/dali/internal/adaptor/tizen-wayland/framework-tizen.h b/dali/internal/adaptor/tizen-wayland/framework-tizen.h index c6c182a2e..996c8960e 100644 --- a/dali/internal/adaptor/tizen-wayland/framework-tizen.h +++ b/dali/internal/adaptor/tizen-wayland/framework-tizen.h @@ -29,7 +29,7 @@ namespace Adaptor /** * FrameworkTizen class provides an Framework Tizen implementation. */ -class FrameworkTizen : public Framework +class DALI_ADAPTOR_API FrameworkTizen : public Framework { public: /** @@ -59,11 +59,21 @@ public: std::string GetBundleName() const; /** + * Called app_reset callback was called with bundle. + */ + void SetBundleName(const std::string& name); + + /** * Gets bundle id which was passed in app_reset callback. */ std::string GetBundleId() const; /** + * Called app_reset callback was called with bundle. + */ + void SetBundleId(const std::string& id); + + /** * Sets system language. */ void SetLanguage(const std::string& language); @@ -83,26 +93,15 @@ public: */ std::string GetRegion() const override; -private: - // Undefined - FrameworkTizen(const FrameworkTizen&) = delete; - FrameworkTizen& operator=(FrameworkTizen&) = delete; - -private: /** * Called when the application is created. */ bool Create(); - /** - * Called app_reset callback was called with bundle. - */ - void SetBundleName(const std::string& name); - - /** - * Called app_reset callback was called with bundle. - */ - void SetBundleId(const std::string& id); +private: + // Undefined + FrameworkTizen(const FrameworkTizen&) = delete; + FrameworkTizen& operator=(FrameworkTizen&) = delete; private: bool mInitialised; diff --git a/dali/internal/application-model/component-based/appmodel-component-based-tizen.cpp b/dali/internal/application-model/component-based/appmodel-component-based-tizen.cpp new file mode 100644 index 000000000..c28c1db97 --- /dev/null +++ b/dali/internal/application-model/component-based/appmodel-component-based-tizen.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2024 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. + * + */ + +// CLASS HEADER +#include <dali/internal/application-model/component-based/appmodel-component-based-tizen.h> + +// EXTERNAL INCLUDES +#include <dlog.h> + +// CONDITIONAL INCLUDES +#ifdef COMPONENT_APPLICATION_SUPPORT +#include <component_based_app_base.h> +#endif +#ifdef DALI_ELDBUS_AVAILABLE +#include <Eldbus.h> +#endif // DALI_ELDBUS_AVAILABLE + +// INTERNAL INCLUDES +#include <dali/integration-api/debug.h> +#include <dali/integration-api/trace.h> +#include <dali/internal/system/linux/dali-ecore.h> +#include <dali/internal/adaptor/common/framework.h> +#include <dali/internal/adaptor/tizen-wayland/framework-tizen.h> + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +extern "C" DALI_ADAPTOR_API AppModelComponentBased* Create() { + return new AppModelComponentBased; +} + +extern "C" DALI_ADAPTOR_API void Destroy(void* p) { + delete p; +} + +extern "C" DALI_ADAPTOR_API int AppMain(bool isUiThread, void* data, void* pData) { + AppModelComponentBased* appComponent = static_cast<AppModelComponentBased*>(pData); + int ret = 0; + if (appComponent != nullptr) + { + ret = appComponent->AppMain(data); + } + else + { + print_log(DLOG_INFO, "DALI", "appComponent is nullptr"); + } + return ret; +} + +extern "C" DALI_ADAPTOR_API void AppExit(AppModelComponentBased* p) { + p->AppExit(); +} + +namespace +{ +#if defined(DEBUG_ENABLED) +Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS"); +#endif +DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_FRAMEWORK, true); +} // anonymous namespace + +struct DALI_ADAPTOR_API AppModelComponentBased::Impl +{ + int AppMain(void* data) + { + int ret = TIZEN_ERROR_NOT_SUPPORTED; +#ifdef COMPONENT_APPLICATION_SUPPORT + FrameworkTizen* mFramework = static_cast<FrameworkTizen*>(data); + + /*Crate component_based_app_base_lifecycle_callback*/ + component_based_app_base_lifecycle_callback_s callback; + callback.init = AppInit; + callback.run = AppRun; + callback.exit = AppExit; + callback.create = ComponentAppCreate; + callback.terminate = ComponentAppTerminate; + callback.fini = ComponentAppFinish; + + ret = component_based_app_base_main(*mFramework->GetArgc(), *mFramework->GetArgv(), &callback, mFramework);; +#else + DALI_LOG_ERROR("component application feature is not supported"); +#endif + return ret; + } + + static void AppInit(int argc, char** argv, void* data) + { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wold-style-cast" + ecore_init(); + ecore_app_args_set(argc, (const char**)argv); + #pragma GCC diagnostic pop + + #ifdef DALI_ELDBUS_AVAILABLE + // Initialize ElDBus. + DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n"); + eldbus_init(); + #endif + } + + static void AppRun(void* data) + { + ecore_main_loop_begin(); + } + + static void AppExit(void* data) + { + ecore_main_loop_quit(); + } + + static void* ComponentAppCreate(void* data) + { + FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); + Framework::Observer* observer = &framework->GetObserver(); + observer->OnInit(); + + return Dali::AnyCast<void*>(observer->OnCreate()); + } + + static void ComponentAppTerminate(void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + observer->OnTerminate(); + } + + static void ComponentAppFinish(void* data) + { + ecore_shutdown(); + + if(getenv("AUL_LOADER_INIT")) + { + setenv("AUL_LOADER_INIT", "0", 1); + ecore_shutdown(); + } + } + + void AppExit() + { +#ifdef COMPONENT_APPLICATION_SUPPORT + component_based_app_base_exit(); +#endif + } + + Impl(void* data) + { + mAppModelComponentBased = static_cast<AppModelComponentBased*>(data); + } + + ~Impl() + { + } + + AppModelComponentBased* mAppModelComponentBased; + +}; + +AppModelComponentBased::AppModelComponentBased() +{ + mImpl = new Impl(this); +} + +AppModelComponentBased::~AppModelComponentBased() +{ + delete mImpl; +} + +int AppModelComponentBased::AppMain(void *data) +{ + return mImpl->AppMain(data); +} + +void AppModelComponentBased::AppExit() +{ + mImpl->AppExit(); +} +} // Adaptor +} // Internal +} // Dali
\ No newline at end of file diff --git a/dali/internal/application-model/component-based/appmodel-component-based-tizen.h b/dali/internal/application-model/component-based/appmodel-component-based-tizen.h new file mode 100644 index 000000000..a42fe84d0 --- /dev/null +++ b/dali/internal/application-model/component-based/appmodel-component-based-tizen.h @@ -0,0 +1,55 @@ +#ifndef APPMODEL_COMPONENT_BASED_H +#define APPMODEL_COMPONENT_BASED_H + +/* + * Copyright (c) 2024 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. + * + */ + +// INTERNAL INCLUDES +#include <dali/public-api/dali-adaptor-common.h> + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +class AppModelComponentBased +{ +public: // Construction & Destruction + /** + * Constructor + */ + AppModelComponentBased(); + + /** + * Destructor + */ + ~AppModelComponentBased(); + +public: + int AppMain(void* data); + void AppExit(); + +private: // impl members + struct Impl; + Impl* mImpl; +}; +} +} +} + +#endif // APPMODEL_COMPONENT_BASED_H diff --git a/dali/internal/application-model/file.list b/dali/internal/application-model/file.list new file mode 100644 index 000000000..febe23971 --- /dev/null +++ b/dali/internal/application-model/file.list @@ -0,0 +1,18 @@ +# Add local source files here + +SET( app_normal_src_files + ${appmodel_src_dir}/normal/appmodel-normal-tizen.cpp +) + +SET( app_widget_src_files + ${appmodel_src_dir}/widget/appmodel-widget-tizen.cpp + ${appmodel_src_dir}/widget/widget-base-tizen.cpp +) + +SET( app_watch_src_files + ${appmodel_src_dir}/watch/appmodel-watch-tizen.cpp +) + +SET( app_component_based_src_files + ${appmodel_src_dir}/component-based/appmodel-component-based-tizen.cpp +) diff --git a/dali/internal/application-model/normal/appmodel-normal-tizen.cpp b/dali/internal/application-model/normal/appmodel-normal-tizen.cpp new file mode 100644 index 000000000..4b27e1450 --- /dev/null +++ b/dali/internal/application-model/normal/appmodel-normal-tizen.cpp @@ -0,0 +1,803 @@ +/* + * Copyright (c) 2024 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. + * + */ + +// CLASS HEADER +#include <dali/internal/application-model/normal/appmodel-normal-tizen.h> + +// EXTERNAL INCLUDES +#include <app_common.h> +#include <app_control_internal.h> +#include <appcore_base.h> +#include <bundle.h> +#include <bundle_internal.h> +#include <dlog.h> +#include <glib.h> +#include <system_info.h> +#include <system_settings.h> +#include <app_core_ui_base.hh> +#include <app_core_task_base.hh> +#include <app_event_internal.hh> + +// CONDITIONAL INCLUDES +#ifdef DALI_ELDBUS_AVAILABLE +#include <Eldbus.h> +#endif // DALI_ELDBUS_AVAILABLE + +// INTERNAL INCLUDES +#include <dali/integration-api/debug.h> +#include <dali/internal/system/linux/dali-ecore.h> +#include <dali/internal/adaptor/common/framework.h> +#include <dali/internal/adaptor/tizen-wayland/framework-tizen.h> + +using namespace tizen_cpp; + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +extern "C" DALI_ADAPTOR_API AppModelNormal* Create() { + return new AppModelNormal(false); +} + +extern "C" DALI_ADAPTOR_API void Destroy(void* p) { + delete p; +} + +extern "C" DALI_ADAPTOR_API int AppMain(bool isUiThread, void* data, void* pData) { + AppModelNormal* appNormal = static_cast<AppModelNormal*>(pData); + int ret = 0; + if (appNormal != nullptr) + { + ret = appNormal->AppMain(data); + } + else + { + print_log(DLOG_INFO, "DALI", "appNormal is nullptr"); + } + return ret; +} + +extern "C" DALI_ADAPTOR_API void AppExit(AppModelNormal* p) { + p->AppExit(); +} + +namespace +{ +#if defined(DEBUG_ENABLED) +Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS"); +#endif +} // anonymous namespace + +namespace AppCore +{ + +typedef enum +{ + LOW_MEMORY, //< The low memory event + LOW_BATTERY, //< The low battery event + LANGUAGE_CHANGED, //< The system language changed event + DEVICE_ORIENTATION_CHANGED, //< The device orientation changed event + REGION_FORMAT_CHANGED, //< The region format changed event + SUSPENDED_STATE_CHANGED, //< The suspended state changed event of the application + UPDATE_REQUESTED, //< The update requested event. This event can occur when an app needs to be updated. It is dependent on target devices. +} AppEventType; + +static int AppEventConverter[APPCORE_BASE_EVENT_MAX] = +{ + [LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY, + [LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY, + [LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE, + [DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED, + [REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE, + [SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE, +}; + +struct AppEventInfo +{ + AppEventType type; + void* value; +}; + +typedef struct AppEventInfo* AppEventInfoPtr; + +typedef void (*AppEventCallback)(AppEventInfoPtr eventInfo, void* userData); + +struct AppEventHandler +{ + AppEventType type; + AppEventCallback cb; + void* data; + void* raw; +}; + +typedef struct AppEventHandler* AppEventHandlerPtr; + +int EventCallback(void* event, void* data) +{ + AppEventHandlerPtr handler = static_cast<AppEventHandlerPtr>(data); + + struct AppEventInfo appEvent; + + appEvent.type = handler->type; + appEvent.value = event; + + if(handler->cb) + handler->cb(&appEvent, handler->data); + + return 0; +} + +int AppAddEventHandler(AppEventHandlerPtr* eventHandler, AppEventType eventType, AppEventCallback callback, void* userData) +{ + AppEventHandlerPtr handler; + + handler = static_cast<AppEventHandlerPtr>(calloc(1, sizeof(struct AppEventHandler))); + if(!handler) + { + DALI_LOG_ERROR("failed to create handler"); + return TIZEN_ERROR_UNKNOWN; + } + else + { + handler->type = eventType; + handler->cb = callback; + handler->data = userData; + handler->raw = appcore_base_add_event(static_cast<appcore_base_event>(AppEventConverter[static_cast<int>(eventType)]), EventCallback, handler); + + *eventHandler = handler; + + return TIZEN_ERROR_NONE; + } +} + +DeviceStatus::Memory::Status GetMemoryStatus(app_event_low_memory_status_e memoryStatus) +{ + switch(memoryStatus) + { + case APP_EVENT_LOW_MEMORY_SOFT_WARNING: // 0x02 + { + return Dali::DeviceStatus::Memory::Status::LOW; + } + case APP_EVENT_LOW_MEMORY_HARD_WARNING: // 0x04 + { + return Dali::DeviceStatus::Memory::Status::CRITICALLY_LOW; + } + default: // APP_EVENT_LOW_MEMORY_NORMAL 0x01 + { + return Dali::DeviceStatus::Memory::Status::NORMAL; + } + } +} + +DeviceStatus::Battery::Status GetBatteryStatus(app_event_low_battery_status_e batteryStatus) +{ + switch(batteryStatus) + { + case APP_EVENT_LOW_BATTERY_POWER_OFF: // 1 + { + return Dali::DeviceStatus::Battery::Status::POWER_OFF; + } + case APP_EVENT_LOW_BATTERY_CRITICAL_LOW: // 2 + { + return Dali::DeviceStatus::Battery::Status::CRITICALLY_LOW; + } + default: + { + return Dali::DeviceStatus::Battery::Status::NORMAL; + } + } +} + +DeviceStatus::Orientation::Status GetOrientationStatus(app_device_orientation_e orientationStatus) +{ + switch(orientationStatus) + { + case APP_DEVICE_ORIENTATION_0: + { + return Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; + } + case APP_DEVICE_ORIENTATION_90: + { + return Dali::DeviceStatus::Orientation::Status::ORIENTATION_90; + } + case APP_DEVICE_ORIENTATION_180: + { + return Dali::DeviceStatus::Orientation::Status::ORIENTATION_180; + } + case APP_DEVICE_ORIENTATION_270: + { + return Dali::DeviceStatus::Orientation::Status::ORIENTATION_270; + } + default: + { + return Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; + } + } +} +} + +struct DALI_ADAPTOR_API AppModelNormal::Impl +{ + class UiAppContext : public AppCoreUiBase + { + public: + class Task : public AppCoreTaskBase + { + public: + explicit Task(FrameworkTizen* framework) + : mFramework(framework), + mNewBatteryStatus(Dali::DeviceStatus::Battery::Status::NORMAL), + mNewMemoryStatus(Dali::DeviceStatus::Memory::NORMAL), + mNewDeviceOrientationStatus(Dali::DeviceStatus::Orientation::ORIENTATION_0) + { + } + + virtual ~Task() + { + } + + int OnCreate() override + { + // On the main thread, the log functions are not set. So print_log() is used directly. + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnCreate() emitted", __MODULE__, __func__, __LINE__); + mFramework->GetTaskObserver().OnTaskInit(); + return AppCoreTaskBase::OnCreate(); + } + + int OnTerminate() override + { + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnTerminate() emitted", __MODULE__, __func__, __LINE__); + mFramework->GetTaskObserver().OnTaskTerminate(); + return AppCoreTaskBase::OnTerminate(); + } + + int OnControl(tizen_base::Bundle b) override + { + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnControl() emitted", __MODULE__, __func__, __LINE__); + AppCoreTaskBase::OnControl(b); + + app_control_h appControl = nullptr; + + auto* bundleData = b.GetHandle(); + if(bundleData) + { + if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE) + { + print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle with Bundle", __MODULE__, __func__, __LINE__); + } + } + else + { + if(app_control_create(&appControl) != TIZEN_ERROR_NONE) + { + print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle", __MODULE__, __func__, __LINE__); + } + } + mFramework->GetTaskObserver().OnTaskAppControl(appControl); + + app_control_destroy(appControl); + return 0; + } + + void OnUiEvent(AppCoreTaskBase::UiState state) override + { + // This event is emitted when the UI thread is paused or resumed. + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnUiEvent() emitted", __MODULE__, __func__, __LINE__); + + // Note: This isn't implemented. + AppCoreTaskBase::OnUiEvent(state); + } + + void OnLowMemory(AppCoreTaskBase::LowMemoryState state) override + { + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowMemory() emitted", __MODULE__, __func__, __LINE__); + + mNewMemoryStatus = AppCore::GetMemoryStatus(static_cast<app_event_low_memory_status_e>(state)); + + PostToUiThread( + [](gpointer userData) -> gboolean { + auto* task = static_cast<Task*>(userData); + auto* framework = static_cast<FrameworkTizen*>(task->mFramework); + framework->GetObserver().OnMemoryLow(task->mNewMemoryStatus); + return G_SOURCE_REMOVE; + }); + mFramework->GetTaskObserver().OnTaskMemoryLow(mNewMemoryStatus); + AppCoreTaskBase::OnLowMemory(state); + } + + void OnDeviceOrientationChanged(AppCoreTaskBase::DeviceOrientationState state) override + { + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnDeviceOrientationChanged() emitted, orientation :%d", __MODULE__, __func__, __LINE__, state); + + mNewDeviceOrientationStatus = AppCore::GetOrientationStatus(static_cast<app_device_orientation_e>(state)); + + PostToUiThread( + [](gpointer userData) -> gboolean { + auto* task = static_cast<Task*>(userData); + auto* framework = static_cast<FrameworkTizen*>(task->mFramework); + framework->GetObserver().OnDeviceOrientationChanged(task->mNewDeviceOrientationStatus); + return G_SOURCE_REMOVE; + }); + + mFramework->GetTaskObserver().OnTaskDeviceOrientationChanged(mNewDeviceOrientationStatus); + + AppCoreTaskBase::OnDeviceOrientationChanged(state); + } + void OnLowBattery(AppCoreTaskBase::LowBatteryState state) override + { + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowBattery() emitted", __MODULE__, __func__, __LINE__); + mNewBatteryStatus = AppCore::GetBatteryStatus(static_cast<app_event_low_battery_status_e>(state)); + + PostToUiThread( + [](gpointer userData) -> gboolean { + auto* task = static_cast<Task*>(userData); + auto* framework = static_cast<FrameworkTizen*>(task->mFramework); + framework->GetObserver().OnBatteryLow(task->mNewBatteryStatus); + return G_SOURCE_REMOVE; + }); + mFramework->GetTaskObserver().OnTaskBatteryLow(mNewBatteryStatus); + AppCoreTaskBase::OnLowBattery(state); + } + + void OnLangChanged(const std::string& lang) override + { + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted 1", __MODULE__, __func__, __LINE__); + mNewLanguage = lang; + mFramework->SetLanguage(mNewLanguage); + + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted 2", __MODULE__, __func__, __LINE__); + PostToUiThread( + [](gpointer userData) -> gboolean { + auto* task = static_cast<Task*>(userData); + auto* framework = static_cast<FrameworkTizen*>(task->mFramework); + framework->GetObserver().OnLanguageChanged(); + return G_SOURCE_REMOVE; + }); + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted 3", __MODULE__, __func__, __LINE__); + + mFramework->GetTaskObserver().OnTaskLanguageChanged(); + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted 4", __MODULE__, __func__, __LINE__); + AppCoreTaskBase::OnLangChanged(lang); + + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted 5", __MODULE__, __func__, __LINE__); + } + + void OnRegionChanged(const std::string& region) override + { + print_log(DLOG_INFO, "DALI", "%s: %s(%d) > nRegionChanged() emitted", __MODULE__, __func__, __LINE__); + mNewRegion = region; + mFramework->SetRegion(mNewRegion); + + PostToUiThread( + [](gpointer userData) -> gboolean { + auto* task = static_cast<Task*>(userData); + auto* framework = static_cast<FrameworkTizen*>(task->mFramework); + framework->GetObserver().OnRegionChanged(); + return G_SOURCE_REMOVE; + }); + + mFramework->GetTaskObserver().OnTaskRegionChanged(); + AppCoreTaskBase::OnRegionChanged(mNewRegion); + } + + private: + GMainContext* GetTizenGlibContext() + { + GMainContext* context; + const char* env = getenv("TIZEN_GLIB_CONTEXT"); + if(env) + { + context = (GMainContext*)strtoul(env, nullptr, 10); + } + else + { + context = nullptr; + } + + return context; + } + + void PostToUiThread(GSourceFunc func) + { + GSource* source = g_idle_source_new(); + g_source_set_callback(source, func, this, nullptr); + g_source_attach(source, GetTizenGlibContext()); + g_source_unref(source); + } + + private: + FrameworkTizen* mFramework; + std::string mNewLanguage; + std::string mNewRegion; + Dali::DeviceStatus::Battery::Status mNewBatteryStatus; + Dali::DeviceStatus::Memory::Status mNewMemoryStatus; + Dali::DeviceStatus::Orientation::Status mNewDeviceOrientationStatus; + }; + + explicit UiAppContext(unsigned int hint, FrameworkTizen* framework) + : AppCoreUiBase(hint), + mFramework(framework), + mUseUiThread(false) + { + if(hint & AppCoreUiBase::HINT_DUAL_THREAD) + { + mUseUiThread = true; + } + + if(!mUseUiThread) + { + mLanguageChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LANG_CHANGE, OnLanguageChanged, this); + AddEvent(mLanguageChanged); + + mDeviceOrientationChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, OnDeviceOrientationChanged, this); + AddEvent(mDeviceOrientationChanged); + + mRegionFormatChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::REGION_CHANGE, OnRegionFormatChanged, this); + AddEvent(mRegionFormatChanged); + + mLowMemory = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_MEMORY, OnLowMemory, this); + AddEvent(mLowMemory); + + mLowBattery = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_BATTERY, OnLowBattery, this); + AddEvent(mLowBattery); + } + } + + virtual ~UiAppContext() + { + if(!mUseUiThread) + { + RemoveEvent(mLowBattery); + RemoveEvent(mLowMemory); + RemoveEvent(mRegionFormatChanged); + RemoveEvent(mDeviceOrientationChanged); + RemoveEvent(mLanguageChanged); + } + } + + std::unique_ptr<AppCoreTaskBase> CreateTask() override + { + return std::unique_ptr<AppCoreTaskBase>( + new Task(mFramework)); + } + + int OnCreate() override + { + AppCoreUiBase::OnCreate(); + mFramework->Create(); + return 0; + } + + int OnTerminate() override + { + AppCoreUiBase::OnTerminate(); + auto* observer = &mFramework->GetObserver(); + observer->OnTerminate(); + return 0; + } + + int OnPause() override + { + AppCoreUiBase::OnPause(); + auto* observer = &mFramework->GetObserver(); + observer->OnPause(); + return 0; + } + + int OnResume() override + { + AppCoreUiBase::OnResume(); + auto* observer = &mFramework->GetObserver(); + observer->OnResume(); + return 0; + } + + int OnControl(tizen_base::Bundle b) override + { + AppCoreUiBase::OnControl(b); + + app_control_h appControl = nullptr; + + auto* bundleData = b.GetHandle(); + if(bundleData) + { + if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE) + { + DALI_LOG_ERROR("Failed to create an app_control handle"); + return 0; + } + } + else + { + if(app_control_create(&appControl) != TIZEN_ERROR_NONE) + { + DALI_LOG_ERROR("Failed to create an app_control handle"); + return 0; + } + } + + auto* observer = &mFramework->GetObserver(); + ProcessBundle(mFramework, bundleData); + observer->OnReset(); + observer->OnAppControl(appControl); + app_control_destroy(appControl); + return 0; + } + + void OnLoopInit(int argc, char** argv) override + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + ecore_init(); + ecore_app_args_set(argc, (const char**)argv); +#pragma GCC diagnostic pop + +#ifdef DALI_ELDBUS_AVAILABLE + // Initialize ElDBus. + DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n"); + eldbus_init(); +#endif + } + + void OnLoopFinish() override + { + ecore_shutdown(); + + if(getenv("AUL_LOADER_INIT")) + { + setenv("AUL_LOADER_INIT", "0", 1); + ecore_shutdown(); + } + +#ifdef DALI_ELDBUS_AVAILABLE + // Shutdown ELDBus. + DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n"); + eldbus_shutdown(); +#endif + } + + void OnLoopRun() override + { + ecore_main_loop_begin(); + } + + void OnLoopExit() override + { + ecore_main_loop_quit(); + } + + private: + static void OnLanguageChanged(app_event_info_h event_info, void* user_data) + { + auto* context = static_cast<UiAppContext*>(user_data); + auto* framework = context->mFramework; + Framework::Observer* observer = &framework->GetObserver(); + + char* lang = nullptr; + auto appEventReturn = app_event_get_language(event_info, &lang); + if(appEventReturn == APP_ERROR_NONE && lang) + { + framework->SetLanguage(std::string(lang)); + observer->OnLanguageChanged(); + free(lang); + } + else + { + DALI_LOG_ERROR("NULL pointer in Language changed event. Error code : %d\n", static_cast<int>(appEventReturn)); + } + } + + static void OnRegionFormatChanged(app_event_info_h event_info, void* user_data) + { + auto* context = static_cast<UiAppContext*>(user_data); + auto* framework = context->mFramework; + Framework::Observer* observer = &framework->GetObserver(); + + char* region = nullptr; + auto appEventReturn = app_event_get_region_format(event_info, ®ion); + if(appEventReturn == APP_ERROR_NONE && region) + { + framework->SetRegion(std::string(region)); + observer->OnRegionChanged(); + free(region); + } + else + { + DALI_LOG_ERROR("NULL pointer in Region changed event. Error code : %d\n", static_cast<int>(appEventReturn)); + } + } + + static void OnLowBattery(app_event_info_h event_info, void* user_data) + { + auto* context = static_cast<UiAppContext*>(user_data); + auto* framework = context->mFramework; + Framework::Observer* observer = &framework->GetObserver(); + + app_event_low_battery_status_e status; + auto appEventReturn = app_event_get_low_battery_status(event_info, &status); + if(appEventReturn == APP_ERROR_NONE) + { + Dali::DeviceStatus::Battery::Status result = AppCore::GetBatteryStatus(status); + observer->OnBatteryLow(result); + } + else + { + DALI_LOG_ERROR("Fail to get low battery status event. Error code : %d\n", static_cast<int>(appEventReturn)); + } + } + + static void OnLowMemory(app_event_info_h event_info, void* user_data) + { + auto* context = static_cast<UiAppContext*>(user_data); + auto* framework = context->mFramework; + Framework::Observer* observer = &framework->GetObserver(); + + app_event_low_memory_status_e status; + auto appEventReturn = app_event_get_low_memory_status(event_info, &status); + if(appEventReturn == APP_ERROR_NONE) + { + Dali::DeviceStatus::Memory::Status result = AppCore::GetMemoryStatus(status); + observer->OnMemoryLow(result); + } + else + { + DALI_LOG_ERROR("Fail to get low memory status event. Error code : %d\n", static_cast<int>(appEventReturn)); + } + } + + static void OnDeviceOrientationChanged(app_event_info_h event_info, void* user_data) + { + auto* context = static_cast<UiAppContext*>(user_data); + auto* framework = context->mFramework; + Framework::Observer* observer = &framework->GetObserver(); + + app_device_orientation_e status; + auto appEventReturn = app_event_get_device_orientation(event_info, &status); + if(appEventReturn == APP_ERROR_NONE) + { + Dali::DeviceStatus::Orientation::Status result = AppCore::GetOrientationStatus(status); + observer->OnDeviceOrientationChanged(result); + } + else + { + DALI_LOG_ERROR("Fail to get device orientation event. Error code : %d\n", static_cast<int>(appEventReturn)); + } + } + + void ProcessBundle(FrameworkTizen* framework, bundle* bundleData) + { + if(bundleData == nullptr) + { + return; + } + + // get bundle name + char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name")); + if(bundleName != nullptr) + { + framework->SetBundleName(bundleName); + } + + // get bundle? id + char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id")); + if(bundleId != nullptr) + { + framework->SetBundleId(bundleId); + } + } + + private: + FrameworkTizen* mFramework; + std::shared_ptr<AppEvent> mLanguageChanged; + std::shared_ptr<AppEvent> mDeviceOrientationChanged; + std::shared_ptr<AppEvent> mRegionFormatChanged; + std::shared_ptr<AppEvent> mLowBattery; + std::shared_ptr<AppEvent> mLowMemory; + bool mUseUiThread; + }; + + int AppMain(void* data) + { + FrameworkTizen* mFramework = static_cast<FrameworkTizen*>(data); + if(mUiAppContext.get() == nullptr) + { + unsigned int hint = AppCoreUiBase::HINT_WINDOW_GROUP_CONTROL | + AppCoreUiBase::HINT_WINDOW_STACK_CONTROL | + AppCoreUiBase::HINT_BG_LAUNCH_CONTROL | + AppCoreUiBase::HINT_HW_ACC_CONTROL | + AppCoreUiBase::HINT_WINDOW_AUTO_CONTROL; + +#ifdef UI_THREAD_AVAILABLE + // For testing UIThread model, This code turns on the UI Thread feature forcibly. + // ex) app_launcher -e [APPID] __K_UI_THREAD enable + // This code doesn't change mUseUiThread in Internal::Application + bundle* b = bundle_import_from_argv(*mFramework->GetArgc(), *mFramework->GetArgv()); + if(b != nullptr) + { + const char* val = bundle_get_val(b, "__K_UI_THREAD"); + if(val != nullptr && strcmp(val, "enable") == 0) + { + mUseUiThread = true; + } + + bundle_free(b); + } + + if(mUseUiThread) + { + hint |= AppCoreUiBase::HINT_DUAL_THREAD; + } +#endif + + mUiAppContext = std::make_unique<UiAppContext>(hint, mFramework); + } + + mUiAppContext->Run(*mFramework->GetArgc(), *mFramework->GetArgv()); + return APP_ERROR_NONE; + } + + void AppExit() + { + if(mUiAppContext.get() == nullptr) + { + return; + } + + mUiAppContext->Exit(); + } + + Impl(void* data, bool useUiThread) + : mUseUiThread(useUiThread) + { + mAppModelNormal = static_cast<AppModelNormal*>(data); + } + + ~Impl() + { + } + + AppModelNormal* mAppModelNormal; + std::unique_ptr<UiAppContext> mUiAppContext{nullptr}; + bool mUseUiThread{false}; +}; + +AppModelNormal::AppModelNormal(bool isUiThread) +{ + mImpl = new Impl(this, isUiThread); +} + +AppModelNormal::~AppModelNormal() +{ + delete mImpl; +} + +int AppModelNormal::AppMain(void* data) +{ + return mImpl->AppMain(data); +} + +void AppModelNormal::AppExit() +{ + mImpl->AppExit(); +} + +} // Adaptor +} // Internal +} // Dali + diff --git a/dali/internal/application-model/normal/appmodel-normal-tizen.h b/dali/internal/application-model/normal/appmodel-normal-tizen.h new file mode 100644 index 000000000..403880296 --- /dev/null +++ b/dali/internal/application-model/normal/appmodel-normal-tizen.h @@ -0,0 +1,55 @@ +#ifndef APPMODEL_NORMAL_H +#define APPMODEL_NORMAL_H +/* + * Copyright (c) 2024 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. + * + */ + +// INTERNAL INCLUDES +#include <dali/public-api/dali-adaptor-common.h> + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +class AppModelNormal +{ +public: // Construction & Destruction + /** + * Constructor + */ + AppModelNormal(bool isUiThread); + + /** + * Destructor + */ + ~AppModelNormal(); + +public: + int AppMain(void* data); + void AppExit(); + +private: // impl members + struct Impl; + Impl* mImpl; +}; +} +} +} + +#endif // APPMODEL_NORMAL_H + diff --git a/dali/internal/application-model/watch/appmodel-watch-tizen.cpp b/dali/internal/application-model/watch/appmodel-watch-tizen.cpp new file mode 100644 index 000000000..6a7a5d59a --- /dev/null +++ b/dali/internal/application-model/watch/appmodel-watch-tizen.cpp @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2024 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. + * + */ + +// CLASS HEADER +#include <dali/internal/application-model/watch/appmodel-watch-tizen.h> + +// CONDITIONAL INCLUDES +#ifdef APPCORE_WATCH_AVAILABLE +#include <appcore-watch/watch_app.h> +#endif + +// EXTERNAL INCLUDES +#include <app_common.h> +#include <appcore_base.h> +#include <tizen.h> +#include <bundle.h> +#include <dlog.h> +#include <bundle_internal.h> +#include <app_control_internal.h> + +// INTERNAL INCLUDES +#include <dali/public-api/watch/watch-time.h> +#include <dali/integration-api/debug.h> +#include <dali/internal/adaptor/common/framework.h> +#include <dali/internal/adaptor/tizen-wayland/framework-tizen.h> + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +extern "C" DALI_ADAPTOR_API AppModelWatch* Create() { + return new AppModelWatch; +} + +extern "C" DALI_ADAPTOR_API void Destroy(void* p) { + delete p; +} + +extern "C" DALI_ADAPTOR_API int AppMain(bool isUiThread, void* data, void* pData) { + AppModelWatch* appWatch = static_cast<AppModelWatch*>(pData); + int ret = 0; + if (appWatch != nullptr) + { + ret = appWatch->AppMain(data); + } + else + { + print_log(DLOG_INFO, "DALI", "appWatch is nullptr"); + } + return ret; +} + +extern "C" DALI_ADAPTOR_API void AppExit(AppModelWatch* p) { + p->AppExit(); +} + +namespace AppCoreWatch +{ +typedef enum +{ + LOW_MEMORY, //< The low memory event + LOW_BATTERY, //< The low battery event + LANGUAGE_CHANGED, //< The system language changed event + DEVICE_ORIENTATION_CHANGED, //< The device orientation changed event + REGION_FORMAT_CHANGED, //< The region format changed event + SUSPENDED_STATE_CHANGED, //< The suspended state changed event of the application + UPDATE_REQUESTED, //< The update requested event. This event can occur when an app needs to be updated. It is dependent on target devices. +} AppEventType; + +static int AppEventConverter[APPCORE_BASE_EVENT_MAX] = +{ + [LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY, + [LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY, + [LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE, + [DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED, + [REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE, + [SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE, +}; + +struct AppEventInfo +{ + AppEventType type; + void* value; +}; + +typedef struct AppEventInfo* AppEventInfoPtr; + +typedef void (*AppEventCallback)(AppEventInfoPtr eventInfo, void* userData); + +struct AppEventHandler +{ + AppEventType type; + AppEventCallback cb; + void* data; + void* raw; +}; + +typedef struct AppEventHandler* AppEventHandlerPtr; + +int EventCallback(void* event, void* data) +{ + AppEventHandlerPtr handler = static_cast<AppEventHandlerPtr>(data); + + struct AppEventInfo appEvent; + + appEvent.type = handler->type; + appEvent.value = event; + + if(handler->cb) + handler->cb(&appEvent, handler->data); + + return 0; +} + +int AppAddEventHandler(AppEventHandlerPtr* eventHandler, AppEventType eventType, AppEventCallback callback, void* userData) +{ + AppEventHandlerPtr handler; + + handler = static_cast<AppEventHandlerPtr>(calloc(1, sizeof(struct AppEventHandler))); + if(!handler) + { + DALI_LOG_ERROR("failed to create handler"); + return TIZEN_ERROR_UNKNOWN; + } + else + { + handler->type = eventType; + handler->cb = callback; + handler->data = userData; + handler->raw = appcore_base_add_event(static_cast<appcore_base_event>(AppEventConverter[static_cast<int>(eventType)]), EventCallback, handler); + + *eventHandler = handler; + + return TIZEN_ERROR_NONE; + } +} +} +struct DALI_ADAPTOR_API AppModelWatch::Impl +{ + +#ifdef APPCORE_WATCH_AVAILABLE + static bool WatchAppCreate(int width, int height, void* data) + { + return static_cast<FrameworkTizen*>(data)->Create(); + } + + static void WatchAppTimeTick(watch_time_h time, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + WatchTime curTime(time); + + observer->OnTimeTick(curTime); + } + + static void WatchAppAmbientTick(watch_time_h time, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + WatchTime curTime(time); + + observer->OnAmbientTick(curTime); + } + + static void WatchAppAmbientChanged(bool ambient, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + + observer->OnAmbientChanged(ambient); + } + + static void WatchAppControl(app_control_h app_control, void* data) + { + FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); + Framework::Observer* observer = &framework->GetObserver(); + bundle* bundleData = NULL; + + app_control_to_bundle(app_control, &bundleData); + ProcessBundle(framework, bundleData); + + observer->OnReset(); + observer->OnAppControl(app_control); + } + + static void WatchAppTerminate(void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + + observer->OnTerminate(); + } + + static void WatchAppPause(void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + + observer->OnPause(); + } + + static void WatchAppResume(void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + + observer->OnResume(); + } + + static void ProcessBundle(FrameworkTizen* framework, bundle* bundleData) + { + if(bundleData == NULL) + { + return; + } + + // get bundle name + char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name")); + if(bundleName != NULL) + { + framework->SetBundleName(bundleName); + } + + // get bundle? id + char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id")); + if(bundleId != NULL) + { + framework->SetBundleId(bundleId); + } + } +#endif + + static void AppLanguageChanged(AppCoreWatch::AppEventInfoPtr event, void* data) + { + FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); + Framework::Observer* observer = &framework->GetObserver(); + + if(event && event->value) + { + framework->SetLanguage(std::string(static_cast<const char*>(event->value))); + observer->OnLanguageChanged(); + } + else + { + DALI_LOG_ERROR("NULL pointer in Language changed event\n"); + } + } + + static void AppRegionChanged(AppCoreWatch::AppEventInfoPtr event, void* data) + { + FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); + Framework::Observer* observer = &framework->GetObserver(); + + if(event && event->value) + { + framework->SetRegion(std::string(static_cast<const char*>(event->value))); + observer->OnRegionChanged(); + } + else + { + DALI_LOG_ERROR("NULL pointer in Region changed event\n"); + } + } + + static void AppBatteryLow(AppCoreWatch::AppEventInfoPtr event, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + int status = *static_cast<int*>(event->value); + Dali::DeviceStatus::Battery::Status result = Dali::DeviceStatus::Battery::Status::NORMAL; + + // convert to dali battery status + switch(status) + { + case 1: + { + result = Dali::DeviceStatus::Battery::POWER_OFF; + break; + } + case 2: + { + result = Dali::DeviceStatus::Battery::CRITICALLY_LOW; + break; + } + default: + break; + } + observer->OnBatteryLow(result); + } + + static void AppMemoryLow(AppCoreWatch::AppEventInfoPtr event, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + int status = *static_cast<int*>(event->value); + Dali::DeviceStatus::Memory::Status result = Dali::DeviceStatus::Memory::Status::NORMAL; + + // convert to dali memmory status + switch(status) + { + case 1: + { + result = Dali::DeviceStatus::Memory::NORMAL; + break; + } + case 2: + { + result = Dali::DeviceStatus::Memory::LOW; + break; + } + case 4: + { + result = Dali::DeviceStatus::Memory::CRITICALLY_LOW; + break; + } + default: + break; + } + observer->OnMemoryLow(result); + } + + static void AppDeviceOrientationChanged(AppCoreWatch::AppEventInfoPtr event, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + int status = *static_cast<int*>(event->value); + Dali::DeviceStatus::Orientation::Status result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; + + switch(status) + { + case APP_DEVICE_ORIENTATION_0: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; + break; + } + case APP_DEVICE_ORIENTATION_90: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_90; + break; + } + case APP_DEVICE_ORIENTATION_180: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_180; + break; + } + case APP_DEVICE_ORIENTATION_270: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_270; + break; + } + + default: + break; + } + observer->OnDeviceOrientationChanged(result); + } + + int AppMain(void* data) + { + int ret = TIZEN_ERROR_NOT_SUPPORTED; + +#ifdef APPCORE_WATCH_AVAILABLE + FrameworkTizen* mFramework = static_cast<FrameworkTizen*>(data); + mWatchCallback.create = WatchAppCreate; + mWatchCallback.app_control = WatchAppControl; + mWatchCallback.terminate = WatchAppTerminate; + mWatchCallback.pause = WatchAppPause; + mWatchCallback.resume = WatchAppResume; + mWatchCallback.time_tick = WatchAppTimeTick; + mWatchCallback.ambient_tick = WatchAppAmbientTick; + mWatchCallback.ambient_changed = WatchAppAmbientChanged; + + AppCoreWatch::AppAddEventHandler(&handlers[AppCoreWatch::LOW_BATTERY], AppCoreWatch::LOW_BATTERY, AppBatteryLow, mFramework); + AppCoreWatch::AppAddEventHandler(&handlers[AppCoreWatch::LOW_MEMORY], AppCoreWatch::LOW_MEMORY, AppMemoryLow, mFramework); + AppCoreWatch::AppAddEventHandler(&handlers[AppCoreWatch::LANGUAGE_CHANGED], AppCoreWatch::LANGUAGE_CHANGED, AppLanguageChanged, mFramework); + AppCoreWatch::AppAddEventHandler(&handlers[AppCoreWatch::REGION_FORMAT_CHANGED], AppCoreWatch::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework); + + ret = watch_app_main(*mFramework->GetArgc(), *mFramework->GetArgv(), &mWatchCallback, mFramework); +#else + DALI_LOG_ERROR("watch feature is not supported"); +#endif + return ret; + } + + void AppExit() + { +#ifdef APPCORE_WATCH_AVAILABLE + watch_app_exit(); +#endif + } + + + Impl(void* data) + : handlers{nullptr, nullptr, nullptr, nullptr, nullptr} +#ifdef APPCORE_WATCH_AVAILABLE + , + mWatchCallback() +#endif + { + mAppModelWatch = static_cast<AppModelWatch*>(data); + } + + ~Impl() + { + } + + AppModelWatch* mAppModelWatch; + AppCoreWatch::AppEventHandlerPtr handlers[5]; +#ifdef APPCORE_WATCH_AVAILABLE + watch_app_lifecycle_callback_s mWatchCallback; +#endif +}; + +AppModelWatch::AppModelWatch() +{ + mImpl = new Impl(this); +} + +AppModelWatch::~AppModelWatch() +{ + delete mImpl; +} + +int AppModelWatch::AppMain(void *data) +{ + return mImpl->AppMain(data); +} + +void AppModelWatch::AppExit() +{ + mImpl->AppExit(); +} + +} // Adaptor +} // Internal +} // Dali + diff --git a/dali/internal/application-model/watch/appmodel-watch-tizen.h b/dali/internal/application-model/watch/appmodel-watch-tizen.h new file mode 100644 index 000000000..f97b23fe5 --- /dev/null +++ b/dali/internal/application-model/watch/appmodel-watch-tizen.h @@ -0,0 +1,56 @@ +#ifndef APPMODEL_WATCH_H +#define APPMODEL_WATCH_H +/* + * Copyright (c) 2024 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. + * + */ + +// INTERNAL INCLUDES +#include <dali/public-api/dali-adaptor-common.h> + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +class AppModelWatch +{ +public: // Construction & Destruction + /** + * Constructor + */ + AppModelWatch(); + + /** + * Destructor + */ + ~AppModelWatch(); + +public: + int AppMain(void* data); + void AppExit(); + +private: // impl members + struct Impl; + Impl* mImpl; +}; + +} +} +} + +#endif // APPMODEL_WATCH_H + diff --git a/dali/internal/application-model/widget/appmodel-widget-tizen.cpp b/dali/internal/application-model/widget/appmodel-widget-tizen.cpp new file mode 100644 index 000000000..109ed100b --- /dev/null +++ b/dali/internal/application-model/widget/appmodel-widget-tizen.cpp @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2024 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. + * + */ + +// CLASS HEADER +#include <dali/internal/application-model/widget/appmodel-widget-tizen.h> + +// EXTERNAL INCLUDES +#include <tizen.h> +#include <bundle.h> +#include <bundle_internal.h> +#include <dlog.h> +#include <widget_base.h> +#include <glib.h> +#include <system_info.h> +#include <system_settings.h> + +#ifdef DALI_ELDBUS_AVAILABLE +#include <Eldbus.h> +#endif // DALI_ELDBUS_AVAILABLE + +// INTERNAL INCLUDES +#include <dali/integration-api/debug.h> +#include <dali/integration-api/trace.h> +#include <dali/internal/system/linux/dali-ecore.h> +#include <dali/internal/adaptor/common/framework.h> +#include <dali/internal/adaptor/tizen-wayland/framework-tizen.h> + +#define DEBUG_PRINTF(fmt, arg...) LOGD(" " fmt, ##arg) + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ + +extern "C" DALI_ADAPTOR_API AppModelWidget* Create() { + print_log(DLOG_INFO, "DALI", "AppModelWidget Create"); + return new AppModelWidget(); +} + +extern "C" DALI_ADAPTOR_API void Destroy(void* p) { + delete p; +} + +extern "C" DALI_ADAPTOR_API int AppMain(bool isUiThread, void* data, void* pData) { + print_log(DLOG_INFO, "DALI", "AppModelWidget AppMain 1"); + AppModelWidget* appWidget = static_cast<AppModelWidget*>(pData); + int ret = 0; + if (appWidget != nullptr) + { + print_log(DLOG_INFO, "DALI", "AppModelWidget AppMain 2"); + ret = appWidget->AppMain(data); + } + else + { + print_log(DLOG_INFO, "DALI", "appWidget is nullptr"); + } + return ret; +} + +extern "C" DALI_ADAPTOR_API void AppExit(AppModelWidget* p) { + p->AppExit(); +} + +namespace +{ +#if defined(DEBUG_ENABLED) +Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS"); +#endif +DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_FRAMEWORK, true); +} // anonymous namespace + +namespace AppCoreWidget +{ +typedef enum +{ + LOW_MEMORY, //< The low memory event + LOW_BATTERY, //< The low battery event + LANGUAGE_CHANGED, //< The system language changed event + DEVICE_ORIENTATION_CHANGED, //< The device orientation changed event + REGION_FORMAT_CHANGED, //< The region format changed event + SUSPENDED_STATE_CHANGED, //< The suspended state changed event of the application + UPDATE_REQUESTED, //< The update requested event. This event can occur when an app needs to be updated. It is dependent on target devices. +} AppEventType; + +static int AppEventConverter[APPCORE_BASE_EVENT_MAX] = +{ + [LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY, + [LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY, + [LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE, + [DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED, + [REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE, + [SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE, +}; + +struct AppEventInfo +{ + AppEventType type; + void* value; +}; + +typedef struct AppEventInfo* AppEventInfoPtr; + +typedef void (*AppEventCallback)(AppEventInfoPtr eventInfo, void* userData); + +struct AppEventHandler +{ + AppEventType type; + AppEventCallback cb; + void* data; + void* raw; +}; + +typedef struct AppEventHandler* AppEventHandlerPtr; + +int EventCallback(void* event, void* data) +{ + AppEventHandlerPtr handler = static_cast<AppEventHandlerPtr>(data); + + struct AppEventInfo appEvent; + + appEvent.type = handler->type; + appEvent.value = event; + + if(handler->cb) + handler->cb(&appEvent, handler->data); + + return 0; +} + +int AppAddEventHandler(AppEventHandlerPtr* eventHandler, AppEventType eventType, AppEventCallback callback, void* userData) +{ + AppEventHandlerPtr handler; + + handler = static_cast<AppEventHandlerPtr>(calloc(1, sizeof(struct AppEventHandler))); + if(!handler) + { + DALI_LOG_ERROR("failed to create handler"); + return TIZEN_ERROR_UNKNOWN; + } + else + { + handler->type = eventType; + handler->cb = callback; + handler->data = userData; + handler->raw = appcore_base_add_event(static_cast<appcore_base_event>(AppEventConverter[static_cast<int>(eventType)]), EventCallback, handler); + + *eventHandler = handler; + + return TIZEN_ERROR_NONE; + } +} +} + +struct DALI_ADAPTOR_API AppModelWidget::Impl +{ + bool IsWidgetFeatureEnabled() + { + static bool feature = false; + static bool retrieved = false; + int ret; + + if(retrieved == true) + { + return feature; + } + + ret = system_info_get_platform_bool("http://tizen.org/feature/shell.appwidget", &feature); + if(ret != SYSTEM_INFO_ERROR_NONE) + { + DALI_LOG_ERROR("failed to get system info"); + return false; + } + + retrieved = true; + return feature; + } + + void AppExit() + { + widget_base_exit(); + } + + static int WidgetAppCreate(void* data) + { + widget_base_on_create(); + return static_cast<int>(static_cast<FrameworkTizen*>(data)->Create()); + } + + static int WidgetAppTerminate(void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + observer->OnTerminate(); + + widget_base_on_terminate(); + return 0; + } + + static void AppInit(int argc, char** argv, void* data) + { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wold-style-cast" + ecore_init(); + ecore_app_args_set(argc, (const char**)argv); + #pragma GCC diagnostic pop + + #ifdef DALI_ELDBUS_AVAILABLE + // Initialize ElDBus. + DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n"); + eldbus_init(); + #endif + } + + static void AppFinish(void) + { + ecore_shutdown(); + + if(getenv("AUL_LOADER_INIT")) + { + setenv("AUL_LOADER_INIT", "0", 1); + ecore_shutdown(); + } + + #ifdef DALI_ELDBUS_AVAILABLE + // Shutdown ELDBus. + DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n"); + eldbus_shutdown(); + #endif + } + + static void AppRun(void* data) + { + ecore_main_loop_begin(); + } + + static void AppExit(void* data) + { + ecore_main_loop_quit(); + } + + + static void AppLanguageChanged(AppCoreWidget::AppEventInfoPtr event, void* data) + { + FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); + Framework::Observer* observer = &framework->GetObserver(); + + if(event && event->value) + { + framework->SetLanguage(std::string(static_cast<const char*>(event->value))); + observer->OnLanguageChanged(); + } + else + { + DALI_LOG_ERROR("NULL pointer in Language changed event\n"); + } + } + + static void AppRegionChanged(AppCoreWidget::AppEventInfoPtr event, void* data) + { + FrameworkTizen* framework = static_cast<FrameworkTizen*>(data); + Framework::Observer* observer = &framework->GetObserver(); + + if(event && event->value) + { + framework->SetRegion(std::string(static_cast<const char*>(event->value))); + observer->OnRegionChanged(); + } + else + { + DALI_LOG_ERROR("NULL pointer in Region changed event\n"); + } + } + + static void AppBatteryLow(AppCoreWidget::AppEventInfoPtr event, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + int status = *static_cast<int*>(event->value); + Dali::DeviceStatus::Battery::Status result = Dali::DeviceStatus::Battery::Status::NORMAL; + + // convert to dali battery status + switch(status) + { + case 1: + { + result = Dali::DeviceStatus::Battery::POWER_OFF; + break; + } + case 2: + { + result = Dali::DeviceStatus::Battery::CRITICALLY_LOW; + break; + } + default: + break; + } + observer->OnBatteryLow(result); + } + + static void AppMemoryLow(AppCoreWidget::AppEventInfoPtr event, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + int status = *static_cast<int*>(event->value); + Dali::DeviceStatus::Memory::Status result = Dali::DeviceStatus::Memory::Status::NORMAL; + + // convert to dali memmory status + switch(status) + { + case 1: + { + result = Dali::DeviceStatus::Memory::NORMAL; + break; + } + case 2: + { + result = Dali::DeviceStatus::Memory::LOW; + break; + } + case 4: + { + result = Dali::DeviceStatus::Memory::CRITICALLY_LOW; + break; + } + default: + break; + } + observer->OnMemoryLow(result); + } + + static void AppDeviceOrientationChanged(AppCoreWidget::AppEventInfoPtr event, void* data) + { + Framework::Observer* observer = &static_cast<FrameworkTizen*>(data)->GetObserver(); + int status = *static_cast<int*>(event->value); + Dali::DeviceStatus::Orientation::Status result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; + + switch(status) + { + case APP_DEVICE_ORIENTATION_0: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_0; + break; + } + case APP_DEVICE_ORIENTATION_90: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_90; + break; + } + case APP_DEVICE_ORIENTATION_180: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_180; + break; + } + case APP_DEVICE_ORIENTATION_270: + { + result = Dali::DeviceStatus::Orientation::Status::ORIENTATION_270; + break; + } + + default: + break; + } + observer->OnDeviceOrientationChanged(result); + } + + int AppMain(void* data) + { + print_log(DLOG_INFO, "DALI", "AppModelWidget AppMain 3"); + if(!IsWidgetFeatureEnabled()) + { + DALI_LOG_ERROR("widget feature is not supported"); + return TIZEN_ERROR_NOT_SUPPORTED; + } + FrameworkTizen* mFramework = static_cast<FrameworkTizen*>(data); + + AppCoreWidget::AppAddEventHandler(&handlers[AppCoreWidget::LOW_BATTERY], AppCoreWidget::LOW_BATTERY, AppBatteryLow, mFramework); + AppCoreWidget::AppAddEventHandler(&handlers[AppCoreWidget::LOW_MEMORY], AppCoreWidget::LOW_MEMORY, AppMemoryLow, mFramework); + AppCoreWidget::AppAddEventHandler(&handlers[AppCoreWidget::DEVICE_ORIENTATION_CHANGED], AppCoreWidget::DEVICE_ORIENTATION_CHANGED, AppDeviceOrientationChanged, mFramework); + AppCoreWidget::AppAddEventHandler(&handlers[AppCoreWidget::LANGUAGE_CHANGED], AppCoreWidget::LANGUAGE_CHANGED, AppLanguageChanged, mFramework); + AppCoreWidget::AppAddEventHandler(&handlers[AppCoreWidget::REGION_FORMAT_CHANGED], AppCoreWidget::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework); + + widget_base_ops ops = widget_base_get_default_ops(); + print_log(DLOG_INFO, "DALI", "AppModelWidget AppMain 4"); + /* override methods */ + ops.create = WidgetAppCreate; + ops.terminate = WidgetAppTerminate; + ops.init = AppInit; + ops.finish = AppFinish; + ops.run = AppRun; + ops.exit = AppExit; + + print_log(DLOG_INFO, "DALI", "AppModelWidget AppMain 5"); + int result = widget_base_init(ops, *mFramework->GetArgc(), *mFramework->GetArgv(), mFramework); + + widget_base_fini(); + print_log(DLOG_INFO, "DALI", "AppModelWidget AppMain 6"); + return result; + } + + Impl(void* data) + : handlers{nullptr, nullptr, nullptr, nullptr, nullptr} + { + mAppModelWidget = static_cast<AppModelWidget*>(data); + } + + ~Impl() + { + } + + AppModelWidget* mAppModelWidget; + AppCoreWidget::AppEventHandlerPtr handlers[5]; +}; // Impl + +AppModelWidget::AppModelWidget() +{ + mImpl = new Impl(this); +} + +AppModelWidget::~AppModelWidget() +{ + delete mImpl; +} + +int AppModelWidget::AppMain(void *data) +{ + return mImpl->AppMain(data); +} + +void AppModelWidget::AppExit() +{ + mImpl->AppExit(); +} + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/application-model/widget/appmodel-widget-tizen.h b/dali/internal/application-model/widget/appmodel-widget-tizen.h new file mode 100644 index 000000000..5ea0f3156 --- /dev/null +++ b/dali/internal/application-model/widget/appmodel-widget-tizen.h @@ -0,0 +1,59 @@ +#ifndef APPMODEL_WIDGET_TIZEN_H +#define APPMODEL_WIDGET_TIZEN_H + +/* + * Copyright (c) 2024 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. + * + */ + +// INTERNAL INCLUDES +#include <dali/public-api/dali-adaptor-common.h> + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +/** + * Plays feedback effects for Dali-Toolkit UI Controls. + */ +class AppModelWidget +{ +public: // Construction & Destruction + /** + * Constructor + */ + AppModelWidget(); + + /** + * Destructor + */ + ~AppModelWidget(); + +public: + int AppMain(void* data); + void AppExit(); + +private: // impl members + struct Impl; + Impl* mImpl; + +}; +} +} +} // Dali + +#endif
\ No newline at end of file diff --git a/dali/internal/application-model/widget/widget-base-tizen.cpp b/dali/internal/application-model/widget/widget-base-tizen.cpp new file mode 100644 index 000000000..d24059394 --- /dev/null +++ b/dali/internal/application-model/widget/widget-base-tizen.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2024 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. + * + */ + +// CLASS HEADER +#include <dali/internal/application-model/widget/widget-base-tizen.h> + + +// INTERNAL INCLUDE +#include <dali/internal/system/tizen-wayland/widget-controller-tizen.h> + +#include <dali/devel-api/events/key-event-devel.h> +#include <dali/internal/adaptor/common/adaptor-impl.h> +#include <dali/internal/system/common/environment-variables.h> + +#include <dali/public-api/adaptor-framework/widget-impl.h> +#include <dali/public-api/adaptor-framework/widget.h> +#include <dali/internal/system/tizen-wayland/widget-application-impl-tizen.h> + +// EXTERNAL INCLUDES +#include <bundle.h> +#include <widget_base.h> +#include <dlog.h> +#include <tizen.h> + +#define DEBUG_PRINTF(fmt, arg...) LOGD(" " fmt, ##arg) + +namespace Dali +{ +namespace Internal +{ +namespace +{ + +int OnInstanceInit(widget_base_instance_h instanceHandle, bundle* content, int w, int h, void* classData) +{ + char* id; + widget_base_context_get_id(instanceHandle, &id); + + widget_base_class_on_create(instanceHandle, content, w, h); + + Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); + + Dali::Window window; + if(application->GetWidgetCount() == 0) + { + window = application->GetWidgetWindow(); + DALI_LOG_RELEASE_INFO("Widget Instance use default Window(win:%p), so it need to bind widget (%dx%d) (id:%s) \n", window, w, h, std::string(id).c_str()); + + } + else + { + window = Dali::Window::New(PositionSize(0, 0, w, h), "", false); + if(window) + { + DALI_LOG_RELEASE_INFO("Widget Instance create new Window (win:%p, cnt:%d) (%dx%d) (id:%s )\n", window, application->GetWidgetCount(), w, h, std::string(id).c_str()); + } + else + { + DALI_LOG_ERROR("This device can't support Multi Widget. it means UI may not be properly drawn."); + window = application->GetWidgetWindow(); + } + } + + Any nativeHandle = window.GetNativeHandle(); + +#ifdef ECORE_WAYLAND2 + Ecore_Wl2_Window* wlWindow = AnyCast<Ecore_Wl2_Window*>(nativeHandle); +#else + Ecore_Wl_Window* wlWindow = AnyCast<Ecore_Wl_Window*>(nativeHandle); +#endif + + widget_base_context_window_bind(instanceHandle, id, wlWindow); + window.SetSize(Dali::Window::WindowSize(w, h)); + + Dali::Internal::Adaptor::WidgetApplication::CreateWidgetFunctionPair pair = application->GetWidgetCreatingFunctionPair(std::string(id)); + Dali::WidgetApplication::CreateWidgetFunction createFunction = pair.second; + + Dali::Widget widgetInstance = createFunction(pair.first); + + application->InitializeWidget(instanceHandle, widgetInstance); + + application->AddWidget(instanceHandle, widgetInstance, window, std::string(id)); + + std::string encodedContentString = ""; + + if(bundle_get_count(content)) + { + bundle_raw* bundleRaw; + int len; + bundle_encode(content, &bundleRaw, &len); + char* encodedContent = reinterpret_cast<char*>(bundleRaw); + encodedContentString = std::string(encodedContent); + free(bundleRaw); + } + + Internal::Adaptor::GetImplementation(widgetInstance).OnCreate(encodedContentString, window); + + // connect keyEvent for widget +#ifdef OVER_TIZEN_VERSION_7 + application->ConnectKeyEvent(window); +#endif + + return 0; +} + +int OnInstanceDestroy(widget_base_instance_h instanceHandle, widget_base_destroy_type_e reason, bundle* content, void* classData) +{ + Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); + + // Get Dali::Widget instance. + Dali::Widget widgetInstance = application->GetWidget(instanceHandle); + + Dali::Widget::Termination destroyReason = Dali::Widget::Termination::TEMPORARY; + + if(reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) + { + destroyReason = Dali::Widget::Termination::PERMANENT; + } + + std::string encodedContentString = ""; + + if(bundle_get_count(content)) + { + bundle_raw* bundleRaw; + int len; + bundle_encode(content, &bundleRaw, &len); + char* encodedContent = reinterpret_cast<char*>(bundleRaw); + encodedContentString = std::string(encodedContent); + free(bundleRaw); + } + + Internal::Adaptor::GetImplementation(widgetInstance).OnTerminate(encodedContentString, destroyReason); + + widget_base_class_on_destroy(instanceHandle, reason, content); + + application->DeleteWidget(instanceHandle); + + return 0; +} + +int OnInstancePause(widget_base_instance_h instanceHandle, void* classData) +{ + widget_base_class_on_pause(instanceHandle); + + Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); + + // Get Dali::Widget instance. + Dali::Widget widgetInstance = application->GetWidget(instanceHandle); + + Internal::Adaptor::GetImplementation(widgetInstance).OnPause(); + + return 0; +} + +int OnInstanceResume(widget_base_instance_h instanceHandle, void* classData) +{ + widget_base_class_on_resume(instanceHandle); + + Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); + + // Get Dali::Widget instance. + Dali::Widget widgetInstance = application->GetWidget(instanceHandle); + + Internal::Adaptor::GetImplementation(widgetInstance).OnResume(); + return 0; +} + +int OnInstanceResize(widget_base_instance_h instanceHandle, int w, int h, void* classData) +{ + widget_base_class_on_resize(instanceHandle, w, h); + + Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); + + // Get Dali::Widget instance. + Dali::Widget widgetInstance = application->GetWidget(instanceHandle); + Dali::Window window = application->GetWindowFromWidget(widgetInstance); + window.SetSize(Dali::Window::WindowSize(w, h)); + Internal::Adaptor::GetImplementation(widgetInstance).OnResize(window); + + return 0; +} + +int OnInstanceUpdate(widget_base_instance_h instanceHandle, bundle* content, int force, void* classData) +{ + widget_base_class_on_update(instanceHandle, content, force); + + Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); + + // Get Dali::Widget instance. + Dali::Widget widgetInstance = application->GetWidget(instanceHandle); + + std::string encodedContentString = ""; + + if(bundle_get_count(content)) + { + bundle_raw* bundleRaw; + int len; + bundle_encode(content, &bundleRaw, &len); + char* encodedContent = reinterpret_cast<char*>(bundleRaw); + encodedContentString = std::string(encodedContent); + free(bundleRaw); + } + Internal::Adaptor::GetImplementation(widgetInstance).OnUpdate(encodedContentString, force); + + return 0; +} +} +namespace Adaptor +{ +extern "C" DALI_ADAPTOR_API void RegisterWidgetCallback(const char* widgetName, void* data) { + widget_base_class cls = widget_base_class_get_default(); + cls.ops.create = OnInstanceInit; + cls.ops.destroy = OnInstanceDestroy; + cls.ops.pause = OnInstancePause; + cls.ops.resume = OnInstanceResume; + cls.ops.resize = OnInstanceResize; + cls.ops.update = OnInstanceUpdate; + + widget_base_class_add(cls, widgetName, data); +} + +extern "C" DALI_ADAPTOR_API void SetContentInfo(void* handle, bundle* bundleData) { + widget_base_instance_h handle_instance = static_cast<widget_base_instance_h>(handle); + //bundle* bundle = static_cast<bundle*>(bundleData); + widget_base_context_set_content_info(handle_instance, bundleData); +} +} +} +} diff --git a/dali/internal/application-model/widget/widget-base-tizen.h b/dali/internal/application-model/widget/widget-base-tizen.h new file mode 100644 index 000000000..7913d8d0a --- /dev/null +++ b/dali/internal/application-model/widget/widget-base-tizen.h @@ -0,0 +1,52 @@ +#ifndef WIDGET_BASE_TIZEN_H +#define WIDGET_BASE_TIZEN_H + +/* + * Copyright (c) 2024 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. + * + */ + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +/** + * Plays feedback effects for Dali-Toolkit UI Controls. + */ +class WidgetBase +{ +public: // Construction & Destruction + /** + * Constructor + */ + WidgetBase(); + + /** + * Destructor + */ + ~WidgetBase(); + +private: // impl members + struct Impl; + Impl* mImpl; + +}; +} +} +} // Dali + +#endif
\ No newline at end of file diff --git a/dali/internal/system/tizen-wayland/widget-application-impl-tizen.cpp b/dali/internal/system/tizen-wayland/widget-application-impl-tizen.cpp index bd76bf4ab..789eea5f6 100644 --- a/dali/internal/system/tizen-wayland/widget-application-impl-tizen.cpp +++ b/dali/internal/system/tizen-wayland/widget-application-impl-tizen.cpp @@ -19,23 +19,35 @@ #include <dali/internal/system/tizen-wayland/widget-application-impl-tizen.h> // INTERNAL INCLUDE +#include <dali/internal/system/tizen-wayland/widget-controller-tizen.h> #include <dali/devel-api/events/key-event-devel.h> #include <dali/internal/adaptor/common/adaptor-impl.h> #include <dali/internal/system/common/environment-variables.h> -#include <dali/internal/system/tizen-wayland/widget-controller-tizen.h> + #include <dali/public-api/adaptor-framework/widget-impl.h> #include <dali/public-api/adaptor-framework/widget.h> // EXTERNAL INCLUDES #include <bundle.h> -#include <widget_base.h> - +#include <dlfcn.h> +#include <dlog.h> +#include <tizen.h> namespace Dali { namespace Internal { namespace { +constexpr char const* const kApplicationNamePrefix = "libdali2-adaptor-application-"; +constexpr char const* const kApplicationNamePostfix = ".so"; + +std::string MakePluginName(const char* appModelName) +{ + std::stringstream fullName; + fullName << kApplicationNamePrefix << appModelName << kApplicationNamePostfix; + return fullName.str(); +} + /** * This Api is called when widget viewer send keyEvent. * In this API, widget framework create a new keyEvent, find the proper widget and send this event. @@ -75,182 +87,6 @@ bool OnKeyEventCallback(const char* id, screen_connector_event_type_e eventType, } #endif -int OnInstanceInit(widget_base_instance_h instanceHandle, bundle* content, int w, int h, void* classData) -{ - char* id; - widget_base_context_get_id(instanceHandle, &id); - - widget_base_class_on_create(instanceHandle, content, w, h); - - Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); - - Dali::Window window; - if(application->GetWidgetCount() == 0) - { - window = application->GetWindow(); - DALI_LOG_RELEASE_INFO("Widget Instance use default Window(win:%p), so it need to bind widget (%dx%d) (id:%s) \n", window, w, h, std::string(id).c_str()); - } - else - { - window = Dali::Window::New(PositionSize(0, 0, w, h), "", false); - if(window) - { - DALI_LOG_RELEASE_INFO("Widget Instance create new Window (win:%p, cnt:%d) (%dx%d) (id:%s )\n", window, application->GetWidgetCount(), w, h, std::string(id).c_str()); - } - else - { - DALI_LOG_ERROR("This device can't support Multi Widget. it means UI may not be properly drawn."); - window = application->GetWindow(); - } - } - - Any nativeHandle = window.GetNativeHandle(); - -#ifdef ECORE_WAYLAND2 - Ecore_Wl2_Window* wlWindow = AnyCast<Ecore_Wl2_Window*>(nativeHandle); -#else - Ecore_Wl_Window* wlWindow = AnyCast<Ecore_Wl_Window*>(nativeHandle); -#endif - - widget_base_context_window_bind(instanceHandle, id, wlWindow); - window.SetSize(Dali::Window::WindowSize(w, h)); - - Dali::Internal::Adaptor::WidgetApplication::CreateWidgetFunctionPair pair = application->GetWidgetCreatingFunctionPair(std::string(id)); - Dali::WidgetApplication::CreateWidgetFunction createFunction = pair.second; - - Dali::Widget widgetInstance = createFunction(pair.first); - - Dali::Internal::Adaptor::Widget::Impl* widgetImpl = new Dali::Internal::Adaptor::WidgetImplTizen(instanceHandle); - Internal::Adaptor::GetImplementation(widgetInstance).SetImpl(widgetImpl); - - application->AddWidget(instanceHandle, widgetInstance, window, std::string(id)); - - std::string encodedContentString = ""; - - if(bundle_get_count(content)) - { - bundle_raw* bundleRaw; - int len; - bundle_encode(content, &bundleRaw, &len); - char* encodedContent = reinterpret_cast<char*>(bundleRaw); - encodedContentString = std::string(encodedContent); - free(bundleRaw); - } - - Internal::Adaptor::GetImplementation(widgetInstance).OnCreate(encodedContentString, window); - - // connect keyEvent for widget -#ifdef OVER_TIZEN_VERSION_7 - application->ConnectKeyEvent(window); -#endif - - return 0; -} - -int OnInstanceDestroy(widget_base_instance_h instanceHandle, widget_base_destroy_type_e reason, bundle* content, void* classData) -{ - Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); - - // Get Dali::Widget instance. - Dali::Widget widgetInstance = application->GetWidget(instanceHandle); - - Dali::Widget::Termination destroyReason = Dali::Widget::Termination::TEMPORARY; - - if(reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) - { - destroyReason = Dali::Widget::Termination::PERMANENT; - } - - std::string encodedContentString = ""; - - if(bundle_get_count(content)) - { - bundle_raw* bundleRaw; - int len; - bundle_encode(content, &bundleRaw, &len); - char* encodedContent = reinterpret_cast<char*>(bundleRaw); - encodedContentString = std::string(encodedContent); - free(bundleRaw); - } - - Internal::Adaptor::GetImplementation(widgetInstance).OnTerminate(encodedContentString, destroyReason); - - widget_base_class_on_destroy(instanceHandle, reason, content); - - application->DeleteWidget(instanceHandle); - - return 0; -} - -int OnInstancePause(widget_base_instance_h instanceHandle, void* classData) -{ - widget_base_class_on_pause(instanceHandle); - - Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); - - // Get Dali::Widget instance. - Dali::Widget widgetInstance = application->GetWidget(instanceHandle); - - Internal::Adaptor::GetImplementation(widgetInstance).OnPause(); - - return 0; -} - -int OnInstanceResume(widget_base_instance_h instanceHandle, void* classData) -{ - widget_base_class_on_resume(instanceHandle); - - Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); - - // Get Dali::Widget instance. - Dali::Widget widgetInstance = application->GetWidget(instanceHandle); - - Internal::Adaptor::GetImplementation(widgetInstance).OnResume(); - - return 0; -} - -int OnInstanceResize(widget_base_instance_h instanceHandle, int w, int h, void* classData) -{ - widget_base_class_on_resize(instanceHandle, w, h); - - Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); - - // Get Dali::Widget instance. - Dali::Widget widgetInstance = application->GetWidget(instanceHandle); - Dali::Window window = application->GetWindowFromWidget(widgetInstance); - window.SetSize(Dali::Window::WindowSize(w, h)); - Internal::Adaptor::GetImplementation(widgetInstance).OnResize(window); - - return 0; -} - -int OnInstanceUpdate(widget_base_instance_h instanceHandle, bundle* content, int force, void* classData) -{ - widget_base_class_on_update(instanceHandle, content, force); - - Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(classData); - - // Get Dali::Widget instance. - Dali::Widget widgetInstance = application->GetWidget(instanceHandle); - - std::string encodedContentString = ""; - - if(bundle_get_count(content)) - { - bundle_raw* bundleRaw; - int len; - bundle_encode(content, &bundleRaw, &len); - char* encodedContent = reinterpret_cast<char*>(bundleRaw); - encodedContentString = std::string(encodedContent); - free(bundleRaw); - } - - Internal::Adaptor::GetImplementation(widgetInstance).OnUpdate(encodedContentString, force); - - return 0; -} - unsigned int GetEnvWidgetRenderRefreshRate() { const char* envVariable = std::getenv(DALI_WIDGET_REFRESH_RATE); @@ -282,20 +118,39 @@ WidgetApplicationTizen::~WidgetApplicationTizen() { } +void WidgetApplicationTizen::InitializeWidget(void* instanceHandle, Dali::Widget widgetInstance) +{ + Dali::Internal::Adaptor::Widget::Impl* widgetImpl = new Dali::Internal::Adaptor::WidgetImplTizen(instanceHandle); + Internal::Adaptor::GetImplementation(widgetInstance).SetImpl(widgetImpl); +} + void WidgetApplicationTizen::RegisterWidgetCreatingFunction(const std::string& widgetName, Dali::WidgetApplication::CreateWidgetFunction createFunction) { AddWidgetCreatingFunctionPair(CreateWidgetFunctionPair(widgetName, createFunction)); - // Register widget class to widget framework - widget_base_class cls = widget_base_class_get_default(); - cls.ops.create = OnInstanceInit; - cls.ops.destroy = OnInstanceDestroy; - cls.ops.pause = OnInstancePause; - cls.ops.resume = OnInstanceResume; - cls.ops.resize = OnInstanceResize; - cls.ops.update = OnInstanceUpdate; + using RegisterFunction = void (*)(const char*, void*); + RegisterFunction registerFunctionPtr; + std::string pluginName = MakePluginName("widget"); + + void* mHandle = dlopen(pluginName.c_str(), RTLD_LAZY); - widget_base_class_add(cls, widgetName.c_str(), this); + if(mHandle == nullptr) + { + print_log(DLOG_INFO, "DALI", "error : %s", dlerror() ); + return; + } + + registerFunctionPtr = reinterpret_cast<RegisterFunction>(dlsym(mHandle, "RegisterWidgetCallback")); + if(registerFunctionPtr == nullptr) + { + DALI_LOG_ERROR("createFunctionPtr is null\n"); + } + registerFunctionPtr(widgetName.c_str(), this); + + if(mHandle!=NULL) + { + dlclose(mHandle); + } } void WidgetApplicationTizen::AddWidgetCreatingFunctionPair(CreateWidgetFunctionPair pair) @@ -318,13 +173,13 @@ WidgetApplicationTizen::CreateWidgetFunctionPair WidgetApplicationTizen::GetWidg return CreateWidgetFunctionPair("", NULL); } -void WidgetApplicationTizen::AddWidget(widget_base_instance_h widgetBaseInstance, Dali::Widget widget, Dali::Window window, const std::string& widgetId) +void WidgetApplicationTizen::AddWidget(void* widgetBaseInstance, Dali::Widget widget, Dali::Window window, const std::string& widgetId) { mWidgetInstanceContainer.push_back(WidgetInstancePair(widgetBaseInstance, widget)); Internal::Adaptor::GetImplementation(widget).SetInformation(window, widgetId); } -Dali::Widget WidgetApplicationTizen::GetWidget(widget_base_instance_h widgetBaseInstance) const +Dali::Widget WidgetApplicationTizen::GetWidget(void* widgetBaseInstance) const { for(auto&& iter : mWidgetInstanceContainer) { @@ -336,7 +191,7 @@ Dali::Widget WidgetApplicationTizen::GetWidget(widget_base_instance_h widgetBase return Dali::Widget(); } -void WidgetApplicationTizen::DeleteWidget(widget_base_instance_h widgetBaseInstance) +void WidgetApplicationTizen::DeleteWidget(void* widgetBaseInstance) { // Delete WidgetInstance auto widgetInstance = std::find_if(mWidgetInstanceContainer.begin(), @@ -359,7 +214,7 @@ Dali::Window WidgetApplicationTizen::GetWindowFromWidget(Dali::Widget widgetInst return Dali::Window(); } -widget_base_instance_h WidgetApplicationTizen::GetWidgetInstanceFromWidgetId(std::string& widgetId) const +void* WidgetApplicationTizen::GetWidgetInstanceFromWidgetId(std::string& widgetId) const { for(auto&& iter : mWidgetInstanceContainer) { @@ -377,6 +232,11 @@ int WidgetApplicationTizen::GetWidgetCount() return mWidgetInstanceContainer.size(); } +Dali::Window WidgetApplicationTizen::GetWidgetWindow() +{ + return GetWindow(); +} + void WidgetApplicationTizen::ConnectKeyEvent(Dali::Window window) { if(!mConnectedKeyEvent) @@ -395,7 +255,7 @@ void WidgetApplicationTizen::OnWindowKeyEvent(const Dali::KeyEvent& event) mReceivedKeyEvent = true; } -bool WidgetApplicationTizen::FeedKeyEvent(widget_base_instance_h instanceHandle, const Dali::KeyEvent& keyEvent) +bool WidgetApplicationTizen::FeedKeyEvent(void* instanceHandle, const Dali::KeyEvent& keyEvent) { bool consumed = true; @@ -443,7 +303,6 @@ Dali::Internal::Adaptor::WidgetApplicationPtr Create(int* argc, char** argv[], c { return WidgetApplicationTizen::New(argc, argv, stylesheet, windowData); } - } // namespace WidgetApplicationFactory } // namespace Adaptor diff --git a/dali/internal/system/tizen-wayland/widget-application-impl-tizen.h b/dali/internal/system/tizen-wayland/widget-application-impl-tizen.h index 8b20e8042..b42d8f185 100644 --- a/dali/internal/system/tizen-wayland/widget-application-impl-tizen.h +++ b/dali/internal/system/tizen-wayland/widget-application-impl-tizen.h @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include <screen_connector_provider.h> -#include <widget_base.h> // INTERNAL INCLUDES #include <dali/devel-api/adaptor-framework/window-devel.h> @@ -41,7 +40,7 @@ typedef IntrusivePtr<WidgetApplication> WidgetApplicationPtr; /** * Implementation of the WidgetApplication class. */ -class WidgetApplicationTizen : public WidgetApplication, public ConnectionTracker +class DALI_ADAPTOR_API WidgetApplicationTizen : public WidgetApplication, public ConnectionTracker { public: typedef std::pair<const std::string, Dali::WidgetApplication::CreateWidgetFunction> CreateWidgetFunctionPair; @@ -63,6 +62,11 @@ public: void OnInit() override; /** + * @copydoc This function creates and initalizes a new Widget instance + */ + void InitializeWidget(void* instanceHandle, Dali::Widget widgetInstance); + + /** * @copydoc Dali::WidgetApplication::RegisterWidgetCreator() */ void RegisterWidgetCreatingFunction(const std::string& widgetName, Dali::WidgetApplication::CreateWidgetFunction createFunction) override; @@ -80,17 +84,17 @@ public: /** * Add widget_base_instance_h - Widget instance pair to container. */ - void AddWidget(widget_base_instance_h widgetBaseInstance, Dali::Widget widget, Dali::Window window, const std::string& widgetId); + void AddWidget(void* widgetBaseInstance, Dali::Widget widget, Dali::Window window, const std::string& widgetId); /** * Find and get Widget instance in container by widget_base_instance_h. */ - Dali::Widget GetWidget(widget_base_instance_h widgetBaseInstance) const; + Dali::Widget GetWidget(void* widgetBaseInstance) const; /** * Delete widget_base_instance_h - Widget instance pair in container. */ - void DeleteWidget(widget_base_instance_h widgetBaseInstance); + void DeleteWidget(void* widgetBaseInstance); /** * Find and get Window instance in container by widget_base_instance_h. @@ -100,13 +104,19 @@ public: /** * Find and get widget_base_instance in container by widget id. */ - widget_base_instance_h GetWidgetInstanceFromWidgetId(std::string& widgetId) const; + void* GetWidgetInstanceFromWidgetId(std::string& widgetId) const; + /** * Get the number of created widget. */ int32_t GetWidgetCount(); /** + * Get the number of created widget. + */ + Dali::Window GetWidgetWindow(); + + /** * @brief connect the keyEvent for window * * @param[in] window window for connecting keyEvent @@ -129,7 +139,7 @@ public: * @param[in] keyEvent The key event for widget * @return True if widget consume keyEvent, false otherwise. */ - bool FeedKeyEvent(widget_base_instance_h instanceHandle, const Dali::KeyEvent& keyEvent); + bool FeedKeyEvent(void* instanceHandle, const Dali::KeyEvent& keyEvent); protected: /** @@ -150,7 +160,7 @@ protected: WidgetApplicationTizen& operator=(Application&) = delete; private: - typedef std::pair<widget_base_instance_h, Dali::Widget> WidgetInstancePair; + typedef std::pair<void*, Dali::Widget> WidgetInstancePair; typedef std::vector<WidgetInstancePair> WidgetInstanceContainer; CreateWidgetFunctionContainer mCreateWidgetFunctionContainer; diff --git a/dali/internal/system/tizen-wayland/widget-controller-tizen.cpp b/dali/internal/system/tizen-wayland/widget-controller-tizen.cpp index 5e03ef1d4..18c13aed6 100644 --- a/dali/internal/system/tizen-wayland/widget-controller-tizen.cpp +++ b/dali/internal/system/tizen-wayland/widget-controller-tizen.cpp @@ -21,19 +21,35 @@ // EXTERNAL INCLUDES #include <dali/public-api/actors/layer.h> #include <bundle.h> -#include <widget_base.h> +#include <dlfcn.h> +#include <dlog.h> +#include <tizen.h> // INTERNAL INCLUDES #include <dali/devel-api/adaptor-framework/accessibility-bridge.h> #include <dali/devel-api/atspi-interfaces/accessible.h> +#include <dali/integration-api/debug.h> namespace Dali { namespace Internal { +namespace +{ +constexpr char const* const kApplicationNamePrefix = "libdali2-adaptor-application-"; +constexpr char const* const kApplicationNamePostfix = ".so"; + +std::string MakePluginName(const char* appModelName) +{ + std::stringstream fullName; + fullName << kApplicationNamePrefix << appModelName << kApplicationNamePostfix; + return fullName.str(); +} + +} namespace Adaptor { -WidgetImplTizen::WidgetImplTizen(widget_base_instance_h instanceHandle) +WidgetImplTizen::WidgetImplTizen(void* instanceHandle) : Widget::Impl(), mInstanceHandle(instanceHandle), mWindow(), @@ -53,9 +69,33 @@ void WidgetImplTizen::SetContentInfo(const std::string& contentInfo) int len = contentInfo.length(); contentBundle = bundle_decode(contentBundleRaw, len); - widget_base_context_set_content_info(mInstanceHandle, contentBundle); + + using SetContentInfoFunc = void (*)(void*, bundle*); + SetContentInfoFunc setContentInfoFuncPtr; + std::string pluginName = MakePluginName("widget"); + + void* mHandle = dlopen(pluginName.c_str(), RTLD_LAZY); + + if(mHandle == nullptr) + { + print_log(DLOG_ERROR, "DALI", "error : %s", dlerror() ); + return; + } + + setContentInfoFuncPtr = reinterpret_cast<SetContentInfoFunc>(dlsym(mHandle, "SetContentInfo")); + if(setContentInfoFuncPtr == nullptr) + { + print_log(DLOG_ERROR, "DALI", "SetContentInfo is null\n" ); + return; + } + setContentInfoFuncPtr(mInstanceHandle, contentBundle); bundle_free(contentBundle); + + if(mHandle!=NULL) + { + dlclose(mHandle); + } } bool WidgetImplTizen::IsKeyEventUsing() const |