0e72fab00aabf20a1bd7f5fa29a2cbe0a5162892
[apps/agl-service-windowmanager.git] / src / wm_layer_control.cpp
1 /*\r
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 #include <assert.h>\r
17 #include <unistd.h>\r
18 #include "wm_layer_control.hpp"\r
19 #include "wm_layer.hpp"\r
20 #include "json_helper.hpp"\r
21 \r
22 #define LC_AREA_PATH "/etc/areas.db"\r
23 #define LC_LAYER_SETTING_PATH "/etc/layer_setting.json"\r
24 \r
25 using std::string;\r
26 using std::vector;\r
27 \r
28 namespace wm {\r
29 \r
30 LayerControl* g_lc_ctxt;\r
31 \r
32 static void createCallback_static(ilmObjectType object,\r
33                             t_ilm_uint id,\r
34                             t_ilm_bool created,\r
35                             void* data)\r
36 {\r
37     static_cast<LayerControl*>(data)->dispatchCreateEvent(object, id, created);\r
38 }\r
39 \r
40 static void surfaceCallback_static(t_ilm_surface surface,\r
41             struct ilmSurfaceProperties* surface_prop,\r
42             t_ilm_notification_mask mask)\r
43 {\r
44     g_lc_ctxt->dispatchPropertyChangeEvent(surface, surface_prop, mask);\r
45 }\r
46 \r
47 static void layerCallback_static(t_ilm_layer layer,\r
48             struct ilmLayerProperties* layer_prop,\r
49             t_ilm_notification_mask mask)\r
50 {\r
51     g_lc_ctxt->dispatchPropertyChangeEvent(layer, layer_prop, mask);\r
52 }\r
53 \r
54 LayerControl::LayerControl(const std::string& root)\r
55 {\r
56     string area_path = root + LC_AREA_PATH;\r
57     string layer_path= root + LC_LAYER_SETTING_PATH;\r
58     // load layers.setting.json\r
59     WMError ret = this->loadLayerSetting(layer_path);\r
60     assert(ret == WMError::SUCCESS);\r
61     // load area.db\r
62     ret = this->loadAreaDb(area_path);\r
63     assert(ret == WMError::SUCCESS);\r
64 }\r
65 \r
66 WMError LayerControl::init(const LayerControlCallbacks& cb)\r
67 {\r
68     ilmErrorTypes rc = ilm_init();\r
69     t_ilm_uint num = 0;\r
70     t_ilm_uint *ids;\r
71     int cnt = 0;\r
72 \r
73     while (rc != ILM_SUCCESS)\r
74     {\r
75         cnt++;\r
76         if (20 <= cnt)\r
77         {\r
78             HMI_ERROR("Could not connect to compositor");\r
79             goto lc_init_error;\r
80         }\r
81         HMI_ERROR("Wait to start weston ...");\r
82         sleep(1);\r
83         ilm_init();\r
84     }\r
85     if(rc != ILM_SUCCESS) goto lc_init_error;\r
86 \r
87     // Get current screen setting\r
88     rc = ilm_getScreenIDs(&num, &ids);\r
89 \r
90     if(rc != ILM_SUCCESS) goto lc_init_error;\r
91 \r
92     for(unsigned i = 0; i < num; i++)\r
93     {\r
94         HMI_INFO("get screen: %d", ids[i]);\r
95     }\r
96     // Currently, 0 is only available\r
97     this->screenID = ids[0];\r
98 \r
99     rc = ilm_getPropertiesOfScreen(this->screenID, &this->screen_prop);\r
100 \r
101     if(rc != ILM_SUCCESS) goto lc_init_error;\r
102 \r
103     // Register Callback from ILM\r
104     this->cb = cb;\r
105     ilm_registerNotification(createCallback_static, this);\r
106 \r
107     return WMError::SUCCESS;\r
108 \r
109 lc_init_error:\r
110     HMI_ERROR("Failed to initialize. Terminate WM");\r
111 \r
112     return WMError::FAIL;\r
113 }\r
114 \r
115 unsigned LayerControl::getNewLayerID(const string& role)\r
116 {\r
117     unsigned ret = 0;\r
118     for(const auto& l: this->wm_layers)\r
119     {\r
120         ret = l->getNewLayerID(role);\r
121         if(ret != 0)\r
122         {\r
123             break;\r
124         }\r
125     }\r
126     return ret;\r
127 }\r
128 \r
129 struct rect LayerControl::getAreaSize(const std::string& area)\r
130 {\r
131     return area2size[area];\r
132 }\r
133 \r
134 void LayerControl::setupArea(double scaling)\r
135 {\r
136     struct rect rct;\r
137 \r
138     rct = this->area2size["normal.full"];\r
139     this->area2size["normalfull"] = rct;\r
140     this->area2size["normal"] = rct;\r
141 \r
142     for (auto &i : this->area2size)\r
143     {\r
144         i.second.x = static_cast<int>(scaling * i.second.x + 0.5);\r
145         i.second.y = static_cast<int>(scaling * i.second.y + 0.5);\r
146         i.second.w = static_cast<int>(scaling * i.second.w + 0.5);\r
147         i.second.h = static_cast<int>(scaling * i.second.h + 0.5);\r
148 \r
149         HMI_DEBUG("wm:lm", "area:%s size(after) : x:%d y:%d w:%d h:%d",\r
150             i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h);\r
151     }\r
152 }\r
153 \r
154 Screen LayerControl::getScreenInfo()\r
155 {\r
156     return Screen(this->screen_prop.screenWidth, this->screen_prop.screenHeight);\r
157 }\r
158 \r
159 WMError LayerControl::updateLayer(LayerState& layer_state)\r
160 {\r
161     return WMError::SUCCESS;\r
162 }\r
163 \r
164 WMError LayerControl::commitChange()\r
165 {\r
166     WMError rc = WMError::SUCCESS;\r
167     vector<unsigned> ivi_l_ids;\r
168     for(const auto& l : this->wm_layers)\r
169     {\r
170         auto state = l->getLayerState();\r
171         for(const auto& id : state.getIviIdList())\r
172         {\r
173             ivi_l_ids.push_back(id);\r
174         }\r
175     }\r
176     t_ilm_layer* id_array = new t_ilm_layer[ivi_l_ids.size()];\r
177     if(id_array == nullptr)\r
178     {\r
179         HMI_WARNING("short memory");\r
180         this->undoUpdate();\r
181         return WMError::FAIL;\r
182     }\r
183     int count = 0;\r
184     for(const auto& i : ivi_l_ids)\r
185     {\r
186         id_array[count] = i;\r
187     }\r
188 \r
189     ilmErrorTypes ret = ilm_displaySetRenderOrder(this->screenID, id_array, ivi_l_ids.size());\r
190     if(ret != ILM_SUCCESS)\r
191     {\r
192         this->undoUpdate();\r
193         rc = WMError::FAIL;\r
194     }\r
195     delete id_array;\r
196     return rc;\r
197 }\r
198 \r
199 void LayerControl::undoUpdate() {}\r
200 \r
201 WMError LayerControl::loadLayerSetting(const string &path)\r
202 {\r
203     HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path);\r
204 \r
205     json_object *json_obj, *json_cfg;\r
206     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);\r
207     if (0 > ret)\r
208     {\r
209         HMI_DEBUG("Could not open %s, so use default area information", path.c_str());\r
210         return WMError::FAIL;\r
211     }\r
212     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));\r
213 \r
214     if (!json_object_object_get_ex(json_obj, "mappings", &json_cfg))\r
215     {\r
216         HMI_ERROR("Parse Error!!");\r
217         return WMError::FAIL;\r
218     }\r
219 \r
220     int len = json_object_array_length(json_cfg);\r
221     HMI_DEBUG("json_cfg len:%d", len);\r
222 \r
223     for (int i = 0; i < len; i++)\r
224     {\r
225         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);\r
226         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));\r
227 \r
228         this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp));\r
229     }\r
230 \r
231     return WMError::SUCCESS;\r
232 }\r
233 \r
234 WMError LayerControl::loadAreaDb(const std::string& path)\r
235 {\r
236     // Load area.db\r
237     json_object *json_obj;\r
238     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);\r
239     if (0 > ret)\r
240     {\r
241         HMI_DEBUG("Could not open %s, so use default area information", path.c_str());\r
242         return WMError::FAIL;\r
243     }\r
244     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));\r
245 \r
246     // Perse areas\r
247     json_object *json_cfg;\r
248     if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))\r
249     {\r
250         HMI_ERROR("Parse Error!!");\r
251         return WMError::FAIL;\r
252     }\r
253 \r
254     int len = json_object_array_length(json_cfg);\r
255     HMI_DEBUG("json_cfg len:%d", len);\r
256 \r
257     const char *area;\r
258     for (int i = 0; i < len; i++)\r
259     {\r
260         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);\r
261         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));\r
262 \r
263         area = jh::getStringFromJson(json_tmp, "name");\r
264         if (nullptr == area)\r
265         {\r
266             HMI_ERROR("Parse Error!!");\r
267             return WMError::FAIL;\r
268         }\r
269         HMI_DEBUG("> area:%s", area);\r
270 \r
271         json_object *json_rect;\r
272         if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))\r
273         {\r
274             HMI_ERROR("Parse Error!!");\r
275             return WMError::FAIL;\r
276         }\r
277         HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));\r
278 \r
279         struct rect area_size;\r
280         area_size.x = jh::getIntFromJson(json_rect, "x");\r
281         area_size.y = jh::getIntFromJson(json_rect, "y");\r
282         area_size.w = jh::getIntFromJson(json_rect, "w");\r
283         area_size.h = jh::getIntFromJson(json_rect, "h");\r
284 \r
285         this->area2size[area] = area_size;\r
286     }\r
287 \r
288     // Check\r
289     for (const auto& itr : this->area2size)\r
290     {\r
291         HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",\r
292                   itr.first.c_str(), itr.second.x, itr.second.y,\r
293                   itr.second.w, itr.second.h);\r
294     }\r
295 \r
296     // Release json_object\r
297     json_object_put(json_obj);\r
298 \r
299     return WMError::SUCCESS;\r
300 }\r
301 \r
302 void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created)\r
303 {\r
304     this->cb.test(id);\r
305     if (ILM_SURFACE == object)\r
306     {\r
307         if (created)\r
308         {\r
309             ilmSurfaceProperties sp;\r
310             ilmErrorTypes rc;\r
311             rc = ilm_getPropertiesOfSurface(id, &sp);\r
312             if(rc != ILM_SUCCESS)\r
313                 return;\r
314             // this->cb->surfaceCreated(pid, id);\r
315             ilm_surfaceAddNotification(id, surfaceCallback_static);\r
316             ilm_surfaceSetSourceRectangle(id, 0, 0, sp.origSourceWidth, sp.origSourceHeight);\r
317         }\r
318         else\r
319         {\r
320             // this->cb->surfaceDestroyed(id);\r
321         }\r
322     }\r
323     if (ILM_LAYER == object)\r
324     {\r
325         if(created)\r
326         {\r
327             ilm_layerAddNotification(id, layerCallback_static);\r
328             // this->cb->layerCreated(id);\r
329         }\r
330         else\r
331         {\r
332             // this->cb->layerDestroyed(id); // Means Application is dead.\r
333         }\r
334     }\r
335 }\r
336 \r
337 void LayerControl::dispatchPropertyChangeEvent(unsigned id,\r
338         struct ilmSurfaceProperties* sprop,\r
339         t_ilm_notification_mask mask)\r
340 {\r
341     pid_t pid = sprop->creatorPid;\r
342     HMI_DEBUG("pid : %d", pid);\r
343 \r
344     if (ILM_NOTIFICATION_VISIBILITY & mask)\r
345     {\r
346         //this->cb->surfaceVisibilityChanged(id, sprop->visibility);\r
347     }\r
348     if (ILM_NOTIFICATION_OPACITY & mask)\r
349     {\r
350     }\r
351     if (ILM_NOTIFICATION_ORIENTATION & mask)\r
352     {\r
353     }\r
354     if (ILM_NOTIFICATION_SOURCE_RECT & mask)\r
355     {\r
356         // this->cb->surfaceSourceRectChanged(id, )\r
357     }\r
358     if (ILM_NOTIFICATION_DEST_RECT & mask)\r
359     {\r
360         // this->cb->surfaceSourceRectChanged(id, )\r
361     }\r
362     if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask)\r
363     {\r
364     }\r
365     if (ILM_NOTIFICATION_CONTENT_REMOVED & mask)\r
366     {\r
367         /* application being down */\r
368         // m_appLayers.remove(pid);\r
369     }\r
370     if (ILM_NOTIFICATION_CONFIGURED & mask)\r
371     {\r
372         /* qDebug("ILM_NOTIFICATION_CONFIGURED");\r
373         qDebug("  surfaceProperties %d", surface);\r
374         qDebug("    surfaceProperties.origSourceWidth: %d", surfaceProperties->origSourceWidth);\r
375         qDebug("    surfaceProperties.origSourceHeight: %d", surfaceProperties->origSourceHeight);\r
376 \r
377         if (surface == WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID) {\r
378             addSurfaceToLayer(surface, WINDOWMANAGER_LAYER_HOMESCREEN);\r
379             configureHomeScreenMainSurface(surface, surfaceProperties->origSourceWidth, surfaceProperties->origSourceHeight);\r
380         } else {\r
381             ilmErrorTypes result;\r
382             t_ilm_layer layer = addSurfaceToAppLayer(pid, surface);\r
383 \r
384             if (layer != 0) {\r
385                 configureAppSurface(surface,\r
386                                     surfaceProperties->origSourceWidth,\r
387                                     surfaceProperties->origSourceHeight);\r
388 \r
389                 result = ilm_layerAddSurface(layer, surface);\r
390                 if (result != ILM_SUCCESS) {\r
391                     qDebug("ilm_layerAddSurface(%d,%d) failed.", layer, surface);\r
392                 }\r
393                 ilm_commitChanges();\r
394             }\r
395         }\r
396         updateScreen(); */\r
397     }\r
398 }\r
399 \r
400 void LayerControl::dispatchPropertyChangeEvent(unsigned id,\r
401         struct ilmLayerProperties* lprop,\r
402         t_ilm_notification_mask mask)\r
403 {\r
404     if (ILM_NOTIFICATION_VISIBILITY & mask)\r
405     {\r
406         //this->cb->layerVisibilityChanged(id, sprop->visibility);\r
407     }\r
408     if (ILM_NOTIFICATION_OPACITY & mask)\r
409     {\r
410     }\r
411     if (ILM_NOTIFICATION_ORIENTATION & mask)\r
412     {\r
413     }\r
414     if (ILM_NOTIFICATION_SOURCE_RECT & mask)\r
415     {\r
416         // this->cb->surfaceSourceRectChanged(id, )\r
417     }\r
418     if (ILM_NOTIFICATION_DEST_RECT & mask)\r
419     {\r
420         // this->cb->surfaceSourceRectChanged(id, )\r
421     }\r
422     if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask)\r
423     {\r
424     }\r
425     if (ILM_NOTIFICATION_CONTENT_REMOVED & mask)\r
426     {\r
427         /* application being down */\r
428         // m_appLayers.remove(pid);\r
429     }\r
430     if (ILM_NOTIFICATION_CONFIGURED & mask)\r
431     {\r
432         /* qDebug("ILM_NOTIFICATION_CONFIGURED");\r
433         qDebug("  surfaceProperties %d", surface);\r
434         qDebug("    surfaceProperties.origSourceWidth: %d", surfaceProperties->origSourceWidth);\r
435         qDebug("    surfaceProperties.origSourceHeight: %d", surfaceProperties->origSourceHeight);\r
436 \r
437         if (surface == WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID) {\r
438             addSurfaceToLayer(surface, WINDOWMANAGER_LAYER_HOMESCREEN);\r
439             configureHomeScreenMainSurface(surface, surfaceProperties->origSourceWidth, surfaceProperties->origSourceHeight);\r
440         } else {\r
441             ilmErrorTypes result;\r
442             t_ilm_layer layer = addSurfaceToAppLayer(pid, surface);\r
443 \r
444             if (layer != 0) {\r
445                 configureAppSurface(surface,\r
446                                     surfaceProperties->origSourceWidth,\r
447                                     surfaceProperties->origSourceHeight);\r
448 \r
449                 result = ilm_layerAddSurface(layer, surface);\r
450                 if (result != ILM_SUCCESS) {\r
451                     qDebug("ilm_layerAddSurface(%d,%d) failed.", layer, surface);\r
452                 }\r
453                 ilm_commitChanges();\r
454             }\r
455         }\r
456         updateScreen(); */\r
457     }\r
458 }\r
459 \r
460 } // namespace wm