Separate rotation implementation from app-core-cpp
[platform/core/appfw/app-core.git] / tizen-cpp / app-core-ui-cpp / app_core_ui_base.cc
index f5b0d9b..beeef29 100644 (file)
@@ -21,6 +21,9 @@
 #include <aul_rpc_port.h>
 #include <aul_svc.h>
 #include <bundle_internal.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <ttrace.h>
 #include <unistd.h>
 #include <memory>
 #include <string>
 #include <thread>
+#include <utility>
 
 #include "app-core-cpp/app_core_base.hh"
+#include "app-core-rotation-cpp/app_core_rotation.hh"
 #include "app-core-ui-cpp/api/app_core_ui_base.h"
 #include "app-core-ui-cpp/app_core_task_base.hh"
 #include "app-core-ui-cpp/app_core_ui_delegator_private.hh"
 #include "app-core-ui-cpp/app_core_ui_plugin_private.hh"
+#include "app-core-ui-cpp/app_core_ui_thread_base.hh"
 #include "app-core-ui-cpp/wayland_handler_private.hh"
+#include "app-core-ui-cpp/window_position_private.hh"
 #include "common/ecore_handler.hh"
 #include "common/glib_private.hh"
 #include "common/log_private.hh"
+#include "common/log_tracer.hh"
 
 namespace tizen_cpp {
 
 constexpr const char K_SERVICE_THREAD[] = "__K_SERVICE_THREAD";
+constexpr const char K_HINT_RECENT_SCREEN_POSITION[] =
+    "__K_HINT_RECENT_SCREEN_POSITION";
+const int APPID_MAX = 256;
 
-class AppCoreUiBase::Impl {
+class AppCoreUiBase::Impl : public AppCoreRotation::IEventListener {
  public:
   Impl(AppCoreUiBase* parent, unsigned int hint)
       : parent_(parent),
         hint_(hint),
         handler_(std::make_shared<EcoreHandler>(parent)),
-        wl_handler_(new WaylandHandler()) {
+        wl_handler_(new WaylandHandler()),
+        wp_manager_(new WindowPositionManager()) {
   }
 
  private:
@@ -105,8 +117,15 @@ class AppCoreUiBase::Impl {
   int FiniWl();
   void PluginInit(int argc, char** argv);
   void PluginFini();
+  void SetWindowPosition(const tizen_base::Bundle& b);
+  void SetWindowPosition();
+  void SetWindow(unsigned int wid);
+  Ecore_Wl2_Window* GetWindow() const;
   void Run(int argc, char** argv);
   void Exit();
+  void RotationInit();
+  void RotationShutdown();
+  void OnRotationChanged(int degree) override;
 
   std::list<std::shared_ptr<WinNode>> winnode_list_;
   unsigned int hint_;
@@ -123,8 +142,11 @@ class AppCoreUiBase::Impl {
   std::unique_ptr<AppCoreUiDelegator> plugin_delegator_;
   std::unique_ptr<AppCoreUiPlugin> plugin_;
   std::unique_ptr<AppCoreTaskBase> service_;
-  GMainContext* context_ = nullptr;
-  std::thread thread_;
+  std::unique_ptr<WindowPosition> position_;
+  Ecore_Wl2_Window* window_ = nullptr;
+  std::unique_ptr<WindowPositionManager> wp_manager_;
+  std::unique_ptr<AppCoreUiThreadBase> thread_;
+  std::unique_ptr<AppCoreRotation> rotation_;
 };
 
 AppCoreUiBase::AppCoreUiBase(unsigned int hint)
@@ -151,6 +173,7 @@ bool AppCoreUiBase::Impl::AddWin(unsigned int win, unsigned int surf) {
     return false;
   }
 
+  SetWindow(win);
   winnode_list_.emplace_back(new WinNode(win, surf));
   return true;
 }
@@ -162,6 +185,7 @@ bool AppCoreUiBase::Impl::DeleteWin(unsigned int win) {
     return false;
   }
 
+  SetWindow(0);
   winnode_list_.remove_if(
       [win](std::shared_ptr<struct AppCoreUiBase::Impl::WinNode> node) {
         return node->win_ == win;
@@ -183,6 +207,10 @@ bool AppCoreUiBase::Impl::UpdateWin(unsigned int win, unsigned int surf,
   if (vis != VT_NONE)
     node->vis_ = vis;
 
+  if (GetWindow() == nullptr)
+    SetWindow(win);
+
+  SetWindowPosition();
   return true;
 }
 
@@ -257,6 +285,7 @@ void AppCoreUiBase::Impl::SetAppId() {
 }
 
 void AppCoreUiBase::Impl::PluginInit(int argc, char** argv) {
+  LogTracer tracer("AppCoreUiBase::Impl::PluginInit()");
   plugin_.reset(AppCoreUiPlugin::Load());
   if (plugin_ == nullptr)
     return;
@@ -377,31 +406,104 @@ void AppCoreUiBase::Impl::PluginFini() {
   plugin_->Fini(parent_);
 }
 
+void AppCoreUiBase::Impl::SetWindowPosition(const tizen_base::Bundle& b) {
+  position_ = wp_manager_->ReadFromBundle(b);
+  if (position_) {
+    _D("x: %d, y: %d, w: %d, h: %d",
+        position_->GetPositionX(), position_->GetPositionY(),
+        position_->GetScreenWidth(), position_->GetScreenHeight());
+  }
+
+  auto recent_screen_position = b.GetString(K_HINT_RECENT_SCREEN_POSITION);
+  if (!recent_screen_position.empty()) {
+    auto position = wp_manager_->ReadFromFile();
+    if (position) {
+      _D("x: %d, y: %d, w: %d, h: %d",
+          position->GetPositionX(), position->GetPositionY(),
+          position->GetScreenWidth(), position->GetScreenHeight());
+      position_ = std::move(position);
+    } else {
+      _D("There is no window position");
+    }
+  }
+
+  if (position_)
+    wp_manager_->WriteToFile(position_);
+}
+
+void AppCoreUiBase::Impl::SetWindowPosition() {
+  if (!position_)
+    return;
+
+  if (GetWindow() == nullptr) {
+    _E("window is nullptr");
+    return;
+  }
+
+  int x = 0;
+  int y = 0;
+  int w = 0;
+  int h = 0;
+  ecore_wl2_window_geometry_get(GetWindow(), &x, &y, &w, &h);
+
+  _W("x: %d, y: %d, w: %d, h: %d", w, y, w, h);
+  if (position_->GetPositionX() != x ||
+      position_->GetPositionY() != y ||
+      position_->GetScreenWidth() != w ||
+      position_->GetScreenHeight() != h) {
+    position_.reset(new WindowPosition(x, y, w, h));
+    wp_manager_->WriteToFile(position_);
+  }
+}
+
+void AppCoreUiBase::Impl::SetWindow(unsigned int wid) {
+  if (wid == 0) {
+    window_ = nullptr;
+    return;
+  }
+
+  window_ = ecore_wl2_window_find(wid);
+  if (window_ == nullptr) {
+    _E("ecore_wl2_window_find() is failed. wid(%u)", wid);
+    return;
+  }
+
+  _D("wid(%u), window(%p)", wid, window_);
+}
+
+Ecore_Wl2_Window* AppCoreUiBase::Impl::GetWindow() const {
+  return window_;
+}
+
 void AppCoreUiBase::DoRun(int argc, char** argv) {
   SetCoreDelegator(nullptr);
   SetLoopDelegator(nullptr);
   SetCoreUiDelegator(nullptr);
   SetWindowDelegator(this);
   impl_->plugin_delegator_.reset();
+
+  impl_->handler_->Init();
   impl_->PluginInit(argc, argv);
 
-  char appid[PATH_MAX] = {0, };
+  char appid[APPID_MAX] = {0, };
   int ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
   if (ret != 0)
     _E("Fail to get appid. pid(%d)", getpid());
 
-  impl_->handler_->Init();
   impl_->state_ = Impl::AS_NONE;
   impl_->w_status_ = Impl::WS_NONE;
   impl_->appid_ = std::string(appid);
   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
-  if (impl_->hint_ & HINT_BG_LAUNCH_CONTROL) {
-    tizen_base::Bundle b(bundle_import_from_argv(argc, argv), false, true);
-    if (!b.IsEmpty()) {
+
+  tizen_base::Bundle b(bundle_import_from_argv(argc, argv), false, true);
+  if (!b.IsEmpty()) {
+    if (impl_->hint_ & HINT_BG_LAUNCH_CONTROL) {
       std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH);
       if (bg_launch.compare("enable") == 0)
         impl_->ApplyBgState(true);
     }
+
+    impl_->SetWindowPosition(b);
   }
 
   if (impl_->hint_ & HINT_WINDOW_ID_CONTROL)
@@ -416,26 +518,16 @@ void AppCoreUiBase::DoExit() {
 
 void AppCoreUiBase::Impl::Run(int argc, char** argv) {
   if (hint_ & HINT_DUAL_THREAD) {
-    // For the loader case
-    while (ecore_shutdown() != 0);
-
     service_ = parent_->CreateTask();
-    context_ = g_main_context_new();
-    std::string env = std::to_string(GPOINTER_TO_UINT(context_));
-    setenv("TIZEN_GLIB_CONTEXT", env.c_str(), 1);
-
-    thread_ = std::thread([&] {
-          parent_->DoRun(argc, argv);
-        });
+    auto* thread_context = AppCoreUiThreadBase::GetContext();
+    if (thread_context == nullptr) {
+      thread_.reset(new AppCoreUiThreadBase());
+      thread_->Run(argc, argv);
+      thread_context = AppCoreUiThreadBase::GetContext();
+    }
 
+    thread_context->Post([&]() { parent_->DoRun(argc, argv); });
     service_->Run(argc, argv);
-
-    if (thread_.joinable())
-      thread_.join();
-
-    setenv("TIZEN_GLIB_CONTEXT", "", 1);
-    g_main_context_unref(context_);
-    context_ = nullptr;
     return;
   }
 
@@ -444,11 +536,11 @@ void AppCoreUiBase::Impl::Run(int argc, char** argv) {
 
 void AppCoreUiBase::Impl::Exit() {
   if (hint_ & HINT_DUAL_THREAD) {
-    GLib::IdleAdd(context_, [](gpointer user_data) {
-          auto* impl = static_cast<AppCoreUiBase::Impl*>(user_data);
-          impl->parent_->DoExit();
-          return G_SOURCE_REMOVE;
-        }, this);
+    auto* thread_context = AppCoreUiThreadBase::GetContext();
+    if (thread_context != nullptr) {
+      thread_context->Post([&]() { parent_->DoExit(); });
+      thread_context->Exit();
+    }
 
     service_->Exit();
     return;
@@ -457,6 +549,22 @@ void AppCoreUiBase::Impl::Exit() {
   parent_->DoExit();
 }
 
+void AppCoreUiBase::Impl::RotationInit() {
+  if (!rotation_) rotation_.reset(new AppCoreRotation(this));
+
+  rotation_->Init();
+}
+
+void AppCoreUiBase::Impl::RotationShutdown() {
+  if (rotation_) rotation_->Dispose();
+}
+
+void AppCoreUiBase::Impl::OnRotationChanged(int degree) {
+  AppCoreBase::SetRotationState(
+      static_cast<AppCoreBase::RotationState>(degree));
+  parent_->RaiseEvent(degree, IEvent::Type::DEVICE_ORIENTATION_CHANGED);
+}
+
 void AppCoreUiBase::Run(int argc, char** argv) {
   impl_->Run(argc, argv);
 }
@@ -466,13 +574,14 @@ void AppCoreUiBase::Exit() {
 }
 
 void AppCoreUiBase::Dispose() {
-  impl_->handler_->Fini();
+  impl_->handler_->UnsetEvents();
   impl_->FiniWl();
 
   impl_->appid_.clear();
 
   AppCoreBase::Dispose();
   impl_->PluginFini();
+  impl_->handler_->Fini();
 }
 
 std::unique_ptr<AppCoreTaskBase> AppCoreUiBase::CreateTask() {
@@ -553,23 +662,21 @@ void AppCoreUiBase::Impl::DoStart(tizen_base::Bundle b) {
     return;
   }
 
+  std::string rpc_port = b.GetString(AUL_K_RPC_PORT);
   if (parent_->GetHint() & HINT_BG_LAUNCH_CONTROL) {
     std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH);
     if (!bg_launch.empty() && bg_launch.compare("enable") == 0) {
       if (!bg_state_ && state_ != AS_RUNNING)
         ApplyBgState(true);
     } else {
-      if (bg_state_)
+      if (bg_state_ && rpc_port.empty())
         ApplyBgState(false);
     }
   }
 
   if (parent_->GetHint() & HINT_WINDOW_AUTO_CONTROL) {
-    if (!bg_state_) {
-      std::string rpc_port = b.GetString(AUL_K_RPC_PORT);
-      if (rpc_port.empty())
-        RaiseWin();
-    }
+    if (!bg_state_ && rpc_port.empty())
+      RaiseWin();
   }
 }
 
@@ -672,7 +779,17 @@ int AppCoreUiBase::OnReceive(aul_type type, tizen_base::Bundle b) {
   return 0;
 }
 
+int AppCoreUiBase::OnControl(tizen_base::Bundle b) {
+  LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
+      impl_->appid_.c_str());
+  AppCoreBase::OnControl(std::move(b));
+  LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
+      impl_->appid_.c_str());
+  return 0;
+}
+
 int AppCoreUiBase::OnCreate() {
+  impl_->handler_->SetEvents();
   AppCoreBase::OnCreate();
   impl_->state_ = Impl::AS_CREATED;
   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
@@ -741,8 +858,9 @@ void AppCoreUiBase::OnShow(int type, void* event) {
   else
     impl_->UpdateWin(win, surf, Impl::VT_NONE);
 
-  if (surf != 0)
+  if (surf != 0) {
     GroupAdd();
+  }
 }
 
 bool AppCoreUiBase::Impl::CheckVisible() {
@@ -867,4 +985,38 @@ void AppCoreUiBase::SetSystemResourceReclaiming(bool enable) {
   impl_->resource_reclaiming_ = enable;
 }
 
+int AppCoreUiBase::GetWindowPosition(int* x, int* y, int* w, int* h) {
+  if (!impl_->position_ ||
+      x == nullptr ||
+      y == nullptr ||
+      w == nullptr ||
+      h == nullptr)
+    return -1;
+
+  *x = impl_->position_->GetPositionX();
+  *y = impl_->position_->GetPositionY();
+  *w = impl_->position_->GetScreenWidth();
+  *h = impl_->position_->GetScreenHeight();
+
+  return 0;
+}
+
+int AppCoreUiBase::OnSetEvent(IEvent::Type event) {
+  AppCoreBase::OnSetEvent(event);
+
+  if (event == IEvent::Type::DEVICE_ORIENTATION_CHANGED)
+    impl_->RotationInit();
+
+  return 0;
+}
+
+int AppCoreUiBase::OnUnsetEvent(IEvent::Type event) {
+  AppCoreBase::OnUnsetEvent(event);
+
+  if (event == IEvent::Type::DEVICE_ORIENTATION_CHANGED)
+    impl_->RotationShutdown();
+
+  return 0;
+}
+
 }  // namespace tizen_cpp