Add nullptr check of EcoreHandler
[platform/core/appfw/app-core.git] / tizen-cpp / app-core-multi-window-cpp / app_core_multi_window_base.cc
1 /*
2  * Copyright (c) 2021 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 <list>
18 #include <map>
19 #include <stdexcept>
20 #include <string>
21
22 #include "app-core-multi-window-cpp/app_core_multi_window_base.hh"
23 #include "common/ecore_handler.hh"
24 #include "common/log_private.hh"
25
26 namespace tizen_cpp {
27
28 class AppCoreMultiWindowBase::Context::Impl {
29  public:
30   Impl(std::string context_id, std::string inst_id, AppCoreMultiWindowBase* app)
31       : id_(inst_id), context_id_(context_id), app_(app) {}
32
33  private:
34   friend class AppCoreMultiWindowBase::Context;
35   bool paused_ = true;
36   std::string id_;
37   std::string context_id_;
38   int wid_ = 0;
39   AppCoreMultiWindowBase* app_;
40 };
41
42 class AppCoreMultiWindowBase::Impl {
43  private:
44   friend class AppCoreMultiWindowBase;
45   std::shared_ptr<EcoreHandler> handler_;
46   std::map<std::string, std::shared_ptr<Context::IFactory>> factory_map_;
47   std::list<std::shared_ptr<Context>> contexts_;
48   std::unique_ptr<EcoreHandler::ITrim> trim_;
49 };
50
51 AppCoreMultiWindowBase::Context::Context(std::string context_id,
52     std::string inst_id, AppCoreMultiWindowBase* app)
53     : impl_(std::make_unique<Impl>(
54           std::move(context_id), std::move(inst_id), app)) {
55 }
56
57 AppCoreMultiWindowBase::Context::~Context() = default;
58
59 void AppCoreMultiWindowBase::Context::Exit() {
60   Context::Pause();
61   OnTerminate();
62 }
63
64 void AppCoreMultiWindowBase::Context::Drop() {
65   OnTerminate();
66 }
67
68 void AppCoreMultiWindowBase::Context::Pause() {
69   if (impl_->paused_)
70     return;
71
72   OnPause();
73   impl_->paused_ = true;
74 }
75
76 void AppCoreMultiWindowBase::Context::Resume() {
77   if (!impl_->paused_)
78     return;
79
80   OnResume();
81   impl_->paused_ = false;
82 }
83
84 bool AppCoreMultiWindowBase::Context::IsResumed() {
85   return !impl_->paused_;
86 }
87
88 const std::string& AppCoreMultiWindowBase::Context::GetInstId() const {
89   return impl_->id_;
90 }
91
92 const std::string& AppCoreMultiWindowBase::Context::GetContextId() const {
93   return impl_->context_id_;
94 }
95
96 int AppCoreMultiWindowBase::Context::GetWindowId() const {
97   return impl_->wid_;
98 }
99
100 void AppCoreMultiWindowBase::Context::WindowBind(Ecore_Wl2_Window* wl_win) {
101   if (wl_win == nullptr) {
102     _E("Invalid parameter");
103     return;
104   }
105
106   impl_->wid_ = ecore_wl2_window_id_get(wl_win);
107 }
108
109 void AppCoreMultiWindowBase::Context::WindowUnbind() {
110   impl_->wid_ = 0;
111 }
112
113 AppCoreMultiWindowBase* AppCoreMultiWindowBase::Context::GetApp() {
114   return impl_->app_;
115 }
116
117 AppCoreMultiWindowBase::AppCoreMultiWindowBase() :
118     impl_(std::make_unique<Impl>()) {}
119
120 AppCoreMultiWindowBase::~AppCoreMultiWindowBase() = default;
121
122 const std::list<std::shared_ptr<AppCoreMultiWindowBase::Context>>&
123 AppCoreMultiWindowBase::GetContexts() {
124   return impl_->contexts_;
125 }
126
127 int AppCoreMultiWindowBase::GetContextCnt() const {
128   return impl_->contexts_.size();
129 }
130
131 void AppCoreMultiWindowBase::ExitContext(
132     std::shared_ptr<AppCoreMultiWindowBase::Context> context) {
133   context->Exit();
134   impl_->contexts_.remove(context);
135 }
136
137 std::shared_ptr<AppCoreMultiWindowBase::Context>
138 AppCoreMultiWindowBase::CreateContext(const std::string& context_id,
139     const std::string& inst_id) {
140   auto i = impl_->factory_map_.find(context_id);
141   if (i == impl_->factory_map_.end())
142     throw std::runtime_error("failed to find factory");
143
144   std::shared_ptr<Context> c = (*i).second->Create(inst_id, this);
145   return c;
146 }
147
148 std::shared_ptr<AppCoreMultiWindowBase::Context>
149 AppCoreMultiWindowBase::RunContext(
150     std::shared_ptr<AppCoreMultiWindowBase::Context> cxt) {
151   impl_->contexts_.push_back(cxt);
152   try {
153     cxt->OnCreate();
154   } catch (const std::runtime_error&) {
155     cxt->Drop();
156     impl_->contexts_.remove(cxt);
157     return {};
158   }
159
160   return cxt;
161 }
162
163 std::shared_ptr<AppCoreMultiWindowBase::Context>
164 AppCoreMultiWindowBase::RunContext(const std::string& context_id,
165     const std::string& inst_id) {
166   auto c = CreateContext(context_id, inst_id);
167   return RunContext(c);
168 }
169
170 std::shared_ptr<AppCoreMultiWindowBase::Context>
171 AppCoreMultiWindowBase::FindById(const std::string& inst_id) {
172   for (auto& i : impl_->contexts_) {
173     if (i->GetInstId() == inst_id) {
174       return i;
175     }
176   }
177
178   return {};
179 }
180
181 std::shared_ptr<AppCoreMultiWindowBase::Context>
182 AppCoreMultiWindowBase::FindByWindowId(int win_id) {
183   for (auto& i : impl_->contexts_) {
184     if (i->GetWindowId() == win_id) {
185       return i;
186     }
187   }
188
189   return {};
190 }
191
192 void AppCoreMultiWindowBase::Run(int argc, char** argv) {
193   class Trimmer : public EcoreHandler::ITrim {
194    public:
195     bool IsTrimmable() {
196       return base_->IsResumed();
197     }
198
199     void OnTrim() {
200       base_->OnTrimMemory();
201     }
202
203     explicit Trimmer(AppCoreMultiWindowBase* base) : base_(base) {}
204
205    private:
206     AppCoreMultiWindowBase* base_;
207   };
208
209   impl_->trim_ = std::unique_ptr<EcoreHandler::ITrim>(new Trimmer(this));
210   impl_->handler_ = std::make_shared<EcoreHandler>(this, impl_->trim_.get());
211   impl_->handler_->Init();
212
213   AppCoreBase::Run(argc, argv);
214 }
215
216 void AppCoreMultiWindowBase::Dispose() {
217   for (auto& i : impl_->contexts_) {
218     i->Exit();
219   }
220   impl_->contexts_.clear();
221   impl_->factory_map_.clear();
222
223   AppCoreBase::Dispose();
224   if (impl_->handler_.get() != nullptr) {
225     impl_->handler_->UnsetEvents();
226     impl_->handler_->Fini();
227   }
228 }
229
230 int AppCoreMultiWindowBase::OnCreate() {
231   impl_->handler_->SetEvents();
232   AppCoreBase::OnCreate();
233   return 0;
234 }
235
236 bool AppCoreMultiWindowBase::IsResumed() {
237   for (auto& i : impl_->contexts_) {
238     if (i->IsResumed())
239       return true;
240   }
241
242   return false;
243 }
244
245 void AppCoreMultiWindowBase::OnShow(int type, void* event) {
246 }
247
248 void AppCoreMultiWindowBase::OnHide(int type, void* event) {
249   Ecore_Wl2_Event_Window_Hide* ev =
250       static_cast<Ecore_Wl2_Event_Window_Hide*>(event);
251   auto cxt = FindByWindowId(ev->win);
252   if (cxt.get() == nullptr)
253     return;
254
255   cxt->WindowUnbind();
256 }
257
258 void AppCoreMultiWindowBase::OnLower(int type, void* event) {
259 }
260
261 void AppCoreMultiWindowBase::OnVisibility(int type, void* event) {
262   auto* ev = static_cast<Ecore_Wl2_Event_Window_Visibility_Change*>(event);
263   auto cxt = FindByWindowId(ev->win);
264   if (cxt.get() == nullptr)
265     return;
266
267   if (ev->fully_obscured)
268     cxt->Context::Pause();
269   else
270     cxt->Context::Resume();
271 }
272
273 void AppCoreMultiWindowBase::OnPreVisibility(int type, void* event) {
274   auto* ev = static_cast<Ecore_Wl2_Event_Window_Pre_Visibility_Change*>(event);
275   auto cxt = FindByWindowId(ev->win);
276   if (cxt.get() == nullptr)
277     return;
278
279   if (ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED)
280     cxt->Context::Resume();
281 }
282
283 void AppCoreMultiWindowBase::OnAuxMessage(int type, void* event) {
284   auto* ev = static_cast<Ecore_Wl2_Event_Aux_Message*>(event);
285   if (ev->key && !strcmp(ev->key, "dpms_wm")) {
286     if (ev->val && !strcmp(ev->val, "on")) {
287       _D("Display state: on");
288       AppCoreBase::SetDisplayState(AppCoreBase::DISPLAY_STATE_ON);
289     } else if (ev->val && !strcmp(ev->val, "off")) {
290       _D("Display state: off");
291       AppCoreBase::SetDisplayState(AppCoreBase::DISPLAY_STATE_OFF);
292     } else {
293       _E("Unknown state: %s", ev->val);
294     }
295   }
296 }
297
298 void AppCoreMultiWindowBase::AddContextFactory(
299     std::shared_ptr<AppCoreMultiWindowBase::Context::IFactory> factory,
300     const std::string& context_id) {
301   impl_->factory_map_[context_id] = std::move(factory);
302 }
303
304 std::shared_ptr<AppCoreMultiWindowBase::Context::IFactory>
305 AppCoreMultiWindowBase::GetContextFactory(const std::string& context_id) {
306   return impl_->factory_map_[context_id];
307 }
308
309 }  // namespace tizen_cpp