5b801f777a11c75f82507822f96ddafdb50bd502
[apps/agl-service-windowmanager.git] / src / wm_layer_control.cpp
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3  * Copyright (c) 2018 Konsulko Group
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include <assert.h>
18 #include <unistd.h>
19 #include "wm_layer_control.hpp"
20 #include "wm_layer.hpp"
21 #include "wm_client.hpp"
22 #include "request.hpp"
23 #include "json_helper.hpp"
24
25 #define LC_AREA_FILE "areas.json"
26 #define LC_LAYER_SETTING_FILE "layers.json"
27 #define LC_DEFAULT_AREA "fullscreen"
28 #define BACK_GROUND_LAYER "BackGroundLayer"
29
30 using std::string;
31 using std::vector;
32 using std::shared_ptr;
33
34 namespace wm {
35
36 LayerControl* g_lc_ctxt;
37
38 static void createCallback_static(ilmObjectType object,
39                             t_ilm_uint id,
40                             t_ilm_bool created,
41                             void* data)
42 {
43     static_cast<LayerControl*>(data)->dispatchCreateEvent(object, id, created);
44 }
45
46 static void surfaceCallback_static(t_ilm_surface surface,
47             struct ilmSurfaceProperties* surface_prop,
48             t_ilm_notification_mask mask)
49 {
50     g_lc_ctxt->dispatchSurfacePropChangeEvent(surface, surface_prop, mask);
51 }
52
53 static void layerCallback_static(t_ilm_layer layer,
54             struct ilmLayerProperties* layer_prop,
55             t_ilm_notification_mask mask)
56 {
57     g_lc_ctxt->dispatchLayerPropChangeEvent(layer, layer_prop, mask);
58 }
59
60 LayerControl::LayerControl(const std::string& root)
61 {
62     string area_path(get_file_path(LC_AREA_FILE, root.c_str()));
63     string layer_path(get_file_path(LC_LAYER_SETTING_FILE, root.c_str()));
64     // load layers.setting.json
65     WMError ret = this->loadLayerSetting(layer_path);
66     assert(ret == WMError::SUCCESS);
67     // load areas.json
68     ret = this->loadAreaDb(area_path);
69     assert(ret == WMError::SUCCESS);
70 }
71
72 WMError LayerControl::init(const LayerControlCallbacks& cb)
73 {
74     HMI_DEBUG("Initialize of ilm library and display");
75     t_ilm_uint num = 0;
76     t_ilm_uint *ids;
77     int cnt = 0;
78     ilmErrorTypes rc = ilm_init();
79
80     while (rc != ILM_SUCCESS)
81     {
82         cnt++;
83         if (20 <= cnt)
84         {
85             HMI_ERROR("Could not connect to compositor");
86             goto lc_init_error;
87         }
88         HMI_ERROR("Wait to start weston ...");
89         sleep(1);
90         rc = ilm_init();
91     }
92     if(rc != ILM_SUCCESS) goto lc_init_error;
93
94     // Get current screen setting
95     rc = ilm_getScreenIDs(&num, &ids);
96
97     if(rc != ILM_SUCCESS) goto lc_init_error;
98
99     for(unsigned i = 0; i < num; i++)
100     {
101         HMI_INFO("get screen: %d", ids[i]);
102     }
103     // Currently, 0 is only available
104     this->screenID = ids[0];
105
106     rc = ilm_getPropertiesOfScreen(this->screenID, &this->screen_prop);
107
108     if(rc != ILM_SUCCESS) goto lc_init_error;
109
110     // Register Callback to Window Manager and from ILM
111     this->cb = cb;
112     ilm_registerNotification(createCallback_static, this);
113
114     return WMError::SUCCESS;
115
116 lc_init_error:
117     HMI_ERROR("Failed to initialize. Terminate WM");
118
119     return WMError::FAIL;
120 }
121
122 void LayerControl::createNewLayer(unsigned id)
123 {
124     HMI_INFO("create new ID :%d", id);
125     struct rect rct = this->area2size[LC_DEFAULT_AREA];
126     ilm_layerCreateWithDimension(&id, rct.w, rct.h);
127     //ilm_layerSetSourceRectangle(id, rct.x, rct.y, rct.w, rct.h);
128     ilm_layerSetDestinationRectangle(id, this->offset_x, this->offset_y, rct.w, rct.h);
129     ilm_layerSetOpacity(id, 1.0);
130     ilm_layerSetVisibility(id, ILM_FALSE);
131     ilm_commitChanges();
132     auto wm_layer = getWMLayer(id);
133     wm_layer->addLayerToState(id);
134     this->renderLayers();
135 }
136
137 unsigned LayerControl::getNewLayerID(const string& role)
138 {
139     unsigned ret = 0;
140     for(const auto& l: this->wm_layers)
141     {
142         ret = l->getNewLayerID(role);
143         if(ret != 0)
144         {
145             unsigned wmlid = l->getWMLayerID();
146             this->lid2wmlid[ret] = wmlid;
147             break;
148         }
149     }
150     return ret;
151 }
152
153 shared_ptr<WMLayer> LayerControl::getWMLayer(unsigned layer)
154 {
155     unsigned wm_lid = this->lid2wmlid[layer];
156     return this->wm_layers[wm_lid];
157 }
158
159 std::shared_ptr<WMLayer> LayerControl::getWMLayer(std::string layer_name)
160 {
161     for(auto &l : this->wm_layers)
162     {
163         if(l->layerName() == layer_name)
164         {
165             return l;
166         }
167     }
168     return nullptr;
169 }
170
171 struct rect LayerControl::getAreaSize(const std::string& area)
172 {
173     return area2size[area];
174 }
175
176 void LayerControl::setupArea(const rectangle& base_rct, double scaling)
177 {
178     this->scaling = scaling;
179     this->offset_x = base_rct.left();
180     this->offset_y = base_rct.top();
181
182     for (auto &i : this->area2size)
183     {
184         i.second.x = static_cast<int>(scaling * i.second.x + 0.5);
185         i.second.y = static_cast<int>(scaling * i.second.y + 0.5);
186         i.second.w = static_cast<int>(scaling * i.second.w + 0.5);
187         i.second.h = static_cast<int>(scaling * i.second.h + 0.5);
188
189         HMI_DEBUG("area:%s size(after) : x:%d y:%d w:%d h:%d",
190             i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h);
191     }
192 }
193
194 Screen LayerControl::getScreenInfo()
195 {
196     return Screen(this->screen_prop.screenWidth, this->screen_prop.screenHeight);
197 }
198
199 double LayerControl::scale()
200 {
201     return this->scaling;
202 }
203
204 WMError LayerControl::renderLayers()
205 {
206     HMI_INFO("Commit change");
207     WMError rc = WMError::SUCCESS;
208
209     // Check the number of layers
210     vector<unsigned> ivi_l_ids;
211     for(auto& l : this->wm_layers)
212     {
213         auto state = l->getLayerState();
214         HMI_DEBUG("layer %s", l->layerName().c_str());
215         for(const auto& id : state.getIviIdList())
216         {
217             HMI_DEBUG("Add %d", id);
218             ivi_l_ids.push_back(id);
219         }
220     }
221
222     // Create render order
223     t_ilm_layer* id_array = new t_ilm_layer[ivi_l_ids.size()];
224     if(id_array == nullptr)
225     {
226         HMI_WARNING("short memory");
227         this->undoUpdate();
228         return WMError::FAIL;
229     }
230     int count = 0;
231     for(const auto& i : ivi_l_ids)
232     {
233         id_array[count] = i;
234         ++count;
235     }
236
237     // Display
238     ilmErrorTypes ret = ilm_displaySetRenderOrder(this->screenID, id_array, ivi_l_ids.size());
239     if(ret != ILM_SUCCESS)
240     {
241         this->undoUpdate();
242         rc = WMError::FAIL;
243     }
244     else
245     {
246         for(auto& l : this->wm_layers)
247         {
248             l->update();
249         }
250     }
251     ilm_commitChanges();
252     delete id_array;
253     return rc;
254 }
255
256 WMError LayerControl::setXDGSurfaceOriginSize(unsigned surface)
257 {
258     WMError ret = WMError::NOT_REGISTERED;
259     ilmSurfaceProperties prop;
260     ilmErrorTypes rc = ilm_getPropertiesOfSurface(surface, &prop);
261     if(rc == ILM_SUCCESS)
262     {
263         HMI_INFO("xdg surface info %d, %d", prop.origSourceWidth, prop.origSourceHeight);
264         ilm_surfaceSetSourceRectangle(surface, 0, 0, prop.origSourceWidth, prop.origSourceHeight);
265         ret = WMError::SUCCESS;
266     }
267     return ret;
268 }
269
270
271 void LayerControl::undoUpdate()
272 {
273     for(auto& l : this->wm_layers)
274     {
275         l->undo();
276     }
277 }
278
279 WMError LayerControl::loadLayerSetting(const string &path)
280 {
281     HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path.c_str());
282
283     json_object *json_obj, *json_cfg;
284     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
285     if (0 > ret)
286     {
287         HMI_ERROR("Could not open %s", path.c_str());
288         return WMError::FAIL;
289     }
290     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
291
292     if (!json_object_object_get_ex(json_obj, "mappings", &json_cfg))
293     {
294         HMI_ERROR("Parse Error!!");
295         return WMError::FAIL;
296     }
297
298     int len = json_object_array_length(json_cfg);
299     HMI_DEBUG("json_cfg len:%d", len);
300
301     for (int i = 0; i < len; i++)
302     {
303         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
304         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
305
306         this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp, i));
307     }
308     json_object_put(json_obj);
309
310     return WMError::SUCCESS;
311 }
312
313 WMError LayerControl::loadAreaDb(const std::string& path)
314 {
315     // Load area.db
316     json_object *json_obj;
317     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
318     if (0 > ret)
319     {
320         HMI_ERROR("Could not open %s", path.c_str());
321         return WMError::FAIL;
322     }
323     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
324
325     // Perse areas
326     json_object *json_cfg;
327     if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))
328     {
329         HMI_ERROR("Parse Error!!");
330         return WMError::FAIL;
331     }
332
333     int len = json_object_array_length(json_cfg);
334     HMI_DEBUG("json_cfg len:%d", len);
335
336     const char *area;
337     for (int i = 0; i < len; i++)
338     {
339         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
340         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
341
342         area = jh::getStringFromJson(json_tmp, "name");
343         if (nullptr == area)
344         {
345             HMI_ERROR("Parse Error!!");
346             return WMError::FAIL;
347         }
348         HMI_DEBUG("> area:%s", area);
349
350         json_object *json_rect;
351         if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))
352         {
353             HMI_ERROR("Parse Error!!");
354             return WMError::FAIL;
355         }
356         HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));
357
358         struct rect area_size;
359         area_size.x = jh::getIntFromJson(json_rect, "x");
360         area_size.y = jh::getIntFromJson(json_rect, "y");
361         area_size.w = jh::getIntFromJson(json_rect, "w");
362         area_size.h = jh::getIntFromJson(json_rect, "h");
363
364         this->area2size[area] = area_size;
365     }
366
367     // Check
368     for (const auto& itr : this->area2size)
369     {
370         HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",
371                   itr.first.c_str(), itr.second.x, itr.second.y,
372                   itr.second.w, itr.second.h);
373     }
374
375     // Release json_object
376     json_object_put(json_obj);
377
378     return WMError::SUCCESS;
379 }
380
381 WMError LayerControl::layoutChange(const WMAction& action)
382 {
383     if (action.visible == TaskVisible::INVISIBLE)
384     {
385         // Visibility is not change -> no redraw is required
386         return WMError::SUCCESS;
387     }
388     if(action.client == nullptr)
389     {
390         HMI_SEQ_ERROR(action.req_num, "client may vanish");
391         return WMError::NOT_REGISTERED;
392     }
393     unsigned layer = action.client->layerID();
394     unsigned surface = action.client->surfaceID();
395
396     auto rect = this->getAreaSize(action.area);
397     HMI_SEQ_INFO(action.req_num, "Set layout %d, %d, %d, %d",rect.x, rect.y, rect.w, rect.h);
398
399     // Sometimes, ivi_wm_surface_size signal doesn't reach window manager,
400     // then, Window Manager set set source size = 0.
401     if(!action.client->isSourceSizeSet())
402     {
403         ilmSurfaceProperties sp;
404         if (ILM_SUCCESS != ilm_getPropertiesOfSurface(surface, &sp))
405             return WMError::FAIL;
406
407         if  (sp.origSourceHeight != sp.sourceHeight ||
408              sp.origSourceWidth  != sp.sourceWidth)
409         {
410             HMI_SEQ_NOTICE(action.req_num, "set source size w:%d h%d", sp.origSourceWidth, sp.origSourceHeight);
411             ilm_surfaceSetSourceRectangle(surface, 0, 0, sp.origSourceWidth, sp.origSourceHeight);
412             ilm_commitChanges();
413             action.client->setSurfaceSizeCorrectly();
414         }
415     }
416
417     ilm_surfaceSetDestinationRectangle(surface, rect.x, rect.y, rect.w, rect.h);
418     ilm_commitChanges();
419     action.client->setArea(action.area);
420     for(auto &wm_layer: this->wm_layers)
421     {
422         // Store the state who is assigned to the area
423         if(wm_layer->hasLayerID(layer))
424         {
425             wm_layer->attachAppToArea(action.client->appID(), action.area);
426             /* TODO: manipulate state directly
427             LayerState ls = wm_layer->getLayerState();
428             ls.seattachAppToAreatArea(action.client->appID(), action.area);
429             wm_layer->dump(); */
430         }
431     }
432
433     return WMError::SUCCESS;
434 }
435
436 WMError LayerControl::visibilityChange(const WMAction& action)
437 {
438     WMError ret = WMError::FAIL;
439     if(action.client == nullptr)
440     {
441         HMI_SEQ_ERROR(action.req_num, "client may vanish");
442         return WMError::NOT_REGISTERED;
443     }
444
445     if (action.visible == TaskVisible::VISIBLE)
446     {
447         ret = this->makeVisible(action.client);
448     }
449     else if (action.visible == TaskVisible::INVISIBLE)
450     {
451         ret = this->makeInvisible(action.client);
452     }
453     ilm_commitChanges();
454     return ret;
455 }
456
457 WMError LayerControl::updateAreaList(const ChangeAreaReq& req)
458 {
459     // error check
460     for(const auto& elem : req.area_req)
461     {
462         if(this->area2size.find(elem.first) == this->area2size.end())
463         {
464             HMI_ERROR("requested area %s is not registered in area list", elem.first.c_str());
465             return WMError::NOT_REGISTERED;
466         }
467     }
468     // update list
469     for(const auto& elem : req.area_req)
470     {
471         this->area2size[elem.first] = elem.second;
472     }
473     if(req.save)
474     {
475         HMI_NOTICE("Not implemented");
476         // TODO
477     }
478     return WMError::SUCCESS;
479 }
480
481 WMError LayerControl::getUpdateAreaList(ChangeAreaReq *req)
482 {
483     for(const auto& wm_layer : this->wm_layers)
484     {
485         // get area name and compare it with elem
486         for(const auto& area : req->area_req)
487         {
488             string app = wm_layer->attachedApp(area.first);
489             if(!app.empty())
490             {
491                 HMI_INFO("app %s changes area %s", app.c_str(), area.first.c_str());
492                 req->update_app2area[app] = area.first;
493             }
494         }
495     }
496     return WMError::SUCCESS;
497 }
498
499 void LayerControl::appTerminated(const shared_ptr<WMClient> client)
500 {
501     for(auto& l : this->wm_layers)
502     {
503         if(l->hasLayerID(client->layerID()))
504         {
505             l->appTerminated(client->layerID());
506         }
507     }
508 }
509
510 void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created)
511 {
512     if (ILM_SURFACE == object)
513     {
514         if (created)
515         {
516             ilmSurfaceProperties sp;
517             ilmErrorTypes rc;
518             rc = ilm_getPropertiesOfSurface(id, &sp);
519             if(rc != ILM_SUCCESS)
520             {
521                 HMI_ERROR("Failed to get surface %d property due to %d", id, ilm_getError());
522                 return;
523             }
524             this->cb.surfaceCreated(sp.creatorPid, id);
525             ilm_surfaceAddNotification(id, surfaceCallback_static);
526             ilm_surfaceSetVisibility(id, ILM_TRUE);
527             ilm_surfaceSetType(id, ILM_SURFACETYPE_DESKTOP);
528         }
529         else
530         {
531             this->cb.surfaceDestroyed(id);
532         }
533     }
534     if (ILM_LAYER == object)
535     {
536         if(created)
537         {
538             ilm_layerAddNotification(id, layerCallback_static);
539         }
540         else
541         {
542             // Ignore here. Nothing to do currently.
543             // Process of application dead is handled by Window Manager
544             // from binder notification
545         }
546     }
547 }
548
549 void LayerControl::dispatchSurfacePropChangeEvent(unsigned id,
550         struct ilmSurfaceProperties* sprop,
551         t_ilm_notification_mask mask)
552 {
553     /*
554       ILM_NOTIFICATION_CONTENT_AVAILABLE & ILM_NOTIFICATION_CONTENT_REMOVED
555       are not handled here, handled in create/destroy event
556      */
557     if (ILM_NOTIFICATION_VISIBILITY & mask)
558     {
559         HMI_DEBUG("surface %d turns visibility %d", id, sprop->visibility);
560     }
561     if (ILM_NOTIFICATION_OPACITY & mask)
562     {
563         HMI_DEBUG("surface %d turns opacity %f", id, sprop->opacity);
564     }
565     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
566     {
567         HMI_DEBUG("surface %d source rect changes", id);
568     }
569     if (ILM_NOTIFICATION_DEST_RECT & mask)
570     {
571         HMI_DEBUG("surface %d dest rect changes", id);
572     }
573     if (ILM_NOTIFICATION_CONFIGURED & mask)
574     {
575         HMI_DEBUG("surface %d size %d, %d, %d, %d", id,
576             sprop->sourceX, sprop->sourceY, sprop->origSourceWidth, sprop->origSourceHeight);
577         ilm_surfaceSetSourceRectangle(id, 0, 0, sprop->origSourceWidth, sprop->origSourceHeight);
578     }
579 }
580
581 void LayerControl::dispatchLayerPropChangeEvent(unsigned id,
582         struct ilmLayerProperties* lprop,
583         t_ilm_notification_mask mask)
584 {
585     if (ILM_NOTIFICATION_VISIBILITY & mask)
586     {
587         HMI_DEBUG("layer %d turns visibility %d", id, lprop->visibility);
588     }
589     if (ILM_NOTIFICATION_OPACITY & mask)
590     {
591         HMI_DEBUG("layer %d turns opacity %f", id, lprop->opacity);
592     }
593     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
594     {
595         HMI_DEBUG("layer %d source rect changes", id);
596     }
597     if (ILM_NOTIFICATION_DEST_RECT & mask)
598     {
599         HMI_DEBUG("layer %d dest rect changes", id);
600     }
601 }
602
603 WMError LayerControl::makeVisible(const shared_ptr<WMClient> client)
604 {
605     WMError ret = WMError::SUCCESS;
606     // Don't check here wheher client is nullptr or not
607     unsigned layer = client->layerID();
608
609     this->moveForeGround(client);
610
611     ilm_layerSetVisibility(layer, ILM_TRUE);
612
613     return ret;
614 }
615
616 WMError LayerControl::makeInvisible(const shared_ptr<WMClient> client)
617 {
618     WMError ret = WMError::SUCCESS;
619     // Don't check here the client is not nullptr
620     unsigned layer = client->layerID();
621
622     bool mv_ok = this->moveBackGround(client);
623
624     if(!mv_ok)
625     {
626         HMI_INFO("make invisible client %s", client->appID().c_str());
627         ilm_layerSetVisibility(layer, ILM_FALSE);
628     }
629
630     return ret;
631 }
632
633 bool LayerControl::moveBackGround(const shared_ptr<WMClient> client)
634 {
635     bool ret = false;
636
637     // Move background from foreground layer
638     auto bg = this->getWMLayer(BACK_GROUND_LAYER);
639     if(bg != nullptr)
640     {
641         HMI_DEBUG("client %s role %s", client->appID().c_str(), client->role().c_str());
642         unsigned layer = client->layerID();
643         if(bg->hasRole(client->role()))
644         {
645             HMI_INFO("%s go to background", client->appID().c_str());
646             bg->addLayerToState(layer);
647             auto wm_layer = this->getWMLayer(layer);
648             wm_layer->removeLayerFromState(layer);
649             /* TODO: manipulate state directly
650             LayerState bg_ls = bg->getLayerState();
651             bg_ls.addLayer(layer);
652             LayerState ls = wm_layer->getLayerState();
653             ls.removeLayer(layer); */
654             bg->dump();
655             wm_layer->dump();
656             ret = true;
657         }
658     }
659     return ret;
660 }
661
662 bool LayerControl::moveForeGround(const shared_ptr<WMClient> client)
663 {
664     bool ret = false;
665
666     // Move foreground from foreground layer
667     auto bg = this->getWMLayer(BACK_GROUND_LAYER);
668     if(bg != nullptr)
669     {
670         if(bg->hasRole(client->role()))
671         {
672             unsigned layer = client->layerID();
673             HMI_INFO("%s go to foreground", client->appID().c_str());
674             bg->removeLayerFromState(layer);
675             auto wm_layer = this->getWMLayer(layer);
676             wm_layer->addLayerToState(layer);
677             /* TODO: manipulate state directly
678             LayerState bg_ls = bg->getLayerState();
679             bg_ls.removeLayer(layer);
680             LayerState ls = wm_layer->getLayerState();
681             ls.addLayer(layer); */
682             bg->dump();
683             wm_layer->dump();
684             ret = true;
685         }
686     }
687     return ret;
688 }
689
690 } // namespace wm