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 cfc6e6c..beeef29 100644 (file)
 #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;
 
-void SetComm(const std::string& name) {
-  pid_t tid = syscall(__NR_gettid);
-  std::string path = "/proc/" + std::to_string(tid) + "/comm";
-  int fd = open(path.c_str(), O_WRONLY);
-  if (fd < 0) {
-    _E("open(%s) is failed. errno(%d)", path.c_str(), errno);
-    return;
-  }
-
-  ssize_t bytes_written = write(fd, name.c_str(), name.length() + 1);
-  if (bytes_written < 0)
-    _E("write(%d) is failed. errno(%d)", fd, errno);
-
-  close(fd);
-}
-
-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,24 +98,6 @@ class AppCoreUiBase::Impl {
     }
   };
 
-  class WindowPosition {
-   public:
-    WindowPosition(int x, int y, int w, int h)
-      : x_(x), y_(y), w_(w), h_(h){
-    }
-
-    int GetPositionX() const { return x_; }
-    int GetPositionY() const { return y_; }
-    int GetScreenWidth() const { return w_; }
-    int GetScreenHeight() const { return h_; }
-
-   private:
-    int x_;
-    int y_;
-    int w_;
-    int h_;
-  };
-
   void ExitFromSuspend();
   void PrepareToSuspend();
   void DoStart(tizen_base::Bundle b);
@@ -143,8 +118,14 @@ class AppCoreUiBase::Impl {
   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_;
@@ -161,9 +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)
@@ -190,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;
 }
@@ -201,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;
@@ -222,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;
 }
 
@@ -296,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;
@@ -417,24 +407,72 @@ void AppCoreUiBase::Impl::PluginFini() {
 }
 
 void AppCoreUiBase::Impl::SetWindowPosition(const tizen_base::Bundle& b) {
-  std::string x_str = b.GetString(AUL_K_HINT_SCREEN_POS_X);
-  if (x_str.empty())
+  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;
 
-  std::string y_str = b.GetString(AUL_K_HINT_SCREEN_POS_Y);
-  if (y_str.empty())
+  if (GetWindow() == nullptr) {
+    _E("window is nullptr");
     return;
+  }
 
-  std::string w_str = b.GetString(AUL_K_HINT_SCREEN_WIDTH);
-  if (w_str.empty())
+  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;
+  }
 
-  std::string h_str = b.GetString(AUL_K_HINT_SCREEN_HEIGHT);
-  if (h_str.empty())
+  window_ = ecore_wl2_window_find(wid);
+  if (window_ == nullptr) {
+    _E("ecore_wl2_window_find() is failed. wid(%u)", wid);
     return;
+  }
 
-  position_ = std::make_unique<AppCoreUiBase::Impl::WindowPosition>(
-      std::stoi(x_str), std::stoi(y_str), std::stoi(w_str), std::stoi(h_str));
+  _D("wid(%u), window(%p)", wid, window_);
+}
+
+Ecore_Wl2_Window* AppCoreUiBase::Impl::GetWindow() const {
+  return window_;
 }
 
 void AppCoreUiBase::DoRun(int argc, char** argv) {
@@ -447,7 +485,7 @@ void AppCoreUiBase::DoRun(int argc, char** argv) {
   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());
@@ -480,28 +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(
-        reinterpret_cast<unsigned long int>(context_));
-    setenv("TIZEN_GLIB_CONTEXT", env.c_str(), 1);
-
-    thread_ = std::thread([&] {
-          SetComm("UIThread+");
-          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", "0", 1);
-    g_main_context_unref(context_);
-    context_ = nullptr;
     return;
   }
 
@@ -510,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;
@@ -523,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);
 }
@@ -816,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() {
@@ -958,4 +1001,22 @@ int AppCoreUiBase::GetWindowPosition(int* x, int* y, int* w, int* h) {
   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