temporary change
[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 "wm_client.hpp"\r
21 #include "request.hpp"\r
22 #include "json_helper.hpp"\r
23 \r
24 #define LC_AREA_PATH "/etc/areas.db"\r
25 #define LC_LAYER_SETTING_PATH "/etc/layer_setting.json"\r
26 #define LC_DEFAULT_AREA "normal.full"\r
27 \r
28 using std::string;\r
29 using std::vector;\r
30 \r
31 namespace wm {\r
32 \r
33 LayerControl* g_lc_ctxt;\r
34 \r
35 static void createCallback_static(ilmObjectType object,\r
36                             t_ilm_uint id,\r
37                             t_ilm_bool created,\r
38                             void* data)\r
39 {\r
40     static_cast<LayerControl*>(data)->dispatchCreateEvent(object, id, created);\r
41 }\r
42 \r
43 static void surfaceCallback_static(t_ilm_surface surface,\r
44             struct ilmSurfaceProperties* surface_prop,\r
45             t_ilm_notification_mask mask)\r
46 {\r
47     g_lc_ctxt->dispatchPropertyChangeEvent(surface, surface_prop, mask);\r
48 }\r
49 \r
50 static void layerCallback_static(t_ilm_layer layer,\r
51             struct ilmLayerProperties* layer_prop,\r
52             t_ilm_notification_mask mask)\r
53 {\r
54     g_lc_ctxt->dispatchPropertyChangeEvent(layer, layer_prop, mask);\r
55 }\r
56 \r
57 LayerControl::LayerControl(const std::string& root)\r
58 {\r
59     string area_path = root + LC_AREA_PATH;\r
60     string layer_path= root + LC_LAYER_SETTING_PATH;\r
61     // load layers.setting.json\r
62     WMError ret = this->loadLayerSetting(layer_path);\r
63     assert(ret == WMError::SUCCESS);\r
64     // load area.db\r
65     ret = this->loadAreaDb(area_path);\r
66     assert(ret == WMError::SUCCESS);\r
67 }\r
68 \r
69 WMError LayerControl::init(const LayerControlCallbacks& cb)\r
70 {\r
71     ilmErrorTypes rc = ilm_init();\r
72     t_ilm_uint num = 0;\r
73     t_ilm_uint *ids;\r
74     int cnt = 0;\r
75 \r
76     while (rc != ILM_SUCCESS)\r
77     {\r
78         cnt++;\r
79         if (20 <= cnt)\r
80         {\r
81             HMI_ERROR("Could not connect to compositor");\r
82             goto lc_init_error;\r
83         }\r
84         HMI_ERROR("Wait to start weston ...");\r
85         sleep(1);\r
86         ilm_init();\r
87     }\r
88     if(rc != ILM_SUCCESS) goto lc_init_error;\r
89 \r
90     // Get current screen setting\r
91     rc = ilm_getScreenIDs(&num, &ids);\r
92 \r
93     if(rc != ILM_SUCCESS) goto lc_init_error;\r
94 \r
95     for(unsigned i = 0; i < num; i++)\r
96     {\r
97         HMI_INFO("get screen: %d", ids[i]);\r
98     }\r
99     // Currently, 0 is only available\r
100     this->screenID = ids[0];\r
101 \r
102     rc = ilm_getPropertiesOfScreen(this->screenID, &this->screen_prop);\r
103 \r
104     if(rc != ILM_SUCCESS) goto lc_init_error;\r
105 \r
106     // Register Callback from ILM\r
107     this->cb = cb;\r
108     ilm_registerNotification(createCallback_static, this);\r
109 \r
110     return WMError::SUCCESS;\r
111 \r
112 lc_init_error:\r
113     HMI_ERROR("Failed to initialize. Terminate WM");\r
114 \r
115     return WMError::FAIL;\r
116 }\r
117 \r
118 void LayerControl::createNewLayer(unsigned id)\r
119 {\r
120     HMI_INFO("create new ID :%d", id);\r
121     struct rect rct = this->area2size[LC_DEFAULT_AREA];\r
122     ilm_layerCreateWithDimension(&id, rct.w, rct.h);\r
123     ilm_layerSetSourceRectangle(id, rct.x, rct.y, rct.w, rct.h);\r
124     ilm_layerSetDestinationRectangle(id, rct.x, rct.y, rct.w, rct.h);\r
125     ilm_layerSetOpacity(id, 1.0);\r
126     ilm_layerSetVisibility(id, ILM_TRUE);\r
127     ilm_commitChanges();\r
128 }\r
129 \r
130 unsigned LayerControl::getNewLayerID(const string& role, string* layer_name)\r
131 {\r
132     unsigned ret = 0;\r
133     for(const auto& l: this->wm_layers)\r
134     {\r
135         ret = l->getNewLayerID(role);\r
136         if(ret != 0)\r
137         {\r
138             *layer_name = l->layerName();\r
139             break;\r
140         }\r
141     }\r
142     return ret;\r
143 }\r
144 \r
145 struct rect LayerControl::getAreaSize(const std::string& area)\r
146 {\r
147     return area2size[area];\r
148 }\r
149 \r
150 void LayerControl::setupArea(double scaling)\r
151 {\r
152     struct rect rct;\r
153     this->scaling = scaling;\r
154 \r
155     rct = this->area2size["normal.full"];\r
156     this->area2size["normalfull"] = rct;\r
157     this->area2size["normal"] = rct;\r
158 \r
159     for (auto &i : this->area2size)\r
160     {\r
161         i.second.x = static_cast<int>(scaling * i.second.x + 0.5);\r
162         i.second.y = static_cast<int>(scaling * i.second.y + 0.5);\r
163         i.second.w = static_cast<int>(scaling * i.second.w + 0.5);\r
164         i.second.h = static_cast<int>(scaling * i.second.h + 0.5);\r
165 \r
166         HMI_DEBUG("wm:lm", "area:%s size(after) : x:%d y:%d w:%d h:%d",\r
167             i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h);\r
168     }\r
169 }\r
170 \r
171 Screen LayerControl::getScreenInfo()\r
172 {\r
173     return Screen(this->screen_prop.screenWidth, this->screen_prop.screenHeight);\r
174 }\r
175 \r
176 double LayerControl::scale()\r
177 {\r
178     return this->scaling;\r
179 }\r
180 \r
181 WMError LayerControl::updateLayer(LayerState& layer_state)\r
182 {\r
183     return WMError::SUCCESS;\r
184 }\r
185 \r
186 WMError LayerControl::commitChange()\r
187 {\r
188     WMError rc = WMError::SUCCESS;\r
189     vector<unsigned> ivi_l_ids;\r
190     for(const auto& l : this->wm_layers)\r
191     {\r
192         auto state = l->getLayerState();\r
193         for(const auto& id : state.getIviIdList())\r
194         {\r
195             ivi_l_ids.push_back(id);\r
196         }\r
197     }\r
198     t_ilm_layer* id_array = new t_ilm_layer[ivi_l_ids.size()];\r
199     if(id_array == nullptr)\r
200     {\r
201         HMI_WARNING("short memory");\r
202         this->undoUpdate();\r
203         return WMError::FAIL;\r
204     }\r
205     int count = 0;\r
206     for(const auto& i : ivi_l_ids)\r
207     {\r
208         id_array[count] = i;\r
209     }\r
210 \r
211     ilmErrorTypes ret = ilm_displaySetRenderOrder(this->screenID, id_array, ivi_l_ids.size());\r
212     if(ret != ILM_SUCCESS)\r
213     {\r
214         this->undoUpdate();\r
215         rc = WMError::FAIL;\r
216     }\r
217     delete id_array;\r
218     return rc;\r
219 }\r
220 \r
221 void LayerControl::undoUpdate() {}\r
222 \r
223 WMError LayerControl::loadLayerSetting(const string &path)\r
224 {\r
225     HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path);\r
226 \r
227     json_object *json_obj, *json_cfg;\r
228     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);\r
229     if (0 > ret)\r
230     {\r
231         HMI_DEBUG("Could not open %s, so use default area information", path.c_str());\r
232         return WMError::FAIL;\r
233     }\r
234     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));\r
235 \r
236     if (!json_object_object_get_ex(json_obj, "mappings", &json_cfg))\r
237     {\r
238         HMI_ERROR("Parse Error!!");\r
239         return WMError::FAIL;\r
240     }\r
241 \r
242     int len = json_object_array_length(json_cfg);\r
243     HMI_DEBUG("json_cfg len:%d", len);\r
244 \r
245     for (int i = 0; i < len; i++)\r
246     {\r
247         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);\r
248         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));\r
249 \r
250         this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp));\r
251     }\r
252 \r
253     return WMError::SUCCESS;\r
254 }\r
255 \r
256 WMError LayerControl::loadAreaDb(const std::string& path)\r
257 {\r
258     // Load area.db\r
259     json_object *json_obj;\r
260     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);\r
261     if (0 > ret)\r
262     {\r
263         HMI_DEBUG("Could not open %s, so use default area information", path.c_str());\r
264         return WMError::FAIL;\r
265     }\r
266     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));\r
267 \r
268     // Perse areas\r
269     json_object *json_cfg;\r
270     if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))\r
271     {\r
272         HMI_ERROR("Parse Error!!");\r
273         return WMError::FAIL;\r
274     }\r
275 \r
276     int len = json_object_array_length(json_cfg);\r
277     HMI_DEBUG("json_cfg len:%d", len);\r
278 \r
279     const char *area;\r
280     for (int i = 0; i < len; i++)\r
281     {\r
282         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);\r
283         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));\r
284 \r
285         area = jh::getStringFromJson(json_tmp, "name");\r
286         if (nullptr == area)\r
287         {\r
288             HMI_ERROR("Parse Error!!");\r
289             return WMError::FAIL;\r
290         }\r
291         HMI_DEBUG("> area:%s", area);\r
292 \r
293         json_object *json_rect;\r
294         if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))\r
295         {\r
296             HMI_ERROR("Parse Error!!");\r
297             return WMError::FAIL;\r
298         }\r
299         HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));\r
300 \r
301         struct rect area_size;\r
302         area_size.x = jh::getIntFromJson(json_rect, "x");\r
303         area_size.y = jh::getIntFromJson(json_rect, "y");\r
304         area_size.w = jh::getIntFromJson(json_rect, "w");\r
305         area_size.h = jh::getIntFromJson(json_rect, "h");\r
306 \r
307         this->area2size[area] = area_size;\r
308     }\r
309 \r
310     // Check\r
311     for (const auto& itr : this->area2size)\r
312     {\r
313         HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",\r
314                   itr.first.c_str(), itr.second.x, itr.second.y,\r
315                   itr.second.w, itr.second.h);\r
316     }\r
317 \r
318     // Release json_object\r
319     json_object_put(json_obj);\r
320 \r
321     return WMError::SUCCESS;\r
322 }\r
323 \r
324 WMError LayerControl::layoutChange(const WMAction& action)\r
325 {\r
326     WMError ret = WMError::FAIL;\r
327     if (action.visible == TaskVisible::INVISIBLE)\r
328     {\r
329         // Visibility is not change -> no redraw is required\r
330         return WMError::SUCCESS;\r
331     }\r
332     if(action.client == nullptr)\r
333     {\r
334         HMI_SEQ_ERROR(action.req_num, "client may vanish");\r
335         return WMError::NOT_REGISTERED;\r
336     }\r
337     unsigned layer = action.client->layerID();\r
338 \r
339     // Layout Manager\r
340     // WMError ret = this->setLayerSize(layer, action.area);\r
341     auto rect = this->getAreaSize(action.area);\r
342     ilmErrorTypes err = ilm_layerSetDestinationRectangle(layer, rect.x, rect.y, rect.w, rect.h);\r
343     if(err == ILM_SUCCESS)\r
344     {\r
345         ret = WMError::SUCCESS;\r
346     }\r
347     return ret;\r
348 }\r
349 \r
350 WMError LayerControl::visibilityChange(const WMAction& action)\r
351 {\r
352     WMError ret = WMError::FAIL;\r
353     if(action.client == nullptr)\r
354     {\r
355         HMI_SEQ_ERROR(action.req_num, "client may vanish");\r
356         return WMError::NOT_REGISTERED;\r
357     }\r
358 \r
359     if (action.visible != TaskVisible::INVISIBLE)\r
360     {\r
361         ret = this->makeVisible(action.client.get());\r
362     }\r
363     else\r
364     {\r
365         ret = this->makeInvisible(action.client.get());\r
366     }\r
367     return ret;\r
368 }\r
369 \r
370 void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created)\r
371 {\r
372     this->cb.test(id);\r
373     if (ILM_SURFACE == object)\r
374     {\r
375         if (created)\r
376         {\r
377             ilmSurfaceProperties sp;\r
378             ilmErrorTypes rc;\r
379             rc = ilm_getPropertiesOfSurface(id, &sp);\r
380             if(rc != ILM_SUCCESS)\r
381                 return;\r
382             // this->cb->surfaceCreated(pid, id);\r
383             ilm_surfaceAddNotification(id, surfaceCallback_static);\r
384             ilm_surfaceSetSourceRectangle(id, 0, 0, sp.origSourceWidth, sp.origSourceHeight);\r
385         }\r
386         else\r
387         {\r
388             // this->cb->surfaceDestroyed(id);\r
389         }\r
390     }\r
391     if (ILM_LAYER == object)\r
392     {\r
393         if(created)\r
394         {\r
395             ilm_layerAddNotification(id, layerCallback_static);\r
396             // this->cb->layerCreated(id);\r
397         }\r
398         else\r
399         {\r
400             // this->cb->layerDestroyed(id); // Means Application is dead.\r
401         }\r
402     }\r
403 }\r
404 \r
405 void LayerControl::dispatchPropertyChangeEvent(unsigned id,\r
406         struct ilmSurfaceProperties* sprop,\r
407         t_ilm_notification_mask mask)\r
408 {\r
409     pid_t pid = sprop->creatorPid;\r
410     HMI_DEBUG("pid : %d", pid);\r
411 \r
412     if (ILM_NOTIFICATION_VISIBILITY & mask)\r
413     {\r
414         //this->cb->surfaceVisibilityChanged(id, sprop->visibility);\r
415     }\r
416     if (ILM_NOTIFICATION_OPACITY & mask)\r
417     {\r
418     }\r
419     if (ILM_NOTIFICATION_ORIENTATION & mask)\r
420     {\r
421     }\r
422     if (ILM_NOTIFICATION_SOURCE_RECT & mask)\r
423     {\r
424         // this->cb->surfaceSourceRectChanged(id, )\r
425     }\r
426     if (ILM_NOTIFICATION_DEST_RECT & mask)\r
427     {\r
428         // this->cb->surfaceSourceRectChanged(id, )\r
429     }\r
430     if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask)\r
431     {\r
432     }\r
433     if (ILM_NOTIFICATION_CONTENT_REMOVED & mask)\r
434     {\r
435         /* application being down */\r
436         // m_appLayers.remove(pid);\r
437     }\r
438     if (ILM_NOTIFICATION_CONFIGURED & mask)\r
439     {\r
440         /* qDebug("ILM_NOTIFICATION_CONFIGURED");\r
441         qDebug("  surfaceProperties %d", surface);\r
442         qDebug("    surfaceProperties.origSourceWidth: %d", surfaceProperties->origSourceWidth);\r
443         qDebug("    surfaceProperties.origSourceHeight: %d", surfaceProperties->origSourceHeight);\r
444 \r
445         if (surface == WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID) {\r
446             addSurfaceToLayer(surface, WINDOWMANAGER_LAYER_HOMESCREEN);\r
447             configureHomeScreenMainSurface(surface, surfaceProperties->origSourceWidth, surfaceProperties->origSourceHeight);\r
448         } else {\r
449             ilmErrorTypes result;\r
450             t_ilm_layer layer = addSurfaceToAppLayer(pid, surface);\r
451 \r
452             if (layer != 0) {\r
453                 configureAppSurface(surface,\r
454                                     surfaceProperties->origSourceWidth,\r
455                                     surfaceProperties->origSourceHeight);\r
456 \r
457                 result = ilm_layerAddSurface(layer, surface);\r
458                 if (result != ILM_SUCCESS) {\r
459                     qDebug("ilm_layerAddSurface(%d,%d) failed.", layer, surface);\r
460                 }\r
461                 ilm_commitChanges();\r
462             }\r
463         }\r
464         updateScreen(); */\r
465     }\r
466 }\r
467 \r
468 void LayerControl::dispatchPropertyChangeEvent(unsigned id,\r
469         struct ilmLayerProperties* lprop,\r
470         t_ilm_notification_mask mask)\r
471 {\r
472     if (ILM_NOTIFICATION_VISIBILITY & mask)\r
473     {\r
474         //this->cb->layerVisibilityChanged(id, sprop->visibility);\r
475     }\r
476     if (ILM_NOTIFICATION_OPACITY & mask)\r
477     {\r
478     }\r
479     if (ILM_NOTIFICATION_ORIENTATION & mask)\r
480     {\r
481     }\r
482     if (ILM_NOTIFICATION_SOURCE_RECT & mask)\r
483     {\r
484         // this->cb->surfaceSourceRectChanged(id, )\r
485     }\r
486     if (ILM_NOTIFICATION_DEST_RECT & mask)\r
487     {\r
488         // this->cb->surfaceSourceRectChanged(id, )\r
489     }\r
490     if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask)\r
491     {\r
492     }\r
493     if (ILM_NOTIFICATION_CONTENT_REMOVED & mask)\r
494     {\r
495         /* application being down */\r
496         // m_appLayers.remove(pid);\r
497     }\r
498     if (ILM_NOTIFICATION_CONFIGURED & mask)\r
499     {\r
500         /* qDebug("ILM_NOTIFICATION_CONFIGURED");\r
501         qDebug("  surfaceProperties %d", surface);\r
502         qDebug("    surfaceProperties.origSourceWidth: %d", surfaceProperties->origSourceWidth);\r
503         qDebug("    surfaceProperties.origSourceHeight: %d", surfaceProperties->origSourceHeight);\r
504 \r
505         if (surface == WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID) {\r
506             addSurfaceToLayer(surface, WINDOWMANAGER_LAYER_HOMESCREEN);\r
507             configureHomeScreenMainSurface(surface, surfaceProperties->origSourceWidth, surfaceProperties->origSourceHeight);\r
508         } else {\r
509             ilmErrorTypes result;\r
510             t_ilm_layer layer = addSurfaceToAppLayer(pid, surface);\r
511 \r
512             if (layer != 0) {\r
513                 configureAppSurface(surface,\r
514                                     surfaceProperties->origSourceWidth,\r
515                                     surfaceProperties->origSourceHeight);\r
516 \r
517                 result = ilm_layerAddSurface(layer, surface);\r
518                 if (result != ILM_SUCCESS) {\r
519                     qDebug("ilm_layerAddSurface(%d,%d) failed.", layer, surface);\r
520                 }\r
521                 ilm_commitChanges();\r
522             }\r
523         }\r
524         updateScreen(); */\r
525     }\r
526 }\r
527 \r
528 WMError LayerControl::makeVisible(const WMClient* client)\r
529 {\r
530     WMError ret = WMError::FAIL;\r
531     // Don't check here the client is not nullptr\r
532     unsigned layer = client->layerID();\r
533     bool contains;// = this->checkBackGround(action.client->role());\r
534     if(contains)\r
535     {\r
536         std::shared_ptr<WMLayer> l;\r
537         // Move background from back ground layer\r
538         for(const auto& wm_layer : this->wm_layers)\r
539         {\r
540             if(wm_layer->layerName() == "BackGroundLayer")\r
541             {\r
542                 //wm_layer.removeLayer(layer);\r
543             }\r
544             else\r
545             {\r
546                 if(wm_layer->checkIDBelongTo(layer))\r
547                 {\r
548                     l = wm_layer;\r
549                 }\r
550             }\r
551         }\r
552         if(l != nullptr)\r
553         {\r
554             // make invisible first\r
555             ilm_layerSetVisibility(layer, 0);\r
556             ilm_commitChanges();\r
557             //l->addLayer(layer);\r
558         }\r
559     }\r
560     for(const auto& wm_layer : this->wm_layers)\r
561     {\r
562         // make visible\r
563         //l->makeVisible(layer);\r
564     }\r
565 \r
566     return ret;\r
567 }\r
568 \r
569 WMError LayerControl::makeInvisible(const WMClient* client)\r
570 {\r
571     WMError ret = WMError::FAIL;\r
572     // Don't check here the client is not nullptr\r
573     unsigned layer = client->layerID();\r
574     bool contains;// = this->checkBackGround(client->role());\r
575     if(contains)\r
576     {\r
577         // Pop from background\r
578     }\r
579     else\r
580     {\r
581 \r
582     }\r
583     return ret;\r
584 }\r
585 } // namespace wm