diff options
Diffstat (limited to 'src/app_main.cc')
-rw-r--r-- | src/app_main.cc | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/app_main.cc b/src/app_main.cc new file mode 100644 index 0000000..771d0ea --- /dev/null +++ b/src/app_main.cc @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2011 - 2021 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <app_common_internal.h> +#include <app_control_internal.h> +#include <dlog.h> +#include <tizen_error.h> + +#include <app_core_efl_base.hh> +#include <app_event_internal.hh> + +#include <list> +#include <memory> + +#include "app_internal.h" +#include "common_private.hh" +#include "log_private.hh" + +namespace { + +using namespace tizen_cpp; + +class UiAppContext : public AppCoreEflBase { + public: + enum AppState { + APP_STATE_NOT_RUNNING, + APP_STATE_CREATING, + APP_STATE_RUNNING, + }; + + UiAppContext(ui_app_lifecycle_callback_s callback, void* data, + unsigned int hint) + : AppCoreEflBase(hint), callback_(callback), data_(data) { + SetAppState(APP_STATE_CREATING); + } + + void Run(int argc, char** argv) override { + SetAppState(APP_STATE_RUNNING); + AppCoreEflBase::Run(argc, argv); + SetAppState(APP_STATE_NOT_RUNNING); + } + + int OnCreate() override { + LOGW("ui_app_create()"); + if (callback_.create == nullptr || callback_.create(data_) == false) + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, + "app_create_cb() returns false"); + AppCoreEflBase::OnCreate(); + + return APP_ERROR_NONE; + } + + int OnControl(tizen_base::Bundle b) override { + app_control_h app_control = nullptr; + + LOGW("ui_app_control()"); + AppCoreEflBase::OnControl(b); + + if (b.GetHandle()) { + int ret = app_control_create_event(b.GetHandle(), &app_control); + if (ret != APP_ERROR_NONE) { + _E("Failed to create an app_control handle"); + return APP_ERROR_INVALID_PARAMETER; + } + } else { + if (app_control_create(&app_control) != APP_ERROR_NONE) { + _E("Failed to create an app_control handle"); + return APP_ERROR_OUT_OF_MEMORY; + } + } + + if (callback_.app_control) + callback_.app_control(app_control, data_); + + app_control_destroy(app_control); + return APP_ERROR_NONE; + } + + int OnTerminate() override { + LOGW("ui_app_terminate()"); + AppCoreEflBase::OnTerminate(); + + if (callback_.terminate) + callback_.terminate(data_); + + return APP_ERROR_NONE; + } + + int OnPause() override { + LOGW("ui_app_pause()"); + AppCoreEflBase::OnPause(); + if (callback_.pause) + callback_.pause(data_); + return APP_ERROR_NONE; + } + + int OnResume() override { + LOGW("ui_app_resume"); + AppCoreEflBase::OnResume(); + if (callback_.resume) + callback_.resume(data_); + return APP_ERROR_NONE; + } + + AppState GetAppState() const { + return state_; + } + + void SetAppState(AppState state) { + state_ = state; + } + + private: + ui_app_lifecycle_callback_s callback_; + void* data_; + AppState state_ = APP_STATE_NOT_RUNNING; +}; + +constexpr int UI_APP_EVENT_MAX = 7; +constexpr IAppCore::IEvent::Type __app_event_converter[UI_APP_EVENT_MAX] = { + [APP_EVENT_LOW_MEMORY] = + IAppCore::IEvent::Type::LOW_MEMORY, + [APP_EVENT_LOW_BATTERY] = + IAppCore::IEvent::Type::LOW_BATTERY, + [APP_EVENT_LANGUAGE_CHANGED] = + IAppCore::IEvent::Type::LANG_CHANGE, + [APP_EVENT_DEVICE_ORIENTATION_CHANGED] = + IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, + [APP_EVENT_REGION_FORMAT_CHANGED] = + IAppCore::IEvent::Type::REGION_CHANGE, + [APP_EVENT_SUSPENDED_STATE_CHANGED] = + IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE, + [APP_EVENT_UPDATE_REQUESTED] = + IAppCore::IEvent::Type::UPDATE_REQUESTED, +}; + +std::unique_ptr<UiAppContext> __context; +std::list<std::shared_ptr<AppEvent>> __pending_app_events; + +} // namespace + +API int ui_app_main(int argc, char** argv, + ui_app_lifecycle_callback_s* callback, void* user_data) { + if (argc < 1 || argv == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return APP_ERROR_INVALID_PARAMETER; + } + + if (callback->create == nullptr) { + _E("app_create_cb() callback MUST be registerted"); + return APP_ERROR_INVALID_PARAMETER; + } + + if (__context.get() != nullptr && + __context->GetAppState() != UiAppContext::APP_STATE_NOT_RUNNING) { + _E("Already running"); + return APP_ERROR_ALREADY_RUNNING; + } + + unsigned int hint = AppCoreEflBase::HINT_WINDOW_GROUP_CONTROL | + AppCoreEflBase::HINT_WINDOW_STACK_CONTROL | + AppCoreEflBase::HINT_BG_LAUNCH_CONTROL | + AppCoreEflBase::HINT_HW_ACC_CONTROL | + AppCoreEflBase::HINT_WINDOW_AUTO_CONTROL | + AppCoreEflBase::HINT_LEGACY_CONTROL | + AppCoreEflBase::HINT_WINDOW_ID_CONTROL; + + LOGW("ui_app_main()"); + try { + __context = std::make_unique<UiAppContext>(*callback, user_data, hint); + for (auto i : __pending_app_events) + __context->AddEvent(i); + + __context->Run(argc, argv); + } catch (std::runtime_error& e) { + __context->SetAppState(UiAppContext::APP_STATE_NOT_RUNNING); + } + + return APP_ERROR_NONE; +} + +API void ui_app_exit(void) { + LOGW("ui_app_exit()"); + if (__context.get() && + __context->GetAppState() == UiAppContext::APP_STATE_RUNNING) + __context->Exit(); +} + +API int ui_app_add_event_handler(app_event_handler_h* event_handler, + app_event_type_e event_type, app_event_cb callback, void* user_data) { + if (event_handler == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return APP_ERROR_INVALID_PARAMETER; + } + + if (event_type < APP_EVENT_LOW_MEMORY || + event_type > APP_EVENT_UPDATE_REQUESTED) { + _E("Invalid event type"); + return APP_ERROR_INVALID_PARAMETER; + } + + auto* ae = new (std::nothrow) AppEvent(__app_event_converter[event_type], + callback, user_data); + if (ae == nullptr) { + _E("Out of memory"); + return APP_ERROR_OUT_OF_MEMORY; + } + + auto* h = new (std::nothrow) std::shared_ptr<AppEvent>(ae); + if (h == nullptr) { + _E("Out of memory"); + delete ae; + return APP_ERROR_OUT_OF_MEMORY; + } + + if (__context.get() && + __context->GetAppState() == UiAppContext::APP_STATE_RUNNING) { + __context->AddEvent(*h); + } else { + __pending_app_events.push_back(*h); + } + + *event_handler = reinterpret_cast<app_event_handler_h>(h); + return APP_ERROR_NONE; +} + +API int ui_app_remove_event_handler(app_event_handler_h event_handler) { + if (event_handler == nullptr) { + _E("Invalid parameter"); + return APP_ERROR_INVALID_PARAMETER; + } + + auto* eb = reinterpret_cast<std::shared_ptr<AppEvent>*>(event_handler); + auto type = (*eb)->GetType(); + if (type < IAppCore::IEvent::Type::LOW_MEMORY || + type > IAppCore::IEvent::Type::UPDATE_REQUESTED) { + _E("invalid parameter"); + return APP_ERROR_INVALID_PARAMETER; + } + + if (__context.get() && + __context->GetAppState() == UiAppContext::APP_STATE_RUNNING) { + if (!__context->RemoveEvent(*eb)) { + _E("Invalid handle"); + return APP_ERROR_INVALID_PARAMETER; + } + } else { + __pending_app_events.remove(*eb); + } + + delete eb; + return APP_ERROR_NONE; +} |