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