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.json"
25 #define LC_LAYER_SETTING_PATH "/etc/layers.json"
26 #define LC_WESTON_SETTING_PATH "/etc/weston.json"
27 #define LC_DEFAULT_AREA "fullscreen"
28 #define BACK_GROUND_LAYER "BackGroundLayer"
29 #define AREA_NAME_RSE1 "rse1.normal.full"
30 #define AREA_NAME_RSE2 "rse2.normal.full"
31 #define AREA_NAME_HUD "hud.normal.full"
32 #define AREA_NAME_HUD_UL "hud.upper.left"
33 #define defaultWestonTimes 60000
34 #define defaultWestonSleep 50
38 using std::shared_ptr;
42 LayerControl* g_lc_ctxt;
44 static void createCallback_static(ilmObjectType object,
49 static_cast<LayerControl*>(data)->dispatchCreateEvent(object, id, created);
52 static void surfaceCallback_static(t_ilm_surface surface,
53 struct ilmSurfaceProperties* surface_prop,
54 t_ilm_notification_mask mask)
56 g_lc_ctxt->dispatchSurfacePropChangeEvent(surface, surface_prop, mask);
59 static void layerCallback_static(t_ilm_layer layer,
60 struct ilmLayerProperties* layer_prop,
61 t_ilm_notification_mask mask)
63 g_lc_ctxt->dispatchLayerPropChangeEvent(layer, layer_prop, mask);
66 LayerControl::LayerControl(const std::string& root, const std::string& ecu_name)
68 string area_path = root + LC_AREA_PATH;
69 string layer_path= root + LC_LAYER_SETTING_PATH;
70 string weston_path = root + LC_WESTON_SETTING_PATH;
72 this->loadWestonSetting(weston_path);
74 // load layers.setting.json
75 WMError ret = this->loadLayerSetting(layer_path);
76 assert(ret == WMError::SUCCESS);
78 ret = this->loadAreasConfigFile(area_path, ecu_name);
79 assert(ret == WMError::SUCCESS);
82 WMError LayerControl::init(const LayerControlCallbacks& cb)
84 HMI_DEBUG("Initialize of ilm library and display");
88 struct timespec startTs, endTs;
90 if (clock_gettime(CLOCK_BOOTTIME, &startTs) != 0)
92 HMI_ERROR("Could't set time (clock_gettime() returns with error");
98 while ((startTs.tv_sec + (this->times / 1000)) > endTs.tv_sec)
102 if (rc == ILM_SUCCESS)
104 HMI_DEBUG("Weston Connected");
108 HMI_ERROR("Wait to start weston ...");
109 usleep(this->sleep * 1000);
111 if (clock_gettime(CLOCK_BOOTTIME, &endTs) != 0)
113 HMI_ERROR("Could't set time (clock_gettime() returns with error");
118 if(rc != ILM_SUCCESS) goto lc_init_error;
120 // Get current screen setting
121 rc = ilm_getScreenIDs(&num, &ids);
123 if(rc != ILM_SUCCESS) goto lc_init_error;
125 for(unsigned i = 0; i < num; i++)
127 HMI_INFO("get screen: %d", ids[i]);
128 ilmScreenProperties prop;
129 rc = ilm_getPropertiesOfScreen(ids[i], &prop);
131 if(rc != ILM_SUCCESS) goto lc_init_error;
132 this->wm_screens.emplace_back(Screen(ids[i], prop.screenWidth, prop.screenHeight));
135 // Currently, 0 is only available
136 this->screenID = ids[0];
138 if(rc != ILM_SUCCESS) goto lc_init_error;
140 // Register Callback to Window Manager and from ILM
142 ilm_registerNotification(createCallback_static, this);
144 return WMError::SUCCESS;
147 HMI_ERROR("Failed to initialize. Terminate WM");
149 return WMError::FAIL;
152 void LayerControl::createNewLayer(unsigned id)
154 HMI_INFO("create new ID :%d", id);
155 struct rect rct = this->area2size[LC_DEFAULT_AREA];
156 ilm_layerCreateWithDimension(&id, rct.w, rct.h);
157 //ilm_layerSetSourceRectangle(id, rct.x, rct.y, rct.w, rct.h);
158 ilm_layerSetDestinationRectangle(id, this->offset_x, this->offset_y, rct.w, rct.h);
159 ilm_layerSetOpacity(id, 1.0);
160 ilm_layerSetVisibility(id, ILM_FALSE);
162 auto wm_layer = getWMLayer(id);
163 wm_layer->addLayerToState(id);
164 this->renderLayers();
167 void LayerControl::createNewRemoteLayer(unsigned id)
169 HMI_INFO("create new ID :%d (For remote layer)", id);
170 struct rect rct = {640, 720, 0, 0};
171 ilm_layerCreateWithDimension(&id, rct.w, rct.h);
172 //ilm_layerSetSourceRectangle(id, rct.x, rct.y, rct.w, rct.h);
173 ilm_layerSetDestinationRectangle(id, this->offset_x, this->offset_y, rct.w, rct.h);
174 ilm_layerSetOpacity(id, 1.0);
175 ilm_layerSetVisibility(id, ILM_FALSE);
177 auto wm_layer = getWMLayer(id);
178 wm_layer->addLayerToState(id);
179 this->renderLayers();
182 unsigned LayerControl::getNewLayerID(const string& role, string* layer_name)
185 for(const auto& l: this->wm_layers)
187 ret = l->getNewLayerID(role);
190 *layer_name = l->layerName();
191 unsigned wmlid = l->getWMLayerID();
192 this->lid2wmlid[ret] = wmlid;
199 shared_ptr<WMLayer> LayerControl::getWMLayer(unsigned layer)
201 unsigned wm_lid = this->lid2wmlid[layer];
202 return this->wm_layers[wm_lid];
205 std::shared_ptr<WMLayer> LayerControl::getWMLayer(std::string layer_name)
207 for(auto &l : this->wm_layers)
209 if(l->layerName() == layer_name)
217 struct rect LayerControl::getAreaSize(const std::string& area)
219 return area2size[area];
222 void LayerControl::setupArea(const rectangle& base_rct, double scaling)
224 this->scaling = scaling;
225 this->offset_x = base_rct.left();
226 this->offset_y = base_rct.top();
228 // TODO: set all screen
229 this->wm_screens[0].setScale(scaling);
230 this->wm_screens[0].setOffset(offset_x, offset_y);
232 for (auto &i : this->area2size)
234 i.second.x = static_cast<int>(scaling * i.second.x + 0.5);
235 i.second.y = static_cast<int>(scaling * i.second.y + 0.5);
236 i.second.w = static_cast<int>(scaling * i.second.w + 0.5);
237 i.second.h = static_cast<int>(scaling * i.second.h + 0.5);
239 HMI_DEBUG("area:%s size(after) : x:%d y:%d w:%d h:%d",
240 i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h);
244 Screen LayerControl::getScreenInfo()
246 return wm_screens[0];
249 double LayerControl::scale()
251 return this->scaling;
254 WMError LayerControl::updateLayer(LayerState& layer_state)
256 return WMError::SUCCESS;
259 WMError LayerControl::renderLayers()
261 HMI_INFO("Commit change");
262 WMError rc = WMError::SUCCESS;
264 // Create render order for each screen and set render order
265 for(const auto& screen : this->wm_screens)
267 unsigned size_ids = 0;
268 for(const auto& wm_l : this->wm_layers)
270 if(wm_l->getScreenID() == screen.id())
272 for(const auto& id : wm_l->getLayerState().getIviIdList())
278 t_ilm_layer* id_array = new t_ilm_layer[size_ids];
279 if(id_array == nullptr)
281 HMI_WARNING("short memory");
283 return WMError::FAIL;
286 for(const auto& wm_l : this->wm_layers)
288 if(wm_l->getScreenID() == screen.id())
290 for(const auto& id : wm_l->getLayerState().getIviIdList())
299 ilmErrorTypes ret = ilm_displaySetRenderOrder(screen.id(), id_array, size_ids);
300 if(ret != ILM_SUCCESS)
303 return WMError::FAIL;
307 for(auto& l : this->wm_layers)
309 if(l->getScreenID() == screen.id()) {
320 WMError LayerControl::setXDGSurfaceOriginSize(unsigned surface)
322 WMError ret = WMError::NOT_REGISTERED;
323 ilmSurfaceProperties prop;
324 ilmErrorTypes rc = ilm_getPropertiesOfSurface(surface, &prop);
325 if(rc == ILM_SUCCESS)
327 HMI_INFO("xdg surface info %d, %d", prop.origSourceWidth, prop.origSourceHeight);
328 ilm_surfaceSetSourceRectangle(surface, 0, 0, prop.origSourceWidth, prop.origSourceHeight);
329 ret = WMError::SUCCESS;
335 void LayerControl::undoUpdate()
337 for(auto& l : this->wm_layers)
343 int LayerControl::loadWestonSetting(const string &path)
345 HMI_DEBUG("loading Weston(Conpositor Time Out) Setting from %s", path.c_str());
347 json_object *json_obj;
349 int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
352 HMI_ERROR("Could not open %s, so use default", path.c_str());
353 this->times = defaultWestonTimes;
354 this->sleep = defaultWestonSleep;
357 HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
359 long times = jh::getIntFromJson(json_obj, "times");
360 this->times = (0 != times) ? times : defaultWestonTimes;
362 long sleep = jh::getIntFromJson(json_obj, "sleep");
363 this->sleep = (0 != sleep) ? sleep : defaultWestonSleep;
368 WMError LayerControl::loadLayerSetting(const string &path)
370 HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path);
372 json_object *json_obj, *json_cfg;
373 int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
376 HMI_ERROR("Could not open %s", path.c_str());
377 return WMError::FAIL;
379 HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
381 if (!json_object_object_get_ex(json_obj, "mappings", &json_cfg))
383 HMI_ERROR("Parse Error!!");
384 return WMError::FAIL;
387 int len = json_object_array_length(json_cfg);
388 HMI_DEBUG("json_cfg len:%d", len);
390 for (int i = 0; i < len; i++)
392 json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
393 HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
395 this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp, i));
397 int screen = jh::getIntFromJson(json_tmp, "screen");
400 std::string layerName = jh::getStringFromJson(json_tmp, "name");
402 HMI_DEBUG("Remote Layer Name:%s Screen: %d", layerName.c_str(), screen);
403 this->wm_remoteLayerName.push_back(layerName);
407 json_object_put(json_obj);
409 return WMError::SUCCESS;
412 WMError LayerControl::loadAreasConfigFile(const std::string& path, const std::string& ecu_name)
414 // Load areas config file
415 json_object *json_obj;
416 int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
419 HMI_ERROR("Could not open %s", path.c_str());
420 return WMError::FAIL;
422 HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
425 json_object *json_cfg;
426 if (!json_object_object_get_ex(json_obj, "ecus", &json_cfg))
428 HMI_ERROR("Parse Error!!");
429 return WMError::FAIL;
432 int num_ecu = json_object_array_length(json_cfg);
433 HMI_DEBUG("json_cfg(ecus) len:%d", num_ecu);
435 const char* c_ecu_name;
436 json_object *json_ecu;
437 for (int i = 0; i < num_ecu; i++)
439 json_ecu= json_object_array_get_idx(json_cfg, i);
441 c_ecu_name = jh::getStringFromJson(json_ecu, "name");
442 if (nullptr == c_ecu_name)
444 HMI_ERROR("Parse Error!!");
445 return WMError::FAIL;
448 if (ecu_name == string(c_ecu_name))
460 HMI_ERROR("Areas for ecu:%s is NOT exist!!", ecu_name.c_str());
461 return WMError::FAIL;
465 if (!json_object_object_get_ex(json_ecu, "screens", &json_cfg))
467 HMI_ERROR("Parse Error!!");
468 return WMError::FAIL;
471 int num_screen = json_object_array_length(json_cfg);
472 HMI_DEBUG("json_cfg(screens) len:%d", num_screen);
474 json_object *json_screen;
475 for (int i = 0; i < num_screen; i++)
478 json_screen = json_object_array_get_idx(json_cfg, i);
479 HMI_INFO("json_cfg dump:%s", json_object_get_string(json_cfg));
481 // TODO: Currently only one display is connected to a ECU.
483 screen_id = jh::getIntFromJson(json_screen, "id"); // screen_id is not used currently
486 json_object *json_tmp;
487 if (!json_object_object_get_ex(json_screen, "areas", &json_tmp))
489 HMI_ERROR("Parse Error!!");
490 return WMError::FAIL;
493 int num_area = json_object_array_length(json_tmp);
494 HMI_DEBUG("json_tmp(areas) len:%d", num_area);
497 for (int j = 0; j < num_area; j++)
499 json_object *json_area = json_object_array_get_idx(json_tmp, j);
501 area = jh::getStringFromJson(json_area, "name");
504 HMI_ERROR("Parse Error!!");
505 return WMError::FAIL;
507 HMI_DEBUG("> area:%s", area);
509 json_object *json_rect;
510 if (!json_object_object_get_ex(json_area, "rect", &json_rect))
512 HMI_ERROR("Parse Error!!");
513 return WMError::FAIL;
516 struct rect area_size;
517 area_size.x = jh::getIntFromJson(json_rect, "x");
518 area_size.y = jh::getIntFromJson(json_rect, "y");
519 area_size.w = jh::getIntFromJson(json_rect, "w");
520 area_size.h = jh::getIntFromJson(json_rect, "h");
521 HMI_INFO("%d, %d, %d, %d, ", area_size.x, area_size.y, area_size.w, area_size.h);
523 this->area2size[area] = area_size;
527 for (const auto& itr : this->area2size)
529 HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",
530 itr.first.c_str(), itr.second.x, itr.second.y,
531 itr.second.w, itr.second.h);
535 // Release json_object
536 json_object_put(json_obj);
538 return WMError::SUCCESS;
541 WMError LayerControl::layoutChange(const WMAction& action)
543 if ((action.visible == TaskVisible::INVISIBLE) ||
544 (action.visible == TaskVisible::REQ_REMOTE_VISIBLE) ||
545 (action.visible == TaskVisible::REQ_REMOTE_INVISIBLE))
547 // Visibility is not change -> no redraw is required
548 return WMError::SUCCESS;
550 if(action.client == nullptr)
552 HMI_SEQ_ERROR(action.req_num, "client may vanish");
553 return WMError::NOT_REGISTERED;
555 unsigned layer = action.client->layerID();
556 unsigned surface = action.client->surfaceID();
558 auto rect = this->getAreaSize(action.area);
559 HMI_DEBUG("Set layout %d, %d, %d, %d",rect.x, rect.y, rect.w, rect.h);
562 // Sometimes, ivi_wm_surface_size signal doesn't reach window manager,
563 // then, Window Manager can't set source size.
564 // This fixes it but it takes about 200ns(on R-Car M3) wastefully
565 ilmSurfaceProperties sp;
566 ilm_getPropertiesOfSurface(surface, &sp);
567 if(sp.origSourceHeight != sp.sourceHeight) {
568 HMI_SEQ_NOTICE(action.req_num, "WORK AROUND: set source size w:%d h%d", sp.origSourceWidth, sp.origSourceHeight);
569 ilm_surfaceSetSourceRectangle(surface, 0, 0, sp.origSourceWidth, sp.origSourceHeight);
573 ilm_surfaceSetDestinationRectangle(surface, rect.x, rect.y, rect.w, rect.h);
575 for(auto &wm_layer: this->wm_layers)
577 // Store the state who is assigned to the area
578 if(wm_layer->hasLayerID(layer))
580 wm_layer->attachAppToArea(action.client->appID(), action.area);
581 /* TODO: manipulate state directly
582 LayerState ls = wm_layer->getLayerState();
583 ls.seattachAppToAreatArea(action.client->appID(), action.area);
588 return WMError::SUCCESS;
591 WMError LayerControl::visibilityChange(const WMAction& action)
593 WMError ret = WMError::FAIL;
594 if(action.client == nullptr)
596 HMI_SEQ_ERROR(action.req_num, "client may vanish");
597 return WMError::NOT_REGISTERED;
600 if (action.visible == TaskVisible::VISIBLE)
602 ret = this->makeVisible(action.client);
604 else if (action.visible == TaskVisible::INVISIBLE)
606 ret = this->makeInvisible(action.client);
608 else if (action.visible == TaskVisible::REMOTE_VISIBLE)
610 ret = this->makeVisible(action.client);
611 this->moveRemote(action.client->layerID(), action.area);
613 else if (action.visible == TaskVisible::REMOTE_INVISIBLE)
615 ret = this->makeInvisible(action.client);
616 this->moveLocal(action.client->layerID());
618 else // TaskVisible::REQ_REMOTE_VISIBLE || TaskVisible::REQ_REMOTE_INVISIBLE
620 // Visibility is not change
621 ret = WMError::SUCCESS;
627 WMError LayerControl::updateAreaList(const ChangeAreaReq& req)
630 for(const auto& elem : req.area_req)
632 if(this->area2size.find(elem.first) == this->area2size.end())
634 HMI_ERROR("requested area %s is not registered in area list", elem.first.c_str());
635 return WMError::NOT_REGISTERED;
639 for(const auto& elem : req.area_req)
641 this->area2size[elem.first] = elem.second;
645 HMI_NOTICE("Not implemented");
648 return WMError::SUCCESS;
651 WMError LayerControl::getUpdateAreaList(ChangeAreaReq *req)
653 for(const auto& wm_layer : this->wm_layers)
655 // get area name and compare it with elem
656 for(const auto& area : req->area_req)
658 string app = wm_layer->attachedApp(area.first);
661 HMI_INFO("app %s changes area %s", app.c_str(), area.first.c_str());
662 req->update_app2area[app] = area.first;
666 return WMError::SUCCESS;
669 void LayerControl::appTerminated(const shared_ptr<WMClient> client)
671 for(auto& l : this->wm_layers)
673 if(l->hasLayerID(client->layerID()))
675 l->appTerminated(client->layerID());
680 void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created)
682 if (ILM_SURFACE == object)
686 ilmSurfaceProperties sp;
688 rc = ilm_getPropertiesOfSurface(id, &sp);
689 if(rc != ILM_SUCCESS)
691 HMI_ERROR("Failed to get surface %d property due to %d", id, ilm_getError());
694 this->cb.surfaceCreated(sp.creatorPid, id);
695 ilm_surfaceSetSourceRectangle(id, 0, 0, sp.origSourceWidth, sp.origSourceHeight);
696 ilm_surfaceAddNotification(id, surfaceCallback_static);
697 ilm_surfaceSetVisibility(id, ILM_TRUE);
698 ilm_surfaceSetType(id, ILM_SURFACETYPE_DESKTOP);
702 this->cb.surfaceDestroyed(id);
705 if (ILM_LAYER == object)
709 ilm_layerAddNotification(id, layerCallback_static);
713 // Ignore here. Nothing to do currently.
714 // Process of application dead is handled by Window Manager
715 // from binder notification
720 void LayerControl::dispatchSurfacePropChangeEvent(unsigned id,
721 struct ilmSurfaceProperties* sprop,
722 t_ilm_notification_mask mask)
725 ILM_NOTIFICATION_CONTENT_AVAILABLE & ILM_NOTIFICATION_CONTENT_REMOVED
726 are not handled here, handled in create/destroy event
728 if (ILM_NOTIFICATION_VISIBILITY & mask)
730 HMI_DEBUG("surface %d turns visibility %d", id, sprop->visibility);
732 if (ILM_NOTIFICATION_OPACITY & mask)
734 HMI_DEBUG("surface %d turns opacity %f", id, sprop->opacity);
736 if (ILM_NOTIFICATION_SOURCE_RECT & mask)
738 HMI_DEBUG("surface %d source rect changes", id);
740 if (ILM_NOTIFICATION_DEST_RECT & mask)
742 HMI_DEBUG("surface %d dest rect changes", id);
744 if (ILM_NOTIFICATION_CONFIGURED & mask)
746 HMI_DEBUG("surface %d size %d, %d, %d, %d", id,
747 sprop->sourceX, sprop->sourceY, sprop->origSourceWidth, sprop->origSourceHeight);
748 ilm_surfaceSetSourceRectangle(id, 0, 0, sprop->origSourceWidth, sprop->origSourceHeight);
752 void LayerControl::dispatchLayerPropChangeEvent(unsigned id,
753 struct ilmLayerProperties* lprop,
754 t_ilm_notification_mask mask)
756 if (ILM_NOTIFICATION_VISIBILITY & mask)
758 HMI_DEBUG("layer %d turns visibility %d", id, lprop->visibility);
760 if (ILM_NOTIFICATION_OPACITY & mask)
762 HMI_DEBUG("layer %d turns opacity %f", id, lprop->opacity);
764 if (ILM_NOTIFICATION_SOURCE_RECT & mask)
766 HMI_DEBUG("layer %d source rect changes", id);
768 if (ILM_NOTIFICATION_DEST_RECT & mask)
770 HMI_DEBUG("layer %d dest rect changes", id);
774 WMError LayerControl::makeVisible(const shared_ptr<WMClient> client)
776 WMError ret = WMError::SUCCESS;
777 // Don't check here wheher client is nullptr or not
778 unsigned layer = client->layerID();
780 this->moveForeGround(client);
782 ilm_layerSetVisibility(layer, ILM_TRUE);
787 WMError LayerControl::makeInvisible(const shared_ptr<WMClient> client)
789 WMError ret = WMError::SUCCESS;
790 // Don't check here the client is not nullptr
791 unsigned layer = client->layerID();
793 bool mv_ok = this->moveBackGround(client);
797 HMI_INFO("make invisible client %s", client->appID().c_str());
798 ilm_layerSetVisibility(layer, ILM_FALSE);
804 bool LayerControl::moveBackGround(const shared_ptr<WMClient> client)
808 // Move background from foreground layer
809 auto bg = this->getWMLayer(BACK_GROUND_LAYER);
812 HMI_DEBUG("client %s role %s", client->appID().c_str(), client->role().c_str());
813 unsigned layer = client->layerID();
814 if(bg->hasRole(client->role()))
816 HMI_INFO("%s go to background", client->appID().c_str());
817 bg->addLayerToState(layer);
818 auto wm_layer = this->getWMLayer(layer);
819 wm_layer->removeLayerFromState(layer);
820 /* TODO: manipulate state directly
821 LayerState bg_ls = bg->getLayerState();
822 bg_ls.addLayer(layer);
823 LayerState ls = wm_layer->getLayerState();
824 ls.removeLayer(layer); */
833 bool LayerControl::moveForeGround(const shared_ptr<WMClient> client)
837 // Move foreground from foreground layer
838 auto bg = this->getWMLayer(BACK_GROUND_LAYER);
841 if(bg->hasRole(client->role()))
843 unsigned layer = client->layerID();
844 HMI_INFO("%s go to foreground", client->appID().c_str());
845 bg->removeLayerFromState(layer);
846 auto wm_layer = this->getWMLayer(layer);
847 wm_layer->addLayerToState(layer);
848 /* TODO: manipulate state directly
849 LayerState bg_ls = bg->getLayerState();
850 bg_ls.removeLayer(layer);
851 LayerState ls = wm_layer->getLayerState();
852 ls.addLayer(layer); */
861 bool LayerControl::moveRemote(unsigned layer, const std::string& area)
864 std::string remote_layer = this->areaToRemoteLayer(area);
865 auto remote = this->getWMLayer(remote_layer);
867 if(remote != nullptr)
870 if(remote->hasLayerID(layer))
872 HMI_DEBUG("Already moved layer %d", layer);
877 shared_ptr<WMLayer> wm_layer;
878 std::string wm_layer_name = this->hasRemoteLayer(layer);
880 if(wm_layer_name == "")
882 wm_layer = this->getWMLayer(layer);
886 wm_layer = this->getWMLayer(wm_layer_name);
889 remote->addLayerToState(layer);
890 wm_layer->removeLayerFromState(layer);
898 bool LayerControl::moveLocal(unsigned layer)
901 std::string remote_layer;
903 remote_layer = this->hasRemoteLayer(layer);
905 auto remote = this->getWMLayer(remote_layer);
906 if(remote != nullptr)
908 remote->removeLayerFromState(layer);
909 auto wm_layer = this->getWMLayer(layer);
910 wm_layer->addLayerToState(layer);
919 std::string LayerControl::hasRemoteLayer(unsigned layer)
921 for (auto itr = wm_remoteLayerName.begin(); itr != wm_remoteLayerName.end(); ++itr)
923 auto remote = this->getWMLayer(*itr);
924 if(remote != nullptr)
926 if(remote->hasLayerFromState(layer))
936 std::string LayerControl::areaToRemoteLayer(const std::string& area)
938 std::vector<std::string> elements;
940 if (area.find('.') != std::string::npos)
942 elements = parseString(area, '.');
946 elements.push_back(area);
949 for (auto itr = wm_remoteLayerName.begin(); itr != wm_remoteLayerName.end(); ++itr)
951 unsigned int idx = 0;
952 for (auto itr_elem = elements.begin(); itr_elem != elements.end(); ++itr_elem)
954 if (std::regex_search(*itr, std::regex(*itr_elem, std::regex::icase)))
956 if (++idx == elements.size())
963 // TODO: workaround, skip normal case
964 if ((itr_elem->compare("normal") == 0) || (itr_elem->compare("full") == 0))
966 if (++idx == elements.size())
979 return wm_remoteLayerName[0];