2 * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
24 #define LC_AREA_PATH "/etc/areas.db"
25 #define LC_LAYER_SETTING_PATH "/etc/layers.json"
26 #define LC_DEFAULT_AREA "fullscreen"
27 #define BACK_GROUND_LAYER "BackGroundLayer"
31 using std::shared_ptr;
35 LayerControl* g_lc_ctxt;
37 static void createCallback_static(ilmObjectType object,
42 static_cast<LayerControl*>(data)->dispatchCreateEvent(object, id, created);
45 static void surfaceCallback_static(t_ilm_surface surface,
46 struct ilmSurfaceProperties* surface_prop,
47 t_ilm_notification_mask mask)
49 g_lc_ctxt->dispatchSurfacePropChangeEvent(surface, surface_prop, mask);
52 static void layerCallback_static(t_ilm_layer layer,
53 struct ilmLayerProperties* layer_prop,
54 t_ilm_notification_mask mask)
56 g_lc_ctxt->dispatchLayerPropChangeEvent(layer, layer_prop, mask);
59 LayerControl::LayerControl(const std::string& root)
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);
67 ret = this->loadAreaDb(area_path);
68 assert(ret == WMError::SUCCESS);
71 WMError LayerControl::init(const LayerControlCallbacks& cb)
73 HMI_DEBUG("Initialize of ilm library and display");
77 ilmErrorTypes rc = ilm_init();
79 while (rc != ILM_SUCCESS)
84 HMI_ERROR("Could not connect to compositor");
87 HMI_ERROR("Wait to start weston ...");
91 if(rc != ILM_SUCCESS) goto lc_init_error;
93 // Get current screen setting
94 rc = ilm_getScreenIDs(&num, &ids);
96 if(rc != ILM_SUCCESS) goto lc_init_error;
98 for(unsigned i = 0; i < num; i++)
100 HMI_INFO("get screen: %d", ids[i]);
102 // Currently, 0 is only available
103 this->screenID = ids[0];
105 rc = ilm_getPropertiesOfScreen(this->screenID, &this->screen_prop);
107 if(rc != ILM_SUCCESS) goto lc_init_error;
109 // Register Callback to Window Manager and from ILM
111 ilm_registerNotification(createCallback_static, this);
113 return WMError::SUCCESS;
116 HMI_ERROR("Failed to initialize. Terminate WM");
118 return WMError::FAIL;
121 unsigned LayerControl::getLayerID(const string& role)
124 for(const auto& l: this->wm_layers)
134 void LayerControl::addSurface(unsigned surface, unsigned layer)
136 ilm_layerAddSurface(layer, surface);
140 void LayerControl::createLayers()
142 for(const auto &layer : this->wm_layers)
144 unsigned id = layer->layerID();
145 HMI_INFO("create new ID :%d", id);
146 struct rect rct = this->area2size[LC_DEFAULT_AREA];
147 ilm_layerCreateWithDimension(&id, rct.w, rct.h);
148 //ilm_layerSetSourceRectangle(id, rct.x, rct.y, rct.w, rct.h);
149 ilm_layerSetDestinationRectangle(id, this->offset_x, this->offset_y, rct.w, rct.h);
150 ilm_layerSetOpacity(id, 1.0);
151 ilm_layerSetVisibility(id, ILM_TRUE);
153 /* auto wm_layer = getWMLayer(id);
154 wm_layer->addLayerToState(id); */
156 this->renderLayers();
159 shared_ptr<WMLayer> LayerControl::getWMLayer(unsigned layer)
161 unsigned uuid = this->lid2wmlid[layer];
162 return this->wm_layers[uuid];
165 std::shared_ptr<WMLayer> LayerControl::getWMLayer(std::string layer_name)
167 for(auto &l : this->wm_layers)
169 if(l->layerName() == layer_name)
177 struct rect LayerControl::getAreaSize(const std::string& area)
179 return area2size[area];
182 void LayerControl::setupArea(const rectangle& base_rct, double scaling)
184 this->scaling = scaling;
185 this->offset_x = base_rct.left();
186 this->offset_y = base_rct.top();
188 for (auto &i : this->area2size)
190 i.second.x = static_cast<int>(scaling * i.second.x + 0.5);
191 i.second.y = static_cast<int>(scaling * i.second.y + 0.5);
192 i.second.w = static_cast<int>(scaling * i.second.w + 0.5);
193 i.second.h = static_cast<int>(scaling * i.second.h + 0.5);
195 HMI_DEBUG("area:%s size(after) : x:%d y:%d w:%d h:%d",
196 i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h);
200 Screen LayerControl::getScreenInfo()
202 return Screen(this->screen_prop.screenWidth, this->screen_prop.screenHeight);
205 double LayerControl::scale()
207 return this->scaling;
210 WMError LayerControl::renderLayers()
212 HMI_INFO("Commit change");
213 WMError rc = WMError::SUCCESS;
215 // Create render order
216 t_ilm_layer* id_array = new t_ilm_layer[this->wm_layers.size()];
217 if(id_array == nullptr)
219 HMI_WARNING("short memory");
220 return WMError::FAIL;
223 for(const auto& i : this->wm_layers)
225 id_array[count] = i->layerID();
230 ilmErrorTypes ret = ilm_displaySetRenderOrder(this->screenID, id_array, this->wm_layers.size());
231 if(ret != ILM_SUCCESS)
240 WMError LayerControl::setXDGSurfaceOriginSize(unsigned surface)
242 WMError ret = WMError::NOT_REGISTERED;
243 ilmSurfaceProperties prop;
244 ilmErrorTypes rc = ilm_getPropertiesOfSurface(surface, &prop);
245 if(rc == ILM_SUCCESS)
247 HMI_INFO("xdg surface info %d, %d", prop.origSourceWidth, prop.origSourceHeight);
248 ilm_surfaceSetSourceRectangle(surface, 0, 0, prop.origSourceWidth, prop.origSourceHeight);
249 ret = WMError::SUCCESS;
254 WMError LayerControl::loadLayerSetting(const string &path)
256 HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path);
258 json_object *json_obj, *json_cfg;
259 int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
262 HMI_ERROR("Could not open %s", path.c_str());
263 return WMError::FAIL;
265 HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
267 if (!json_object_object_get_ex(json_obj, "mappings", &json_cfg))
269 HMI_ERROR("Parse Error!!");
270 return WMError::FAIL;
273 int len = json_object_array_length(json_cfg);
274 HMI_DEBUG("json_cfg len:%d", len);
276 for (int i = 0; i < len; i++)
278 json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
279 HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
281 this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp));
283 json_object_put(json_obj);
285 return WMError::SUCCESS;
288 WMError LayerControl::loadAreaDb(const std::string& path)
291 json_object *json_obj;
292 int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
295 HMI_ERROR("Could not open %s", path.c_str());
296 return WMError::FAIL;
298 HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
301 json_object *json_cfg;
302 if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))
304 HMI_ERROR("Parse Error!!");
305 return WMError::FAIL;
308 int len = json_object_array_length(json_cfg);
309 HMI_DEBUG("json_cfg len:%d", len);
312 for (int i = 0; i < len; i++)
314 json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
315 HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
317 area = jh::getStringFromJson(json_tmp, "name");
320 HMI_ERROR("Parse Error!!");
321 return WMError::FAIL;
323 HMI_DEBUG("> area:%s", area);
325 json_object *json_rect;
326 if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))
328 HMI_ERROR("Parse Error!!");
329 return WMError::FAIL;
331 HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));
333 struct rect area_size;
334 area_size.x = jh::getIntFromJson(json_rect, "x");
335 area_size.y = jh::getIntFromJson(json_rect, "y");
336 area_size.w = jh::getIntFromJson(json_rect, "w");
337 area_size.h = jh::getIntFromJson(json_rect, "h");
339 this->area2size[area] = area_size;
343 for (const auto& itr : this->area2size)
345 HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",
346 itr.first.c_str(), itr.second.x, itr.second.y,
347 itr.second.w, itr.second.h);
350 // Release json_object
351 json_object_put(json_obj);
353 return WMError::SUCCESS;
356 WMError LayerControl::layoutChange(const WMAction& action)
358 if (action.visible == TaskVisible::INVISIBLE)
360 // Visibility is not change -> no redraw is required
361 return WMError::SUCCESS;
363 if(action.client == nullptr)
365 HMI_SEQ_ERROR(action.req_num, "client may vanish");
366 return WMError::NOT_REGISTERED;
368 unsigned surface = action.client->surfaceID(action.role);
370 auto rect = this->getAreaSize(action.area);
371 HMI_DEBUG("Set layout %d, %d, %d, %d",rect.x, rect.y, rect.w, rect.h);
373 ilm_surfaceSetDestinationRectangle(surface, rect.x, rect.y, rect.w, rect.h);
376 return WMError::SUCCESS;
379 WMError LayerControl::visibilityChange(const WMAction& action)
381 WMError ret = WMError::FAIL;
382 if(action.client == nullptr)
384 HMI_SEQ_ERROR(action.req_num, "client may vanish");
385 return WMError::NOT_REGISTERED;
388 if (action.visible == TaskVisible::VISIBLE)
390 ret = this->makeVisible(action.client, action.role);
392 else if (action.visible == TaskVisible::INVISIBLE)
394 ret = this->makeInvisible(action.client, action.role);
400 void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created)
402 if (ILM_SURFACE == object)
406 ilmSurfaceProperties sp;
408 rc = ilm_getPropertiesOfSurface(id, &sp);
409 if(rc != ILM_SUCCESS)
411 HMI_ERROR("Failed to get surface %d property due to %d", id, ilm_getError());
414 this->cb.surfaceCreated(sp.creatorPid, id);
415 ilm_surfaceAddNotification(id, surfaceCallback_static);
416 ilm_surfaceSetType(id, ILM_SURFACETYPE_DESKTOP);
420 this->cb.surfaceDestroyed(id);
423 if (ILM_LAYER == object)
427 ilm_layerAddNotification(id, layerCallback_static);
431 // Ignore here. Nothing to do currently.
432 // Process of application dead is handled by Window Manager
433 // from binder notification
438 void LayerControl::dispatchSurfacePropChangeEvent(unsigned id,
439 struct ilmSurfaceProperties* sprop,
440 t_ilm_notification_mask mask)
443 ILM_NOTIFICATION_CONTENT_AVAILABLE & ILM_NOTIFICATION_CONTENT_REMOVED
444 are not handled here, handled in create/destroy event
446 if (ILM_NOTIFICATION_VISIBILITY & mask)
448 HMI_DEBUG("surface %d turns visibility %d", id, sprop->visibility);
450 if (ILM_NOTIFICATION_OPACITY & mask)
452 HMI_DEBUG("surface %d turns opacity %f", id, sprop->opacity);
454 if (ILM_NOTIFICATION_SOURCE_RECT & mask)
456 HMI_DEBUG("surface %d source rect changes", id);
458 if (ILM_NOTIFICATION_DEST_RECT & mask)
460 HMI_DEBUG("surface %d dest rect changes", id);
462 if (ILM_NOTIFICATION_CONFIGURED & mask)
464 HMI_DEBUG("surface %d size %d, %d, %d, %d", id,
465 sprop->sourceX, sprop->sourceY, sprop->origSourceWidth, sprop->origSourceHeight);
466 ilm_surfaceSetSourceRectangle(id, 0, 0, sprop->origSourceWidth, sprop->origSourceHeight);
470 void LayerControl::dispatchLayerPropChangeEvent(unsigned id,
471 struct ilmLayerProperties* lprop,
472 t_ilm_notification_mask mask)
474 if (ILM_NOTIFICATION_VISIBILITY & mask)
476 HMI_DEBUG("layer %d turns visibility %d", id, lprop->visibility);
478 if (ILM_NOTIFICATION_OPACITY & mask)
480 HMI_DEBUG("layer %d turns opacity %f", id, lprop->opacity);
482 if (ILM_NOTIFICATION_SOURCE_RECT & mask)
484 HMI_DEBUG("layer %d source rect changes", id);
486 if (ILM_NOTIFICATION_DEST_RECT & mask)
488 HMI_DEBUG("layer %d dest rect changes", id);
492 WMError LayerControl::makeVisible(const shared_ptr<WMClient> client, const string& role)
494 WMError ret = WMError::SUCCESS;
495 // Don't check here the client is not nullptr
496 unsigned surface = client->surfaceID(role);
498 this->moveForeGround(client, role);
500 ilm_surfaceSetVisibility(surface, ILM_TRUE);
505 WMError LayerControl::makeInvisible(const shared_ptr<WMClient> client, const string& role)
507 WMError ret = WMError::SUCCESS;
508 unsigned surface = client->surfaceID(role); // Don't check here the client is not nullptr
510 bool mv_ok = this->moveBackGround(client, role);
514 HMI_INFO("make invisible client %s", client->appID().c_str());
515 ilm_surfaceSetVisibility(surface, ILM_FALSE);
521 bool LayerControl::moveBackGround(const shared_ptr<WMClient> client, const string& role)
524 const char* label = role.c_str();
526 if ((0 == strcmp(label, "radio")) ||
527 (0 == strcmp(label, "music")) ||
528 (0 == strcmp(label, "video")) ||
529 (0 == strcmp(label, "map")))
531 unsigned surface = client->surfaceID(role);
532 this->surface_bg.push_back(surface);
533 auto bg = this->getWMLayer(BACK_GROUND_LAYER);
535 for(const auto& l : this->wm_layers)
539 layer = l->layerID();
540 ilm_layerRemoveSurface(layer, surface);
541 ilm_layerAddSurface(bg->layerID(), surface);
551 bool LayerControl::moveForeGround(const shared_ptr<WMClient> client, const string& role)
554 const char* label = role.c_str();
556 // Move foreground from foreground layer
557 if ((0 == strcmp(label, "radio")) ||
558 (0 == strcmp(label, "music")) ||
559 (0 == strcmp(label, "video")) ||
560 (0 == strcmp(label, "map")))
562 for (auto i = surface_bg.begin(); i != surface_bg.end(); ++i)
564 if (client->surfaceID(role) == *i)
567 unsigned surface = *i;
569 this->surface_bg.erase(i);
571 // Remove from BG layer (999)
572 HMI_DEBUG("wm", "Remove %s(%d) from BG layer", label, surface);
573 auto bg = this->getWMLayer(BACK_GROUND_LAYER);
575 for(const auto& l : this->wm_layers)
579 layer = l->layerID();
583 ilm_layerRemoveSurface(bg->layerID(), surface);
584 ilm_layerAddSurface(layer, surface);