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