Update wm_layer
[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 WMError LayerControl::updateLayer(LayerState& layer_state)\r
130 {\r
131     return WMError::SUCCESS;\r
132 }\r
133 \r
134 WMError LayerControl::commitChange()\r
135 {\r
136     WMError rc = WMError::SUCCESS;\r
137     vector<unsigned> ivi_l_ids;\r
138     for(const auto& l : this->wm_layers)\r
139     {\r
140         auto state = l->getLayerState();\r
141         for(const auto& id : state.getIviIdList())\r
142         {\r
143             ivi_l_ids.push_back(id);\r
144         }\r
145     }\r
146     t_ilm_layer* id_array = new t_ilm_layer[ivi_l_ids.size()];\r
147     if(id_array == nullptr)\r
148     {\r
149         HMI_WARNING("short memory");\r
150         this->undoUpdate();\r
151         return WMError::FAIL;\r
152     }\r
153     int count = 0;\r
154     for(const auto& i : ivi_l_ids)\r
155     {\r
156         id_array[count] = i;\r
157     }\r
158 \r
159     ilmErrorTypes ret = ilm_displaySetRenderOrder(this->screenID, id_array, ivi_l_ids.size());\r
160     if(ret != ILM_SUCCESS)\r
161     {\r
162         this->undoUpdate();\r
163         rc = WMError::FAIL;\r
164     }\r
165     delete id_array;\r
166     return rc;\r
167 }\r
168 \r
169 void LayerControl::undoUpdate() {}\r
170 \r
171 WMError LayerControl::loadLayerSetting(const string &path)\r
172 {\r
173     HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path);\r
174 \r
175     json_object *json_obj, *json_cfg;\r
176     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);\r
177     if (0 > ret)\r
178     {\r
179         HMI_DEBUG("Could not open %s, so use default area information", path.c_str());\r
180         return WMError::FAIL;\r
181     }\r
182     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));\r
183 \r
184     if (!json_object_object_get_ex(json_obj, "mappings", &json_cfg))\r
185     {\r
186         HMI_ERROR("Parse Error!!");\r
187         return WMError::FAIL;\r
188     }\r
189 \r
190     int len = json_object_array_length(json_cfg);\r
191     HMI_DEBUG("json_cfg len:%d", len);\r
192 \r
193     for (int i = 0; i < len; i++)\r
194     {\r
195         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);\r
196         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));\r
197 \r
198         this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp));\r
199     }\r
200 \r
201     return WMError::SUCCESS;\r
202 }\r
203 \r
204 WMError LayerControl::loadAreaDb(const std::string& path)\r
205 {\r
206     // Load area.db\r
207     json_object *json_obj;\r
208     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);\r
209     if (0 > ret)\r
210     {\r
211         HMI_DEBUG("Could not open %s, so use default area information", path.c_str());\r
212         return WMError::FAIL;\r
213     }\r
214     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));\r
215 \r
216     // Perse areas\r
217     json_object *json_cfg;\r
218     if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))\r
219     {\r
220         HMI_ERROR("Parse Error!!");\r
221         return WMError::FAIL;\r
222     }\r
223 \r
224     int len = json_object_array_length(json_cfg);\r
225     HMI_DEBUG("json_cfg len:%d", len);\r
226 \r
227     const char *area;\r
228     for (int i = 0; i < len; i++)\r
229     {\r
230         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);\r
231         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));\r
232 \r
233         area = jh::getStringFromJson(json_tmp, "name");\r
234         if (nullptr == area)\r
235         {\r
236             HMI_ERROR("Parse Error!!");\r
237             return WMError::FAIL;\r
238         }\r
239         HMI_DEBUG("> area:%s", area);\r
240 \r
241         json_object *json_rect;\r
242         if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))\r
243         {\r
244             HMI_ERROR("Parse Error!!");\r
245             return WMError::FAIL;\r
246         }\r
247         HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));\r
248 \r
249         struct rect area_size;\r
250         area_size.x = jh::getIntFromJson(json_rect, "x");\r
251         area_size.y = jh::getIntFromJson(json_rect, "y");\r
252         area_size.w = jh::getIntFromJson(json_rect, "w");\r
253         area_size.h = jh::getIntFromJson(json_rect, "h");\r
254 \r
255         this->area2size[area] = area_size;\r
256     }\r
257 \r
258     // Check\r
259     for (const auto& itr : this->area2size)\r
260     {\r
261         HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",\r
262                   itr.first.c_str(), itr.second.x, itr.second.y,\r
263                   itr.second.w, itr.second.h);\r
264     }\r
265 \r
266     // Release json_object\r
267     json_object_put(json_obj);\r
268 \r
269     return WMError::SUCCESS;\r
270 }\r
271 \r
272 void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created)\r
273 {\r
274     this->cb.test(id);\r
275     if (ILM_SURFACE == object)\r
276     {\r
277         if (created)\r
278         {\r
279             ilmSurfaceProperties sp;\r
280             ilmErrorTypes rc;\r
281             rc = ilm_getPropertiesOfSurface(id, &sp);\r
282             if(rc != ILM_SUCCESS)\r
283                 return;\r
284             // this->cb->surfaceCreated(pid, id);\r
285             ilm_surfaceAddNotification(id, surfaceCallback_static);\r
286             ilm_surfaceSetSourceRectangle(id, 0, 0, sp.origSourceWidth, sp.origSourceHeight);\r
287         }\r
288         else\r
289         {\r
290             // this->cb->surfaceDestroyed(id);\r
291         }\r
292     }\r
293     if (ILM_LAYER == object)\r
294     {\r
295         if(created)\r
296         {\r
297             ilm_layerAddNotification(id, layerCallback_static);\r
298             // this->cb->layerCreated(id);\r
299         }\r
300         else\r
301         {\r
302             // this->cb->layerDestroyed(id); // Means Application is dead.\r
303         }\r
304     }\r
305 }\r
306 \r
307 void LayerControl::dispatchPropertyChangeEvent(unsigned id,\r
308         struct ilmSurfaceProperties* sprop,\r
309         t_ilm_notification_mask mask)\r
310 {\r
311     pid_t pid = sprop->creatorPid;\r
312     HMI_DEBUG("pid : %d", pid);\r
313 \r
314     if (ILM_NOTIFICATION_VISIBILITY & mask)\r
315     {\r
316         //this->cb->surfaceVisibilityChanged(id, sprop->visibility);\r
317     }\r
318     if (ILM_NOTIFICATION_OPACITY & mask)\r
319     {\r
320     }\r
321     if (ILM_NOTIFICATION_ORIENTATION & mask)\r
322     {\r
323     }\r
324     if (ILM_NOTIFICATION_SOURCE_RECT & mask)\r
325     {\r
326         // this->cb->surfaceSourceRectChanged(id, )\r
327     }\r
328     if (ILM_NOTIFICATION_DEST_RECT & mask)\r
329     {\r
330         // this->cb->surfaceSourceRectChanged(id, )\r
331     }\r
332     if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask)\r
333     {\r
334     }\r
335     if (ILM_NOTIFICATION_CONTENT_REMOVED & mask)\r
336     {\r
337         /* application being down */\r
338         // m_appLayers.remove(pid);\r
339     }\r
340     if (ILM_NOTIFICATION_CONFIGURED & mask)\r
341     {\r
342         /* qDebug("ILM_NOTIFICATION_CONFIGURED");\r
343         qDebug("  surfaceProperties %d", surface);\r
344         qDebug("    surfaceProperties.origSourceWidth: %d", surfaceProperties->origSourceWidth);\r
345         qDebug("    surfaceProperties.origSourceHeight: %d", surfaceProperties->origSourceHeight);\r
346 \r
347         if (surface == WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID) {\r
348             addSurfaceToLayer(surface, WINDOWMANAGER_LAYER_HOMESCREEN);\r
349             configureHomeScreenMainSurface(surface, surfaceProperties->origSourceWidth, surfaceProperties->origSourceHeight);\r
350         } else {\r
351             ilmErrorTypes result;\r
352             t_ilm_layer layer = addSurfaceToAppLayer(pid, surface);\r
353 \r
354             if (layer != 0) {\r
355                 configureAppSurface(surface,\r
356                                     surfaceProperties->origSourceWidth,\r
357                                     surfaceProperties->origSourceHeight);\r
358 \r
359                 result = ilm_layerAddSurface(layer, surface);\r
360                 if (result != ILM_SUCCESS) {\r
361                     qDebug("ilm_layerAddSurface(%d,%d) failed.", layer, surface);\r
362                 }\r
363                 ilm_commitChanges();\r
364             }\r
365         }\r
366         updateScreen(); */\r
367     }\r
368 }\r
369 \r
370 void LayerControl::dispatchPropertyChangeEvent(unsigned id,\r
371         struct ilmLayerProperties* lprop,\r
372         t_ilm_notification_mask mask)\r
373 {\r
374     if (ILM_NOTIFICATION_VISIBILITY & mask)\r
375     {\r
376         //this->cb->layerVisibilityChanged(id, sprop->visibility);\r
377     }\r
378     if (ILM_NOTIFICATION_OPACITY & mask)\r
379     {\r
380     }\r
381     if (ILM_NOTIFICATION_ORIENTATION & mask)\r
382     {\r
383     }\r
384     if (ILM_NOTIFICATION_SOURCE_RECT & mask)\r
385     {\r
386         // this->cb->surfaceSourceRectChanged(id, )\r
387     }\r
388     if (ILM_NOTIFICATION_DEST_RECT & mask)\r
389     {\r
390         // this->cb->surfaceSourceRectChanged(id, )\r
391     }\r
392     if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask)\r
393     {\r
394     }\r
395     if (ILM_NOTIFICATION_CONTENT_REMOVED & mask)\r
396     {\r
397         /* application being down */\r
398         // m_appLayers.remove(pid);\r
399     }\r
400     if (ILM_NOTIFICATION_CONFIGURED & mask)\r
401     {\r
402         /* qDebug("ILM_NOTIFICATION_CONFIGURED");\r
403         qDebug("  surfaceProperties %d", surface);\r
404         qDebug("    surfaceProperties.origSourceWidth: %d", surfaceProperties->origSourceWidth);\r
405         qDebug("    surfaceProperties.origSourceHeight: %d", surfaceProperties->origSourceHeight);\r
406 \r
407         if (surface == WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID) {\r
408             addSurfaceToLayer(surface, WINDOWMANAGER_LAYER_HOMESCREEN);\r
409             configureHomeScreenMainSurface(surface, surfaceProperties->origSourceWidth, surfaceProperties->origSourceHeight);\r
410         } else {\r
411             ilmErrorTypes result;\r
412             t_ilm_layer layer = addSurfaceToAppLayer(pid, surface);\r
413 \r
414             if (layer != 0) {\r
415                 configureAppSurface(surface,\r
416                                     surfaceProperties->origSourceWidth,\r
417                                     surfaceProperties->origSourceHeight);\r
418 \r
419                 result = ilm_layerAddSurface(layer, surface);\r
420                 if (result != ILM_SUCCESS) {\r
421                     qDebug("ilm_layerAddSurface(%d,%d) failed.", layer, surface);\r
422                 }\r
423                 ilm_commitChanges();\r
424             }\r
425         }\r
426         updateScreen(); */\r
427     }\r
428 }\r
429 \r
430 } // namespace wm