summaryrefslogtreecommitdiff
path: root/src/app_main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/app_main.cc')
-rw-r--r--src/app_main.cc266
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;
+}