c5c7913a40cdf27b839c6221a9a898d14bfc1e5d
[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         ilm_getPropertiesOfSurface(surface, &sp);
405         if((sp.origSourceHeight != sp.sourceHeight) || (sp.origSourceWidth != sp.sourceWidth))
406         {
407             HMI_SEQ_NOTICE(action.req_num, "set source size w:%d h%d", sp.origSourceWidth, sp.origSourceHeight);
408             ilm_surfaceSetSourceRectangle(surface, 0, 0, sp.origSourceWidth, sp.origSourceHeight);
409             ilm_commitChanges();
410             action.client->setSurfaceSizeCorrectly();
411         }
412     }
413
414     ilm_surfaceSetDestinationRectangle(surface, rect.x, rect.y, rect.w, rect.h);
415     ilm_commitChanges();
416     action.client->setArea(action.area);
417     for(auto &wm_layer: this->wm_layers)
418     {
419         // Store the state who is assigned to the area
420         if(wm_layer->hasLayerID(layer))
421         {
422             wm_layer->attachAppToArea(action.client->appID(), action.area);
423             /* TODO: manipulate state directly
424             LayerState ls = wm_layer->getLayerState();
425             ls.seattachAppToAreatArea(action.client->appID(), action.area);
426             wm_layer->dump(); */
427         }
428     }
429
430     return WMError::SUCCESS;
431 }
432
433 WMError LayerControl::visibilityChange(const WMAction& action)
434 {
435     WMError ret = WMError::FAIL;
436     if(action.client == nullptr)
437     {
438         HMI_SEQ_ERROR(action.req_num, "client may vanish");
439         return WMError::NOT_REGISTERED;
440     }
441
442     if (action.visible == TaskVisible::VISIBLE)
443     {
444         ret = this->makeVisible(action.client);
445     }
446     else if (action.visible == TaskVisible::INVISIBLE)
447     {
448         ret = this->makeInvisible(action.client);
449     }
450     ilm_commitChanges();
451     return ret;
452 }
453
454 WMError LayerControl::updateAreaList(const ChangeAreaReq& req)
455 {
456     // error check
457     for(const auto& elem : req.area_req)
458     {
459         if(this->area2size.find(elem.first) == this->area2size.end())
460         {
461             HMI_ERROR("requested area %s is not registered in area list", elem.first.c_str());
462             return WMError::NOT_REGISTERED;
463         }
464     }
465     // update list
466     for(const auto& elem : req.area_req)
467     {
468         this->area2size[elem.first] = elem.second;
469     }
470     if(req.save)
471     {
472         HMI_NOTICE("Not implemented");
473         // TODO
474     }
475     return WMError::SUCCESS;
476 }
477
478 WMError LayerControl::getUpdateAreaList(ChangeAreaReq *req)
479 {
480     for(const auto& wm_layer : this->wm_layers)
481     {
482         // get area name and compare it with elem
483         for(const auto& area : req->area_req)
484         {
485             string app = wm_layer->attachedApp(area.first);
486             if(!app.empty())
487             {
488                 HMI_INFO("app %s changes area %s", app.c_str(), area.first.c_str());
489                 req->update_app2area[app] = area.first;
490             }
491         }
492     }
493     return WMError::SUCCESS;
494 }
495
496 void LayerControl::appTerminated(const shared_ptr<WMClient> client)
497 {
498     for(auto& l : this->wm_layers)
499     {
500         if(l->hasLayerID(client->layerID()))
501         {
502             l->appTerminated(client->layerID());
503         }
504     }
505 }
506
507 void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created)
508 {
509     if (ILM_SURFACE == object)
510     {
511         if (created)
512         {
513             ilmSurfaceProperties sp;
514             ilmErrorTypes rc;
515             rc = ilm_getPropertiesOfSurface(id, &sp);
516             if(rc != ILM_SUCCESS)
517             {
518                 HMI_ERROR("Failed to get surface %d property due to %d", id, ilm_getError());
519                 return;
520             }
521             this->cb.surfaceCreated(sp.creatorPid, id);
522             ilm_surfaceAddNotification(id, surfaceCallback_static);
523             ilm_surfaceSetVisibility(id, ILM_TRUE);
524             ilm_surfaceSetType(id, ILM_SURFACETYPE_DESKTOP);
525         }
526         else
527         {
528             this->cb.surfaceDestroyed(id);
529         }
530     }
531     if (ILM_LAYER == object)
532     {
533         if(created)
534         {
535             ilm_layerAddNotification(id, layerCallback_static);
536         }
537         else
538         {
539             // Ignore here. Nothing to do currently.
540             // Process of application dead is handled by Window Manager
541             // from binder notification
542         }
543     }
544 }
545
546 void LayerControl::dispatchSurfacePropChangeEvent(unsigned id,
547         struct ilmSurfaceProperties* sprop,
548         t_ilm_notification_mask mask)
549 {
550     /*
551       ILM_NOTIFICATION_CONTENT_AVAILABLE & ILM_NOTIFICATION_CONTENT_REMOVED
552       are not handled here, handled in create/destroy event
553      */
554     if (ILM_NOTIFICATION_VISIBILITY & mask)
555     {
556         HMI_DEBUG("surface %d turns visibility %d", id, sprop->visibility);
557     }
558     if (ILM_NOTIFICATION_OPACITY & mask)
559     {
560         HMI_DEBUG("surface %d turns opacity %f", id, sprop->opacity);
561     }
562     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
563     {
564         HMI_DEBUG("surface %d source rect changes", id);
565     }
566     if (ILM_NOTIFICATION_DEST_RECT & mask)
567     {
568         HMI_DEBUG("surface %d dest rect changes", id);
569     }
570     if (ILM_NOTIFICATION_CONFIGURED & mask)
571     {
572         HMI_DEBUG("surface %d size %d, %d, %d, %d", id,
573             sprop->sourceX, sprop->sourceY, sprop->origSourceWidth, sprop->origSourceHeight);
574         ilm_surfaceSetSourceRectangle(id, 0, 0, sprop->origSourceWidth, sprop->origSourceHeight);
575     }
576 }
577
578 void LayerControl::dispatchLayerPropChangeEvent(unsigned id,
579         struct ilmLayerProperties* lprop,
580         t_ilm_notification_mask mask)
581 {
582     if (ILM_NOTIFICATION_VISIBILITY & mask)
583     {
584         HMI_DEBUG("layer %d turns visibility %d", id, lprop->visibility);
585     }
586     if (ILM_NOTIFICATION_OPACITY & mask)
587     {
588         HMI_DEBUG("layer %d turns opacity %f", id, lprop->opacity);
589     }
590     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
591     {
592         HMI_DEBUG("layer %d source rect changes", id);
593     }
594     if (ILM_NOTIFICATION_DEST_RECT & mask)
595     {
596         HMI_DEBUG("layer %d dest rect changes", id);
597     }
598 }
599
600 WMError LayerControl::makeVisible(const shared_ptr<WMClient> client)
601 {
602     WMError ret = WMError::SUCCESS;
603     // Don't check here wheher client is nullptr or not
604     unsigned layer = client->layerID();
605
606     this->moveForeGround(client);
607
608     ilm_layerSetVisibility(layer, ILM_TRUE);
609
610     return ret;
611 }
612
613 WMError LayerControl::makeInvisible(const shared_ptr<WMClient> client)
614 {
615     WMError ret = WMError::SUCCESS;
616     // Don't check here the client is not nullptr
617     unsigned layer = client->layerID();
618
619     bool mv_ok = this->moveBackGround(client);
620
621     if(!mv_ok)
622     {
623         HMI_INFO("make invisible client %s", client->appID().c_str());
624         ilm_layerSetVisibility(layer, ILM_FALSE);
625     }
626
627     return ret;
628 }
629
630 bool LayerControl::moveBackGround(const shared_ptr<WMClient> client)
631 {
632     bool ret = false;
633
634     // Move background from foreground layer
635     auto bg = this->getWMLayer(BACK_GROUND_LAYER);
636     if(bg != nullptr)
637     {
638         HMI_DEBUG("client %s role %s", client->appID().c_str(), client->role().c_str());
639         unsigned layer = client->layerID();
640         if(bg->hasRole(client->role()))
641         {
642             HMI_INFO("%s go to background", client->appID().c_str());
643             bg->addLayerToState(layer);
644             auto wm_layer = this->getWMLayer(layer);
645             wm_layer->removeLayerFromState(layer);
646             /* TODO: manipulate state directly
647             LayerState bg_ls = bg->getLayerState();
648             bg_ls.addLayer(layer);
649             LayerState ls = wm_layer->getLayerState();
650             ls.removeLayer(layer); */
651             bg->dump();
652             wm_layer->dump();
653             ret = true;
654         }
655     }
656     return ret;
657 }
658
659 bool LayerControl::moveForeGround(const shared_ptr<WMClient> client)
660 {
661     bool ret = false;
662
663     // Move foreground from foreground layer
664     auto bg = this->getWMLayer(BACK_GROUND_LAYER);
665     if(bg != nullptr)
666     {
667         if(bg->hasRole(client->role()))
668         {
669             unsigned layer = client->layerID();
670             HMI_INFO("%s go to foreground", client->appID().c_str());
671             bg->removeLayerFromState(layer);
672             auto wm_layer = this->getWMLayer(layer);
673             wm_layer->addLayerToState(layer);
674             /* TODO: manipulate state directly
675             LayerState bg_ls = bg->getLayerState();
676             bg_ls.removeLayer(layer);
677             LayerState ls = wm_layer->getLayerState();
678             ls.addLayer(layer); */
679             bg->dump();
680             wm_layer->dump();
681             ret = true;
682         }
683     }
684     return ret;
685 }
686
687 } // namespace wm