Add internal method to set window position
[platform/core/appfw/app-core.git] / tizen-cpp / app-core-ui-cpp / app_core_ui_base.cc
1 /*
2  * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "app-core-ui-cpp/app_core_ui_base.hh"
18
19 #include <Ecore_Wl2.h>
20 #include <aul_app_lifecycle.h>
21 #include <aul_rpc_port.h>
22 #include <aul_svc.h>
23 #include <bundle_internal.h>
24 #include <fcntl.h>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
28 #include <ttrace.h>
29 #include <unistd.h>
30
31 #include <list>
32 #include <memory>
33 #include <string>
34 #include <thread>
35
36 #include "app-core-cpp/app_core_base.hh"
37 #include "app-core-ui-cpp/api/app_core_ui_base.h"
38 #include "app-core-ui-cpp/app_core_task_base.hh"
39 #include "app-core-ui-cpp/app_core_ui_delegator_private.hh"
40 #include "app-core-ui-cpp/app_core_ui_plugin_private.hh"
41 #include "app-core-ui-cpp/wayland_handler_private.hh"
42 #include "common/ecore_handler.hh"
43 #include "common/glib_private.hh"
44 #include "common/log_private.hh"
45
46 namespace tizen_cpp {
47
48 constexpr const char K_SERVICE_THREAD[] = "__K_SERVICE_THREAD";
49
50 void SetComm(const std::string& name) {
51   pid_t tid = syscall(__NR_gettid);
52   std::string path = "/proc/" + std::to_string(tid) + "/comm";
53   int fd = open(path.c_str(), O_WRONLY);
54   if (fd < 0) {
55     _E("open(%s) is failed. errno(%d)", path.c_str(), errno);
56     return;
57   }
58
59   ssize_t bytes_written = write(fd, name.c_str(), name.length() + 1);
60   if (bytes_written < 0)
61     _E("write(%d) is failed. errno(%d)", fd, errno);
62
63   close(fd);
64 }
65
66 class AppCoreUiBase::Impl {
67  public:
68   Impl(AppCoreUiBase* parent, unsigned int hint)
69       : parent_(parent),
70         hint_(hint),
71         handler_(std::make_shared<EcoreHandler>(parent)),
72         wl_handler_(new WaylandHandler()) {
73   }
74
75  private:
76   friend class AppCoreUiBase;
77   AppCoreUiBase* parent_;
78
79   enum AppState {
80     AS_NONE,
81     AS_CREATED,
82     AS_RUNNING,
83     AS_PAUSED,
84     AS_DYING,
85   };
86
87   enum VisibilityType {
88     VT_NONE,
89     VT_UNOBSCURED,
90     VT_FULLY_OBSCURED,
91   };
92
93   enum WinStatus {
94     WS_NONE,
95     WS_PAUSE,
96     WS_RESUME,
97   };
98
99   struct WinNode {
100     unsigned int win_;
101     unsigned int surf_;
102     int vis_;
103     WinNode(unsigned int win, unsigned int surf)
104         : win_(win), surf_(surf), vis_(VT_NONE) {
105     }
106   };
107
108   class WindowPosition {
109    public:
110     WindowPosition(int x, int y, int w, int h)
111       : x_(x), y_(y), w_(w), h_(h){
112     }
113
114     int GetPositionX() const { return x_; }
115     int GetPositionY() const { return y_; }
116     int GetScreenWidth() const { return w_; }
117     int GetScreenHeight() const { return h_; }
118
119    private:
120     int x_;
121     int y_;
122     int w_;
123     int h_;
124   };
125
126   void ExitFromSuspend();
127   void PrepareToSuspend();
128   void DoStart(tizen_base::Bundle b);
129   void DoResume();
130   void DoPause();
131   bool CheckVisible();
132   int IsLegacyLifecycle();
133   std::shared_ptr<struct WinNode> FindWin(unsigned int win);
134   bool AddWin(unsigned int win, unsigned int surf);
135   bool DeleteWin(unsigned int win);
136   bool UpdateWin(unsigned int win, unsigned int surf, int vis);
137   void RaiseWin();
138   void PauseWin();
139   void ApplyBgState(bool bg_state);
140   void SetAppId();
141   int InitWl();
142   int FiniWl();
143   void PluginInit(int argc, char** argv);
144   void PluginFini();
145   void SetWindowPosition(const tizen_base::Bundle& b);
146   void Run(int argc, char** argv);
147   void Exit();
148
149   std::list<std::shared_ptr<WinNode>> winnode_list_;
150   unsigned int hint_;
151   std::string below_app_;
152   bool first_launch_ = true;
153   bool bg_state_ = false;
154   bool resource_reclaiming_ = true;
155   std::string appid_;
156   AppState state_ = AS_NONE;
157   WinStatus w_status_ = WS_NONE;
158   std::shared_ptr<EcoreHandler> handler_;
159   std::unique_ptr<WaylandHandler> wl_handler_;
160   IAppCoreUi* core_ui_delegator_ = nullptr;
161   std::unique_ptr<AppCoreUiDelegator> plugin_delegator_;
162   std::unique_ptr<AppCoreUiPlugin> plugin_;
163   std::unique_ptr<AppCoreTaskBase> service_;
164   GMainContext* context_ = nullptr;
165   std::thread thread_;
166   std::unique_ptr<WindowPosition> position_;
167 };
168
169 AppCoreUiBase::AppCoreUiBase(unsigned int hint)
170     : impl_(new Impl(this, hint)) {
171 }
172
173 AppCoreUiBase::~AppCoreUiBase() = default;
174
175 std::shared_ptr<AppCoreUiBase::Impl::WinNode> AppCoreUiBase::Impl::FindWin(
176     unsigned int win) {
177   for (auto& i : winnode_list_) {
178     if (i->win_ == win)
179       return i;
180   }
181
182   return nullptr;
183 }
184
185 bool AppCoreUiBase::Impl::AddWin(unsigned int win, unsigned int surf) {
186   _D("[EVENT_TEST][EVENT] __add_win WIN: %u", win);
187   std::shared_ptr<AppCoreUiBase::Impl::WinNode> node = FindWin(win);
188   if (node != nullptr) {
189     _D("[EVENT_TEST][EVENT] ERROR There is already window: %u", win);
190     return false;
191   }
192
193   winnode_list_.emplace_back(new WinNode(win, surf));
194   return true;
195 }
196
197 bool AppCoreUiBase::Impl::DeleteWin(unsigned int win) {
198   std::shared_ptr<struct AppCoreUiBase::Impl::WinNode> node = FindWin(win);
199   if (node == nullptr) {
200     _D("[EVENT_TEST][EVENT] ERROR There is no window: %u", win);
201     return false;
202   }
203
204   winnode_list_.remove_if(
205       [win](std::shared_ptr<struct AppCoreUiBase::Impl::WinNode> node) {
206         return node->win_ == win;
207       });
208   return true;
209 }
210
211 bool AppCoreUiBase::Impl::UpdateWin(unsigned int win, unsigned int surf,
212     int vis) {
213   std::shared_ptr<AppCoreUiBase::Impl::WinNode> node = FindWin(win);
214   if (node == nullptr) {
215     _D("[EVENT_TEST][EVENT] ERROR There is no window: %u", win);
216     return false;
217   }
218
219   node->win_ = win;
220   if (surf != 0)
221     node->surf_ = surf;
222   if (vis != VT_NONE)
223     node->vis_ = vis;
224
225   return true;
226 }
227
228 void AppCoreUiBase::Impl::RaiseWin() {
229   if (!(hint_ & HINT_WINDOW_STACK_CONTROL))
230     return;
231
232   unsigned int win_id = parent_->GetMainWindow();
233   _I("Raise window: %u", win_id);
234   handler_->RaiseWin(win_id);
235 }
236
237 void AppCoreUiBase::Impl::PauseWin() {
238   if (!(hint_ & HINT_WINDOW_STACK_CONTROL))
239     return;
240
241   _D("Pause window");
242   for (auto& i : winnode_list_) {
243     _D("Pause window: %u", i->win_);
244     handler_->PauseWin(i->win_);
245   }
246 }
247
248 unsigned int AppCoreUiBase::GetMainWindow() {
249   if (impl_->winnode_list_.empty())
250     return 0;
251
252   return impl_->winnode_list_.begin()->get()->win_;
253 }
254
255 unsigned int AppCoreUiBase::GetMainSurface() {
256   if (impl_->winnode_list_.empty())
257     return 0;
258
259   return impl_->winnode_list_.begin()->get()->surf_;
260 }
261
262 void AppCoreUiBase::SetCoreUiDelegator(IAppCoreUi* delegator) {
263   impl_->core_ui_delegator_ = delegator;
264 }
265
266 void AppCoreUiBase::SetWindowDelegator(IWindow* delegator) {
267   impl_->handler_->SetWindow(delegator);
268 }
269
270 int AppCoreUiBase::Impl::InitWl() {
271   return wl_handler_->Init();
272 }
273
274 int AppCoreUiBase::Impl::FiniWl() {
275   wl_handler_->Fini();
276   return 0;
277 }
278
279 void AppCoreUiBase::Impl::ApplyBgState(bool bg_state) {
280   if (wl_handler_->Init() < 0)
281     return;
282
283   if (bg_state)
284     wl_handler_->SetBgState();
285   else
286     wl_handler_->UnsetBgState();
287
288   parent_->SetBgState(bg_state);
289 }
290
291 void AppCoreUiBase::Impl::SetAppId() {
292   if (wl_handler_->Init() < 0)
293     return;
294
295   wl_handler_->SetAppId(appid_);
296 }
297
298 void AppCoreUiBase::Impl::PluginInit(int argc, char** argv) {
299   plugin_.reset(AppCoreUiPlugin::Load());
300   if (plugin_ == nullptr)
301     return;
302
303   app_core_ui_base_ops ops;
304   ops.base.create = [](void* data) -> int {
305     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
306     return base->OnCreate();
307   };
308
309   ops.base.control = [](bundle* b, void* data) -> int {
310     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
311     return base->OnControl(tizen_base::Bundle(b));
312   };
313
314   ops.base.terminate = [](void* data) -> int {
315     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
316     return base->OnTerminate();
317   };
318
319   ops.base.receive = [](aul_type type, bundle* b, void* data) -> int {
320     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
321     return base->OnReceive(type, tizen_base::Bundle(b));
322   };
323
324   ops.base.set_i18n = [](void* data) -> int {
325     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
326     return base->OnSetI18n();
327   };
328
329   ops.base.init = [](int argc, char** argv, void* data) {
330     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
331     base->OnLoopInit(argc, argv);
332   };
333
334   ops.base.finish = [](void* data) {
335     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
336     base->OnLoopFinish();
337   };
338
339   ops.base.run = [](void* data) {
340     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
341     base->OnLoopRun();
342   };
343
344   ops.base.exit = [](void* data) {
345     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
346     base->OnLoopExit();
347   };
348
349   ops.base.set_event = [](app_core_ui_base_event_e event, void* data) {
350     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
351     base->OnSetEvent(static_cast<IAppCore::IEvent::Type>(event));
352   };
353
354   ops.base.unset_event = [](app_core_ui_base_event_e event, void* data) {
355     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
356     base->OnUnsetEvent(static_cast<IAppCore::IEvent::Type>(event));
357   };
358
359   ops.base.trim_memory = [](void* data) {
360     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
361     base->OnTrimMemory();
362   };
363
364   ops.pause = [](void* data) -> int {
365     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
366     return base->OnPause();
367   };
368
369   ops.resume = [](void* data) -> int {
370     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
371     return base->OnResume();
372   };
373
374   ops.window.show = [](int type, void* event, void* data) {
375     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
376     base->OnShow(type, event);
377   };
378
379   ops.window.hide = [](int type, void* event, void* data) {
380     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
381     base->OnHide(type, event);
382   };
383
384   ops.window.lower = [](int type, void* event, void* data) {
385     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
386     base->OnLower(type, event);
387   };
388
389   ops.window.visibility = [](int type, void* event, void* data) {
390     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
391     base->OnVisibility(type, event);
392   };
393
394   ops.window.pre_visibility = [](int type, void* event, void* data) {
395     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
396     base->OnPreVisibility(type, event);
397   };
398
399   ops.window.aux_message = [](int type, void* event, void* data) {
400     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
401     base->OnAuxMessage(type, event);
402   };
403
404   plugin_->Init(parent_, &ops, argc, argv, &hint_);
405   plugin_delegator_.reset(new AppCoreUiDelegator(ops, parent_));
406   parent_->SetCoreDelegator(plugin_delegator_.get());
407   parent_->SetLoopDelegator(plugin_delegator_.get());
408   parent_->SetCoreUiDelegator(plugin_delegator_.get());
409   parent_->SetWindowDelegator(plugin_delegator_.get());
410 }
411
412 void AppCoreUiBase::Impl::PluginFini() {
413   if (plugin_ == nullptr)
414     return;
415
416   plugin_->Fini(parent_);
417 }
418
419 void AppCoreUiBase::Impl::SetWindowPosition(const tizen_base::Bundle& b) {
420   std::string x_str = b.GetString(AUL_K_HINT_SCREEN_POS_X);
421   if (x_str.empty())
422     return;
423
424   std::string y_str = b.GetString(AUL_K_HINT_SCREEN_POS_Y);
425   if (y_str.empty())
426     return;
427
428   std::string w_str = b.GetString(AUL_K_HINT_SCREEN_WIDTH);
429   if (w_str.empty())
430     return;
431
432   std::string h_str = b.GetString(AUL_K_HINT_SCREEN_HEIGHT);
433   if (h_str.empty())
434     return;
435
436   position_ = std::make_unique<AppCoreUiBase::Impl::WindowPosition>(
437       std::stoi(x_str), std::stoi(y_str), std::stoi(w_str), std::stoi(h_str));
438 }
439
440 void AppCoreUiBase::DoRun(int argc, char** argv) {
441   SetCoreDelegator(nullptr);
442   SetLoopDelegator(nullptr);
443   SetCoreUiDelegator(nullptr);
444   SetWindowDelegator(this);
445   impl_->plugin_delegator_.reset();
446
447   impl_->handler_->Init();
448   impl_->PluginInit(argc, argv);
449
450   char appid[PATH_MAX] = {0, };
451   int ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
452   if (ret != 0)
453     _E("Fail to get appid. pid(%d)", getpid());
454
455   impl_->state_ = Impl::AS_NONE;
456   impl_->w_status_ = Impl::WS_NONE;
457   impl_->appid_ = std::string(appid);
458   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
459
460   tizen_base::Bundle b(bundle_import_from_argv(argc, argv), false, true);
461   if (!b.IsEmpty()) {
462     if (impl_->hint_ & HINT_BG_LAUNCH_CONTROL) {
463       std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH);
464       if (bg_launch.compare("enable") == 0)
465         impl_->ApplyBgState(true);
466     }
467
468     impl_->SetWindowPosition(b);
469   }
470
471   if (impl_->hint_ & HINT_WINDOW_ID_CONTROL)
472     impl_->SetAppId();
473
474   AppCoreBase::Run(argc, argv);
475 }
476
477 void AppCoreUiBase::DoExit() {
478   AppCoreBase::Exit();
479 }
480
481 void AppCoreUiBase::Impl::Run(int argc, char** argv) {
482   if (hint_ & HINT_DUAL_THREAD) {
483     // For the loader case
484     while (ecore_shutdown() != 0);
485
486     service_ = parent_->CreateTask();
487     context_ = g_main_context_new();
488     std::string env = std::to_string(
489         reinterpret_cast<unsigned long int>(context_));
490     setenv("TIZEN_GLIB_CONTEXT", env.c_str(), 1);
491
492     thread_ = std::thread([&] {
493           SetComm("UIThread+");
494           parent_->DoRun(argc, argv);
495         });
496
497     service_->Run(argc, argv);
498
499     if (thread_.joinable())
500       thread_.join();
501
502     setenv("TIZEN_GLIB_CONTEXT", "0", 1);
503     g_main_context_unref(context_);
504     context_ = nullptr;
505     return;
506   }
507
508   parent_->DoRun(argc, argv);
509 }
510
511 void AppCoreUiBase::Impl::Exit() {
512   if (hint_ & HINT_DUAL_THREAD) {
513     GLib::IdleAdd(context_, [](gpointer user_data) {
514           auto* impl = static_cast<AppCoreUiBase::Impl*>(user_data);
515           impl->parent_->DoExit();
516           return G_SOURCE_REMOVE;
517         }, this);
518
519     service_->Exit();
520     return;
521   }
522
523   parent_->DoExit();
524 }
525
526 void AppCoreUiBase::Run(int argc, char** argv) {
527   impl_->Run(argc, argv);
528 }
529
530 void AppCoreUiBase::Exit() {
531   impl_->Exit();
532 }
533
534 void AppCoreUiBase::Dispose() {
535   impl_->handler_->UnsetEvents();
536   impl_->FiniWl();
537
538   impl_->appid_.clear();
539
540   AppCoreBase::Dispose();
541   impl_->PluginFini();
542   impl_->handler_->Fini();
543 }
544
545 std::unique_ptr<AppCoreTaskBase> AppCoreUiBase::CreateTask() {
546   return std::make_unique<AppCoreTaskBase>();
547 }
548
549 void AppCoreUiBase::Impl::PrepareToSuspend() {
550   if (parent_->IsBgAllowed() && !parent_->IsSuspended()) {
551     SuspendedState suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
552     parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
553     parent_->ToggleSuspendedState();
554   }
555 }
556
557 void AppCoreUiBase::Impl::ExitFromSuspend() {
558   if (parent_->IsSuspended()) {
559     SuspendedState suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
560     parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
561     parent_->ToggleSuspendedState();
562   }
563 }
564
565 void AppCoreUiBase::Impl::DoPause() {
566   if (state_ == AS_RUNNING) {
567     aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_PAUSED);
568     state_ = AS_PAUSED;
569     traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
570     _D("Call pause callback");
571     if (parent_->GetHint() & HINT_DUAL_THREAD)
572       service_->Post(AppCoreTaskBase::UiState::PAUSED);
573
574     int ret;
575     if (core_ui_delegator_)
576       ret = core_ui_delegator_->OnPause();
577     else
578       ret = parent_->OnPause();
579
580     traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
581     if (ret >= 0 && resource_reclaiming_)
582       parent_->AddSuspendTimer();
583
584     PrepareToSuspend();
585   }
586
587   aul_status_update(STATUS_BG);
588 }
589
590 void AppCoreUiBase::Impl::DoResume() {
591   if (state_ == AS_PAUSED || state_ == AS_CREATED) {
592     aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_RESUMED);
593     ExitFromSuspend();
594     state_ = AS_RUNNING;
595     LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", appid_.c_str());
596     traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
597     _D("Call resume callback");
598     if (parent_->GetHint() & HINT_DUAL_THREAD)
599       service_->Post(AppCoreTaskBase::UiState::RESUMED);
600
601     parent_->RemoveSuspendTimer();
602     if (core_ui_delegator_)
603       core_ui_delegator_->OnResume();
604     else
605       parent_->OnResume();
606
607     traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
608     LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", appid_.c_str());
609   }
610
611   aul_status_update(STATUS_VISIBLE);
612 }
613
614 void AppCoreUiBase::Impl::DoStart(tizen_base::Bundle b) {
615   if (parent_->GetHint() & HINT_WINDOW_STACK_CONTROL)
616     below_app_ = b.GetString(AUL_SVC_K_RELOCATE_BELOW);
617
618   if (first_launch_) {
619     first_launch_ = false;
620     return;
621   }
622
623   std::string rpc_port = b.GetString(AUL_K_RPC_PORT);
624   if (parent_->GetHint() & HINT_BG_LAUNCH_CONTROL) {
625     std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH);
626     if (!bg_launch.empty() && bg_launch.compare("enable") == 0) {
627       if (!bg_state_ && state_ != AS_RUNNING)
628         ApplyBgState(true);
629     } else {
630       if (bg_state_ && rpc_port.empty())
631         ApplyBgState(false);
632     }
633   }
634
635   if (parent_->GetHint() & HINT_WINDOW_AUTO_CONTROL) {
636     if (!bg_state_ && rpc_port.empty())
637       RaiseWin();
638   }
639 }
640
641 int AppCoreUiBase::Impl::IsLegacyLifecycle() {
642   static int is_legacy = -1;
643   if (__builtin_expect(is_legacy != -1, 1))
644     return is_legacy;
645
646   const char* api_version = getenv("TIZEN_API_VERSION");
647   if (api_version) {
648     if (strverscmp("2.4", api_version) > 0 &&
649         strverscmp("2.2.1", api_version) < 0)
650       is_legacy = 1;
651     else
652       is_legacy = 0;
653   } else {
654     is_legacy = 0;
655   }
656
657   return is_legacy;
658 }
659
660 int AppCoreUiBase::OnPause() {
661   return 0;
662 }
663
664 int AppCoreUiBase::OnResume() {
665   return 0;
666 }
667
668 int AppCoreUiBase::OnReceive(aul_type type, tizen_base::Bundle b) {
669   if (impl_->state_ == Impl::AS_DYING) {
670     _E("Skip the event in dying state");
671     return 0;
672   }
673
674   if ((type == AUL_TERMINATE_BGAPP || type == AUL_TERMINATE_BG_INST) &&
675       impl_->state_ != Impl::AS_PAUSED)
676     return 0;
677
678   if (type == AUL_START) {
679     impl_->ExitFromSuspend();
680
681     if (!b.GetString(K_SERVICE_THREAD).empty()) {
682       impl_->service_->OnReceive(type, std::move(b));
683       return 0;
684     }
685   }
686
687   AppCoreBase::OnReceive(type, b);
688
689   switch (type) {
690   case AUL_START:
691     impl_->DoStart(b);
692     if (GetHint() & HINT_LEGACY_CONTROL) {
693       if (impl_->bg_state_ && impl_->IsLegacyLifecycle()) {
694         _D("Legacy lifecycle");
695         impl_->DoResume();
696       }
697     }
698     break;
699   case AUL_RESUME:
700     if (impl_->bg_state_)
701       impl_->ApplyBgState(false);
702
703     impl_->RaiseWin();
704     break;
705   case AUL_TERMINATE:
706     if (impl_->state_ == Impl::AS_RUNNING) {
707       _D("Call pause callback");
708       if (impl_->core_ui_delegator_)
709         impl_->core_ui_delegator_->OnPause();
710       else
711         OnPause();
712     }
713     impl_->state_ = Impl::AS_DYING;
714     break;
715   case AUL_TERMINATE_BGAPP:
716   case AUL_TERMINATE_BG_INST:
717   case AUL_TERMINATE_INST:
718     _D("[APP %d] TERMINATE", getpid());
719     if (impl_->state_ == Impl::AS_RUNNING) {
720       _D("Call pause callback");
721       if (impl_->core_ui_delegator_)
722         impl_->core_ui_delegator_->OnPause();
723       else
724         OnPause();
725     }
726     impl_->state_ = Impl::AS_DYING;
727     aul_status_update(STATUS_DYING);
728     Exit();
729     break;
730   case AUL_PAUSE:
731     impl_->PauseWin();
732     break;
733   default:
734     break;
735   }
736
737   return 0;
738 }
739
740 int AppCoreUiBase::OnControl(tizen_base::Bundle b) {
741   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
742       impl_->appid_.c_str());
743   AppCoreBase::OnControl(std::move(b));
744   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
745       impl_->appid_.c_str());
746   return 0;
747 }
748
749 int AppCoreUiBase::OnCreate() {
750   impl_->handler_->SetEvents();
751   AppCoreBase::OnCreate();
752   impl_->state_ = Impl::AS_CREATED;
753   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
754       impl_->appid_.c_str());
755   return 0;
756 }
757
758 int AppCoreUiBase::OnTerminate() {
759   if (impl_->state_ == Impl::AS_RUNNING) {
760     _D("Call pause callback");
761     OnPause();
762   }
763
764   impl_->state_ = Impl::AS_DYING;
765   AppCoreBase::OnTerminate();
766   return 0;
767 }
768
769 int AppCoreUiBase::OnTrimMemory() {
770   return AppCoreBase::OnTrimMemory();
771 }
772
773 int AppCoreUiBase::GroupAdd() {
774   _D("Group attach");
775   static bool attached = false;
776   if (attached)
777     return 0;
778
779   int wid = GetMainSurface();
780   if (wid == 0) {
781     _E("window wasn't ready");
782     return -1;
783   }
784
785   int ret = aul_app_group_set_window(wid);
786   if (ret < 0) {
787     _E("Failed to set app group window. error(%d)", ret);
788     return ret;
789   }
790
791   attached = true;
792   return 0;
793 }
794
795 void AppCoreUiBase::GroupRemove() {
796   _D("Group lower");
797   int exit = 0;
798   aul_app_group_lower(&exit);
799   if (exit) {
800     _W("Sub App");
801     Exit();
802   }
803 }
804
805 void AppCoreUiBase::OnShow(int type, void* event) {
806   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Show*>(event);
807   if (ev->parent_win != 0)
808     return;
809
810   unsigned int win = static_cast<unsigned int>(ev->win);
811   unsigned int surf = static_cast<unsigned int>(ev->data[0]);
812   _D("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN: %u, %u", win, surf);
813
814   if (!impl_->FindWin(win))
815     impl_->AddWin(win, surf);
816   else
817     impl_->UpdateWin(win, surf, Impl::VT_NONE);
818
819   if (surf != 0)
820     GroupAdd();
821 }
822
823 bool AppCoreUiBase::Impl::CheckVisible() {
824   _D("[EVENT_TEST][EVENT] __check_visible");
825   for (auto& i : winnode_list_) {
826     _D("win : %u visibility : %d", i->win_, i->vis_);
827     if (i->vis_ == VT_UNOBSCURED)
828       return true;
829   }
830
831   return false;
832 }
833
834 void AppCoreUiBase::OnHide(int type, void* event) {
835   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Hide*>(event);
836   _D("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN :%d", ev->win);
837   if (impl_->FindWin((unsigned int)ev->win)) {
838     impl_->DeleteWin((unsigned int)ev->win);
839     bool bvisibility = impl_->CheckVisible();
840     if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) {
841       _D("Go to Pasue state");
842       impl_->w_status_ = Impl::WS_PAUSE;
843       impl_->DoPause();
844     }
845   }
846 }
847
848 void AppCoreUiBase::OnLower(int type, void* event) {
849   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Lower*>(event);
850   if (!ev)
851     return;
852
853   _D("ECORE_WL2_EVENT_WINDOW_LOWER window id: %u", ev->win);
854   if (!(impl_->hint_ & HINT_WINDOW_GROUP_CONTROL))
855     return;
856
857   GroupRemove();
858 }
859
860 void AppCoreUiBase::OnVisibility(int type, void* event) {
861   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Visibility_Change*>(event);
862   impl_->UpdateWin((unsigned int)ev->win, 0,
863       ev->fully_obscured ? Impl::VT_FULLY_OBSCURED : Impl::VT_UNOBSCURED);
864   bool bvisibility = impl_->CheckVisible();
865   _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_);
866
867   if (bvisibility && (impl_->hint_ & HINT_WINDOW_STACK_CONTROL) &&
868       !impl_->below_app_.empty()) {
869     aul_app_group_activate_below(impl_->below_app_.c_str());
870     impl_->below_app_.clear();
871   }
872
873   if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) {
874     _D("Go to Resume state");
875     impl_->w_status_ = Impl::WS_RESUME;
876     impl_->DoResume();
877   } else if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) {
878     _D("Go to Pasue state");
879     impl_->w_status_ = Impl::WS_PAUSE;
880     impl_->DoPause();
881   } else {
882     _D("No change state");
883   }
884 }
885
886 void AppCoreUiBase::OnPreVisibility(int type, void* event) {
887   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Pre_Visibility_Change*>(
888       event);
889   if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
890     impl_->UpdateWin((unsigned int)ev->win, 0, Impl::VT_UNOBSCURED);
891     bool bvisibility = impl_->CheckVisible();
892
893     _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_);
894     if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) {
895       _D(" Go to Resume state");
896       impl_->w_status_ = Impl::WS_RESUME;
897       impl_->DoResume();
898     }
899   }
900 }
901
902 void AppCoreUiBase::OnAuxMessage(int type, void* event) {
903   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Aux_Message*>(event);
904   if (ev->key && !strcmp(ev->key, "dpms_wm")) {
905     if (ev->val && !strcmp(ev->val, "on")) {
906       _D("Display state: on");
907       SetDisplayState(DISPLAY_STATE_ON);
908     } else if (ev->val && !strcmp(ev->val, "off")) {
909       _D("Display state: off");
910       SetDisplayState(DISPLAY_STATE_OFF);
911     } else {
912       _E("Unknown state: %s", ev->val);
913     }
914   }
915 }
916
917 void AppCoreUiBase::Pause() {
918   impl_->DoPause();
919 }
920
921 void AppCoreUiBase::Resume() {
922   impl_->DoResume();
923 }
924
925 bool AppCoreUiBase::IsResumed() {
926   return impl_->state_ == Impl::AS_RUNNING;
927 }
928
929 int AppCoreUiBase::GetHint() {
930   return impl_->hint_;
931 }
932
933 bool AppCoreUiBase::GetBgState() {
934   return impl_->bg_state_;
935 }
936
937 void AppCoreUiBase::SetBgState(bool bg_state) {
938   impl_->bg_state_ = bg_state;
939 }
940
941 void AppCoreUiBase::SetSystemResourceReclaiming(bool enable) {
942   impl_->resource_reclaiming_ = enable;
943 }
944
945 int AppCoreUiBase::GetWindowPosition(int* x, int* y, int* w, int* h) {
946   if (!impl_->position_ ||
947       x == nullptr ||
948       y == nullptr ||
949       w == nullptr ||
950       h == nullptr)
951     return -1;
952
953   *x = impl_->position_->GetPositionX();
954   *y = impl_->position_->GetPositionY();
955   *w = impl_->position_->GetScreenWidth();
956   *h = impl_->position_->GetScreenHeight();
957
958   return 0;
959 }
960
961 }  // namespace tizen_cpp