Clean: sort source code according to the order of header file
[apps/agl-service-windowmanager-2017.git] / src / window_manager.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
17 #include <fstream>
18 #include <regex>
19
20 #include "window_manager.hpp"
21 #include "../include/json.hpp"
22 #include "applist.hpp"
23
24 extern "C"
25 {
26 #include <systemd/sd-event.h>
27 }
28
29 namespace wm
30 {
31
32 static const unsigned kTimeOut = 3000000UL; /* 3s */
33
34 /* DrawingArea name used by "{layout}.{area}" */
35 const char kNameLayoutNormal[] = "normal";
36 const char kNameLayoutSplit[]  = "split";
37 const char kNameAreaFull[]     = "full";
38 const char kNameAreaMain[]     = "main";
39 const char kNameAreaSub[]      = "sub";
40
41 /* Key for json obejct */
42 const char kKeyDrawingName[] = "drawing_name";
43 const char kKeyDrawingArea[] = "drawing_area";
44 const char kKeyDrawingRect[] = "drawing_rect";
45 const char kKeyX[]           = "x";
46 const char kKeyY[]           = "y";
47 const char kKeyWidth[]       = "width";
48 const char kKeyHeight[]      = "height";
49 const char kKeyWidthPixel[]  = "width_pixel";
50 const char kKeyHeightPixel[] = "height_pixel";
51 const char kKeyWidthMm[]     = "width_mm";
52 const char kKeyHeightMm[]    = "height_mm";
53
54 static sd_event_source *g_timer_ev_src = nullptr;
55 static AppList g_app_list;
56
57 namespace
58 {
59
60 using nlohmann::json;
61
62 result<json> file_to_json(char const *filename)
63 {
64     json j;
65     std::ifstream i(filename);
66     if (i.fail())
67     {
68         HMI_DEBUG("wm", "Could not open config file, so use default layer information");
69         j = default_layers_json;
70     }
71     else
72     {
73         i >> j;
74     }
75
76     return Ok(j);
77 }
78
79 struct result<layer_map> load_layer_map(char const *filename)
80 {
81     HMI_DEBUG("wm", "loading IDs from %s", filename);
82
83     auto j = file_to_json(filename);
84     if (j.is_err())
85     {
86         return Err<layer_map>(j.unwrap_err());
87     }
88     json jids = j.unwrap();
89
90     return to_layer_map(jids);
91 }
92
93 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
94 {
95     HMI_NOTICE("wm", "Time out occurs because the client replys endDraw slow, so revert the request");
96     reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
97     return 0;
98 }
99
100 } // namespace
101
102 /**
103  * WindowManager Impl
104  */
105 WindowManager::WindowManager(wl::display *d)
106     : chooks{this},
107       display{d},
108       controller{},
109       outputs(),
110       layers(),
111       id_alloc{},
112       pending_events(false)
113 {
114     char const *path_layers_json = getenv("AFM_APP_INSTALL_DIR");
115     std::string path;
116     if (!path_layers_json)
117     {
118         HMI_ERROR("wm", "AFM_APP_INSTALL_DIR is not defined");
119         path = std::string(path_layers_json);
120     }
121     else
122     {
123         path = std::string(path_layers_json) + std::string("/etc/layers.json");
124     }
125
126     try
127     {
128         {
129             auto l = load_layer_map(path.c_str());
130             if (l.is_ok())
131             {
132                 this->layers = l.unwrap();
133             }
134             else
135             {
136                 HMI_ERROR("wm", "%s", l.err().value());
137             }
138         }
139     }
140     catch (std::exception &e)
141     {
142         HMI_ERROR("wm", "Loading of configuration failed: %s", e.what());
143     }
144 }
145
146 int WindowManager::init()
147 {
148     if (!this->display->ok())
149     {
150         return -1;
151     }
152
153     if (this->layers.mapping.empty())
154     {
155         HMI_ERROR("wm", "No surface -> layer mapping loaded");
156         return -1;
157     }
158
159     // Make afb event
160     for (int i = Event_Val_Min; i <= Event_Val_Max; i++)
161     {
162         map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i]);
163     }
164
165     this->display->add_global_handler(
166         "wl_output", [this](wl_registry *r, uint32_t name, uint32_t v) {
167             this->outputs.emplace_back(std::make_unique<wl::output>(r, name, v));
168         });
169
170     this->display->add_global_handler(
171         "ivi_wm", [this](wl_registry *r, uint32_t name, uint32_t v) {
172             this->controller =
173                 std::make_unique<struct compositor::controller>(r, name, v);
174
175             // Init controller hooks
176             this->controller->chooks = &this->chooks;
177
178             // This protocol needs the output, so lets just add our mapping here...
179             this->controller->add_proxy_to_id_mapping(
180                 this->outputs.back()->proxy.get(),
181                 wl_proxy_get_id(reinterpret_cast<struct wl_proxy *>(
182                     this->outputs.back()->proxy.get())));
183
184             // Create screen
185             this->controller->create_screen(this->outputs.back()->proxy.get());
186
187             // Set display to controller
188             this->controller->display = this->display;
189         });
190
191     // First level objects
192     this->display->roundtrip();
193     // Second level objects
194     this->display->roundtrip();
195     // Third level objects
196     this->display->roundtrip();
197
198     return init_layers();
199 }
200
201 int WindowManager::dispatch_pending_events()
202 {
203     if (this->pop_pending_events())
204     {
205         this->display->dispatch_pending();
206         return 0;
207     }
208     return -1;
209 }
210
211 void WindowManager::set_pending_events()
212 {
213     this->pending_events.store(true, std::memory_order_release);
214 }
215
216 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
217 {
218     auto lid = this->layers.get_layer_id(std::string(drawing_name));
219     if (!lid)
220     {
221         /**
222        * register drawing_name as fallback and make it displayed.
223        */
224         lid = this->layers.get_layer_id(std::string("Fallback"));
225         HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", drawing_name);
226         if (!lid)
227         {
228             return Err<int>("Drawing name does not match any role, Fallback is disabled");
229         }
230     }
231
232     auto rname = this->lookup_id(drawing_name);
233     if (!rname)
234     {
235         // name does not exist yet, allocate surface id...
236         auto id = int(this->id_alloc.generate_id(drawing_name));
237         this->layers.add_surface(id, *lid);
238
239         // set the main_surface[_name] here and now
240         if (!this->layers.main_surface_name.empty() &&
241             this->layers.main_surface_name == drawing_name)
242         {
243             this->layers.main_surface = id;
244             HMI_DEBUG("wm", "Set main_surface id to %u", id);
245         }
246
247         // add client into the db
248         std::string appid_str(appid);
249         std::string role(drawing_name);
250         g_app_list.addClient(appid_str, *lid, id, role);
251
252         return Ok<int>(id);
253     }
254
255     // Check currently registered drawing names if it is already there.
256     return Err<int>("Surface already present");
257 }
258
259 char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
260                                      char const *ivi_id)
261 {
262     ST();
263
264     auto lid = this->layers.get_layer_id(std::string(drawing_name));
265     unsigned sid = std::stol(ivi_id);
266
267     if (!lid)
268     {
269         /**
270        * register drawing_name as fallback and make it displayed.
271        */
272         lid = this->layers.get_layer_id(std::string("Fallback"));
273         HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", drawing_name);
274         if (!lid)
275         {
276             return "Drawing name does not match any role, Fallback is disabled";
277         }
278     }
279
280     auto rname = this->lookup_id(drawing_name);
281
282     if (rname)
283     {
284         return "Surface already present";
285     }
286
287     // register pair drawing_name and ivi_id
288     this->id_alloc.register_name_id(drawing_name, sid);
289     this->layers.add_surface(sid, *lid);
290
291     // this surface is already created
292     HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", sid, *lid);
293
294     this->controller->layers[*lid]->add_surface(sid);
295     this->layout_commit();
296
297     // add client into the db
298     std::string appid_str(appid);
299     std::string role(drawing_name);
300     g_app_list.addClient(appid_str, *lid, sid, role);
301
302     return nullptr;
303 }
304
305 void WindowManager::api_activate_surface(char const *appid, char const *drawing_name,
306                                char const *drawing_area, const reply_func &reply)
307 {
308     ST();
309
310     std::string id = appid;
311     std::string role = drawing_name;
312     std::string area = drawing_area;
313     Task task = Task::TASK_ALLOCATE;
314     unsigned req_num = 0;
315     WMError ret = WMError::UNKNOWN;
316
317     ret = this->setRequest(id, role, area, task, &req_num);
318
319     if(ret != WMError::SUCCESS)
320     {
321         HMI_ERROR("wm", errorDescription(ret));
322         reply("Failed to set request");
323         return;
324     }
325
326     reply(nullptr);
327     if (req_num != g_app_list.currentRequestNumber())
328     {
329         // Add request, then invoked after the previous task is finished
330         HMI_SEQ_DEBUG(req_num, "request is accepted");
331         return;
332     }
333
334     /*
335      * Do allocate tasks
336      */
337     ret = this->doTransition(req_num);
338
339     if (ret != WMError::SUCCESS)
340     {
341         //this->emit_error()
342         HMI_SEQ_ERROR(req_num, errorDescription(ret));
343         g_app_list.removeRequest(req_num);
344         this->processNextRequest();
345     }
346 }
347
348 void WindowManager::api_deactivate_surface(char const *appid, char const *drawing_name,
349                                  const reply_func &reply)
350 {
351     ST();
352
353     /*
354     * Check Phase
355     */
356     std::string id = appid;
357     std::string role = drawing_name;
358     std::string area = ""; //drawing_area;
359     Task task = Task::TASK_RELEASE;
360     unsigned req_num = 0;
361     WMError ret = WMError::UNKNOWN;
362
363     ret = this->setRequest(id, role, area, task, &req_num);
364
365     if (ret != WMError::SUCCESS)
366     {
367         HMI_ERROR("wm", errorDescription(ret));
368         reply("Failed to set request");
369         return;
370     }
371
372     reply(nullptr);
373     if (req_num != g_app_list.currentRequestNumber())
374     {
375         // Add request, then invoked after the previous task is finished
376         HMI_SEQ_DEBUG(req_num, "request is accepted");
377         return;
378     }
379
380     /*
381     * Do allocate tasks
382     */
383     ret = this->doTransition(req_num);
384
385     if (ret != WMError::SUCCESS)
386     {
387         //this->emit_error()
388         HMI_SEQ_ERROR(req_num, errorDescription(ret));
389         g_app_list.removeRequest(req_num);
390         this->processNextRequest();
391     }
392 }
393
394 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
395 {
396     std::string id = appid;
397     std::string role = drawing_name;
398     unsigned current_req = g_app_list.currentRequestNumber();
399     bool result = g_app_list.setEndDrawFinished(current_req, id, role);
400
401     if (!result)
402     {
403         HMI_ERROR("wm", "%s is not in transition state", id.c_str());
404         return;
405     }
406
407     if (g_app_list.endDrawFullfilled(current_req))
408     {
409         // do task for endDraw
410         this->stopTimer();
411         WMError ret = this->doEndDraw(current_req);
412
413         if(ret != WMError::SUCCESS)
414         {
415             //this->emit_error();
416         }
417         HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
418
419         g_app_list.removeRequest(current_req);
420
421         this->processNextRequest();
422     }
423     else
424     {
425         HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
426         return;
427     }
428 }
429
430 result<json_object *> WindowManager::api_get_display_info()
431 {
432     // Check controller
433     if (!this->controller)
434     {
435         return Err<json_object *>("ivi_controller global not available");
436     }
437
438     // Set display info
439     compositor::size o_size = this->controller->output_size;
440     compositor::size p_size = this->controller->physical_size;
441
442     json_object *object = json_object_new_object();
443     json_object_object_add(object, kKeyWidthPixel, json_object_new_int(o_size.w));
444     json_object_object_add(object, kKeyHeightPixel, json_object_new_int(o_size.h));
445     json_object_object_add(object, kKeyWidthMm, json_object_new_int(p_size.w));
446     json_object_object_add(object, kKeyHeightMm, json_object_new_int(p_size.h));
447
448     return Ok<json_object *>(object);
449 }
450
451 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
452 {
453     HMI_DEBUG("wm", "called");
454
455     // Check drawing name, surface/layer id
456     auto const &surface_id = this->lookup_id(drawing_name);
457     if (!surface_id)
458     {
459         return Err<json_object *>("Surface does not exist");
460     }
461
462     if (!this->controller->surface_exists(*surface_id))
463     {
464         return Err<json_object *>("Surface does not exist in controller!");
465     }
466
467     auto layer_id = this->layers.get_layer_id(*surface_id);
468     if (!layer_id)
469     {
470         return Err<json_object *>("Surface is not on any layer!");
471     }
472
473     auto o_state = *this->layers.get_layout_state(*surface_id);
474     if (o_state == nullptr)
475     {
476         return Err<json_object *>("Could not find layer for surface");
477     }
478
479     struct LayoutState &state = *o_state;
480     if ((state.main != *surface_id) && (state.sub != *surface_id))
481     {
482         return Err<json_object *>("Surface is inactive");
483     }
484
485     // Set area rectangle
486     compositor::rect area_info = this->area_info[*surface_id];
487     json_object *object = json_object_new_object();
488     json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
489     json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
490     json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
491     json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
492
493     return Ok<json_object *>(object);
494 }
495
496 void WindowManager::api_ping() { this->dispatch_pending_events(); }
497
498 void WindowManager::send_event(char const *evname, char const *label)
499 {
500     HMI_DEBUG("wm", "%s: %s(%s)", __func__, evname, label);
501
502     json_object *j = json_object_new_object();
503     json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
504
505     int ret = afb_event_push(this->map_afb_event[evname], j);
506     if (ret != 0)
507     {
508         HMI_DEBUG("wm", "afb_event_push failed: %m");
509     }
510 }
511
512 void WindowManager::send_event(char const *evname, char const *label, char const *area,
513                      int x, int y, int w, int h)
514 {
515     HMI_DEBUG("wm", "%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
516               __func__, evname, label, area, x, y, w, h);
517
518     json_object *j_rect = json_object_new_object();
519     json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
520     json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
521     json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
522     json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
523
524     json_object *j = json_object_new_object();
525     json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
526     json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area));
527     json_object_object_add(j, kKeyDrawingRect, j_rect);
528
529     int ret = afb_event_push(this->map_afb_event[evname], j);
530     if (ret != 0)
531     {
532         HMI_DEBUG("wm", "afb_event_push failed: %m");
533     }
534 }
535
536 /**
537  * proxied events
538  */
539 void WindowManager::surface_created(uint32_t surface_id)
540 {
541     auto layer_id = this->layers.get_layer_id(surface_id);
542     if (!layer_id)
543     {
544         HMI_DEBUG("wm", "Newly created surfce %d is not associated with any layer!",
545                   surface_id);
546         return;
547     }
548
549     HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", surface_id, *layer_id);
550
551     this->controller->layers[*layer_id]->add_surface(surface_id);
552     this->layout_commit();
553 }
554
555 void WindowManager::surface_removed(uint32_t surface_id)
556 {
557     HMI_DEBUG("wm", "surface_id is %u", surface_id);
558     g_app_list.removeSurface(surface_id);
559 }
560
561 void WindowManager::removeClient(const std::string &appid)
562 {
563     HMI_DEBUG("wm", "Remove clinet %s from list", appid.c_str());
564     g_app_list.removeClient(appid);
565 }
566
567 void WindowManager::exceptionProcessForTransition()
568 {
569     unsigned req_num = g_app_list.currentRequestNumber();
570     HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
571     g_app_list.removeRequest(req_num);
572     HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
573     this->processNextRequest();
574 }
575
576 void WindowManager::timerHandler()
577 {
578     unsigned req_num = g_app_list.currentRequestNumber();
579     HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
580     g_app_list.reqDump();
581     g_app_list.removeRequest(req_num);
582     this->processNextRequest();
583 }
584
585 /*
586  ******* Private Functions *******
587  */
588
589 bool WindowManager::pop_pending_events()
590 {
591     bool x{true};
592     return this->pending_events.compare_exchange_strong(
593         x, false, std::memory_order_consume);
594 }
595
596 optional<int> WindowManager::lookup_id(char const *name)
597 {
598     return this->id_alloc.lookup(std::string(name));
599 }
600 optional<std::string> WindowManager::lookup_name(int id)
601 {
602     return this->id_alloc.lookup(id);
603 }
604
605 /**
606  * init_layers()
607  */
608 int WindowManager::init_layers()
609 {
610     if (!this->controller)
611     {
612         HMI_ERROR("wm", "ivi_controller global not available");
613         return -1;
614     }
615
616     if (this->outputs.empty())
617     {
618         HMI_ERROR("wm", "no output was set up!");
619         return -1;
620     }
621
622     auto &c = this->controller;
623
624     auto &o = this->outputs.front();
625     auto &s = c->screens.begin()->second;
626     auto &layers = c->layers;
627
628     // Write output dimensions to ivi controller...
629     c->output_size = compositor::size{uint32_t(o->width), uint32_t(o->height)};
630     c->physical_size = compositor::size{uint32_t(o->physical_width),
631                                         uint32_t(o->physical_height)};
632
633     // Clear scene
634     layers.clear();
635
636     // Clear screen
637     s->clear();
638
639     // Quick and dirty setup of layers
640     for (auto const &i : this->layers.mapping)
641     {
642         c->layer_create(i.second.layer_id, o->width, o->height);
643         auto &l = layers[i.second.layer_id];
644         l->set_destination_rectangle(0, 0, o->width, o->height);
645         l->set_visibility(1);
646         HMI_DEBUG("wm", "Setting up layer %s (%d) for surface role match \"%s\"",
647                   i.second.name.c_str(), i.second.layer_id, i.second.role.c_str());
648     }
649
650     // Add layers to screen
651     s->set_render_order(this->layers.layers);
652
653     this->layout_commit();
654
655     this->layers.setupArea(o->width, o->height);
656
657     return 0;
658 }
659
660 void WindowManager::surface_set_layout(int surface_id, const std::string& area)
661 {
662     if (!this->controller->surface_exists(surface_id))
663     {
664         HMI_ERROR("wm", "Surface %d does not exist", surface_id);
665         return;
666     }
667
668     auto o_layer_id = this->layers.get_layer_id(surface_id);
669
670     if (!o_layer_id)
671     {
672         HMI_ERROR("wm", "Surface %d is not associated with any layer!", surface_id);
673         return;
674     }
675
676     uint32_t layer_id = *o_layer_id;
677
678     auto const &layer = this->layers.get_layer(layer_id);
679     auto rect = this->layers.getAreaSize(area);
680     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "%s : x:%d y:%d w:%d h:%d", area.c_str(),
681                     rect.x, rect.y, rect.w, rect.h);
682     auto &s = this->controller->surfaces[surface_id];
683
684     int x = rect.x;
685     int y = rect.y;
686     int w = rect.w;
687     int h = rect.h;
688
689     // less-than-0 values refer to MAX + 1 - $VALUE
690     // e.g. MAX is either screen width or height
691     if (w < 0)
692     {
693         w = this->controller->output_size.w + 1 + w;
694     }
695     if (h < 0)
696     {
697         h = this->controller->output_size.h + 1 + h;
698     }
699
700     HMI_DEBUG("wm", "surface_set_layout for surface %u on layer %u", surface_id,
701               layer_id);
702
703     // set destination to the display rectangle
704     s->set_destination_rectangle(x, y, w, h);
705
706     // update area information
707     this->area_info[surface_id].x = x;
708     this->area_info[surface_id].y = y;
709     this->area_info[surface_id].w = w;
710     this->area_info[surface_id].h = h;
711
712     HMI_DEBUG("wm", "Surface %u now on layer %u with rect { %d, %d, %d, %d }",
713               surface_id, layer_id, x, y, w, h);
714 }
715
716 void WindowManager::layout_commit()
717 {
718     this->controller->commit_changes();
719     this->display->flush();
720 }
721
722 void WindowManager::emit_activated(char const *label)
723 {
724     this->send_event(kListEventName[Event_Active], label);
725 }
726
727 void WindowManager::emit_deactivated(char const *label)
728 {
729     this->send_event(kListEventName[Event_Inactive], label);
730 }
731
732 void WindowManager::emit_syncdraw(char const *label, char const *area, int x, int y, int w, int h)
733 {
734     this->send_event(kListEventName[Event_SyncDraw], label, area, x, y, w, h);
735 }
736
737 void WindowManager::emit_syncdraw(const std::string &role, const std::string &area)
738 {
739     compositor::rect rect = this->layers.getAreaSize(area);
740     this->send_event(kListEventName[Event_SyncDraw],
741         role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
742 }
743
744 void WindowManager::emit_flushdraw(char const *label)
745 {
746     this->send_event(kListEventName[Event_FlushDraw], label);
747 }
748
749 void WindowManager::emit_visible(char const *label, bool is_visible)
750 {
751     this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], label);
752 }
753
754 void WindowManager::emit_invisible(char const *label)
755 {
756     return emit_visible(label, false);
757 }
758
759 void WindowManager::emit_visible(char const *label) { return emit_visible(label, true); }
760
761 void WindowManager::activate(int id)
762 {
763     auto ip = this->controller->sprops.find(id);
764     if (ip != this->controller->sprops.end())
765     {
766         this->controller->surfaces[id]->set_visibility(1);
767         char const *label =
768             this->lookup_name(id).value_or("unknown-name").c_str();
769
770          // FOR CES DEMO >>>
771         if ((0 == strcmp(label, "Radio"))       ||
772             (0 == strcmp(label, "MediaPlayer")) ||
773             (0 == strcmp(label, "Music"))       ||
774             (0 == strcmp(label, "Navigation")))
775         {
776             for (auto i = surface_bg.begin(); i != surface_bg.end(); ++i)
777             {
778                 if (id == *i)
779                 {
780                     // Remove id
781                     this->surface_bg.erase(i);
782
783                     // Remove from BG layer (999)
784                     HMI_DEBUG("wm", "Remove %s(%d) from BG layer", label, id);
785                     this->controller->layers[999]->remove_surface(id);
786
787                     // Add to FG layer (1001)
788                     HMI_DEBUG("wm", "Add %s(%d) to FG layer", label, id);
789                     this->controller->layers[1001]->add_surface(id);
790
791                     for (int j : this->surface_bg)
792                     {
793                         HMI_DEBUG("wm", "Stored id:%d", j);
794                     }
795                     break;
796                 }
797             }
798         }
799         // <<< FOR CES DEMO
800         this->layout_commit();
801
802         this->emit_visible(label);
803         this->emit_activated(label);
804     }
805 }
806
807 void WindowManager::deactivate(int id)
808 {
809     auto ip = this->controller->sprops.find(id);
810     if (ip != this->controller->sprops.end())
811     {
812         char const *label =
813             this->lookup_name(id).value_or("unknown-name").c_str();
814
815         // FOR CES DEMO >>>
816         if ((0 == strcmp(label, "Radio"))       ||
817             (0 == strcmp(label, "MediaPlayer")) ||
818             (0 == strcmp(label, "Music"))       ||
819             (0 == strcmp(label, "Navigation")))
820         {
821
822             // Store id
823             this->surface_bg.push_back(id);
824
825             // Remove from FG layer (1001)
826             HMI_DEBUG("wm", "Remove %s(%d) from FG layer", label, id);
827             this->controller->layers[1001]->remove_surface(id);
828
829             // Add to BG layer (999)
830             HMI_DEBUG("wm", "Add %s(%d) to BG layer", label, id);
831             this->controller->layers[999]->add_surface(id);
832
833             for (int j : surface_bg)
834             {
835                 HMI_DEBUG("wm", "Stored id:%d", j);
836             }
837         }
838         else
839         {
840             this->controller->surfaces[id]->set_visibility(0);
841         }
842         // <<< FOR CES DEMO
843
844         this->emit_deactivated(label);
845         this->emit_invisible(label);
846     }
847 }
848
849 WMError WindowManager::setRequest(const std::string& appid, const std::string &role, const std::string &area,
850                             Task task, unsigned* req_num)
851 {
852     if (!g_app_list.contains(appid))
853     {
854         return WMError::NOT_REGISTERED;
855     }
856
857     auto client = g_app_list.lookUpClient(appid);
858
859     /*
860      * Queueing Phase
861      */
862     unsigned current = g_app_list.currentRequestNumber();
863     unsigned requested_num = g_app_list.getRequestNumber(appid);
864     if (requested_num != 0)
865     {
866         HMI_SEQ_INFO(requested_num,
867             "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
868         return REQ_REJECTED;
869     }
870
871     WMRequest req = WMRequest(appid, role, area, task);
872     unsigned new_req = g_app_list.addRequest(req);
873     *req_num = new_req;
874     g_app_list.reqDump();
875
876     HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
877
878     return WMError::SUCCESS;
879 }
880
881 WMError WindowManager::doTransition(unsigned req_num)
882 {
883     HMI_SEQ_DEBUG(req_num, "check policy");
884     WMError ret = this->checkPolicy(req_num);
885     if (ret != WMError::SUCCESS)
886     {
887         return ret;
888     }
889     HMI_SEQ_DEBUG(req_num, "Start transition.");
890     ret = this->startTransition(req_num);
891     return ret;
892 }
893
894 WMError WindowManager::checkPolicy(unsigned req_num)
895 {
896     /*
897     * Check Policy
898     */
899     // get current trigger
900     bool found = false;
901     bool split = false;
902     WMError ret = WMError::LAYOUT_CHANGE_FAIL;
903     auto trigger = g_app_list.getRequest(req_num, &found);
904     if (!found)
905     {
906         ret = WMError::NO_ENTRY;
907         return ret;
908     }
909     std::string req_area = trigger.area;
910
911     // >>>> Compatible with current window manager until policy manager coming
912     if (trigger.task == Task::TASK_ALLOCATE)
913     {
914         HMI_SEQ_DEBUG(req_num, "Check split or not");
915         const char *msg = this->check_surface_exist(trigger.role.c_str());
916
917         if (msg)
918         {
919             HMI_SEQ_ERROR(req_num, msg);
920             ret = WMError::LAYOUT_CHANGE_FAIL;
921             return ret;
922         }
923
924         auto const &surface_id = this->lookup_id(trigger.role.c_str());
925         auto o_state = *this->layers.get_layout_state(*surface_id);
926         struct LayoutState &state = *o_state;
927
928         unsigned curernt_sid = state.main;
929         split = this->can_split(state, *surface_id);
930
931         if (split)
932         {
933             HMI_SEQ_DEBUG(req_num, "Split happens");
934             // Get current visible role
935             std::string add_role = this->lookup_name(state.main).value();
936             // Set next area
937             std::string add_area = std::string(kNameLayoutSplit) + "." + std::string(kNameAreaMain);
938             // Change request area
939             req_area = std::string(kNameLayoutSplit) + "." + std::string(kNameAreaSub);
940             HMI_SEQ_NOTICE(req_num, "Change request area from %s to %s, because split happens",
941                                 trigger.area.c_str(), req_area.c_str());
942             // set another action
943             std::string add_name = g_app_list.getAppID(curernt_sid, add_role, &found);
944             if (!found)
945             {
946                 HMI_SEQ_ERROR(req_num, "Couldn't widhdraw with surfaceID : %d", curernt_sid);
947                 ret = WMError::NOT_REGISTERED;
948                 return ret;
949             }
950             HMI_SEQ_INFO(req_num, "Additional split app %s, role: %s, area: %s",
951                          add_name.c_str(), add_role.c_str(), add_area.c_str());
952             // Set split action
953             bool end_draw_finished = false;
954             WMAction split_action{
955                 add_name,
956                 add_role,
957                 add_area,
958                 TaskVisible::VISIBLE,
959                 end_draw_finished};
960             WMError ret = g_app_list.setAction(req_num, split_action);
961             if (ret != WMError::SUCCESS)
962             {
963                 HMI_SEQ_ERROR(req_num, "Failed to set action");
964                 return ret;
965             }
966             g_app_list.reqDump();
967         }
968     }
969     else
970     {
971         HMI_SEQ_DEBUG(req_num, "split doesn't happen");
972     }
973
974     // Set invisible task(Remove if policy manager finish)
975     ret = this->setInvisibleTask(trigger.role, split);
976     if(ret != WMError::SUCCESS)
977     {
978         HMI_SEQ_ERROR(req_num, "Failed to set invisible task: %s", errorDescription(ret));
979         return ret;
980     }
981
982     /*  get new status from Policy Manager */
983     HMI_SEQ_NOTICE(req_num, "ATM, Policy manager does't exist, then set WMAction as is");
984     if(trigger.role == "HomeScreen")
985     {
986         // TODO : Remove when Policy Manager completed
987         HMI_SEQ_NOTICE(req_num, "Hack. This process will be removed. Change HomeScreen code!!");
988         req_area = "fullscreen";
989     }
990     TaskVisible task_visible =
991         (trigger.task == Task::TASK_ALLOCATE) ? TaskVisible::VISIBLE : TaskVisible::INVISIBLE;
992
993     ret = g_app_list.setAction(req_num, trigger.appid, trigger.role, req_area, task_visible);
994     g_app_list.reqDump();
995
996     return ret;
997 }
998
999 WMError WindowManager::startTransition(unsigned req_num)
1000 {
1001     bool sync_draw_happen = false;
1002     bool found = false;
1003     WMError ret = WMError::SUCCESS;
1004     auto actions = g_app_list.getActions(req_num, &found);
1005     if (!found)
1006     {
1007         ret = WMError::NO_ENTRY;
1008         HMI_SEQ_ERROR(req_num,
1009             "Window Manager bug :%s : Action is not set", errorDescription(ret));
1010         return ret;
1011     }
1012
1013     for (const auto &action : actions)
1014     {
1015         if (action.visible != TaskVisible::INVISIBLE)
1016         {
1017             sync_draw_happen = true;
1018             this->emit_syncdraw(action.role, action.area);
1019             /* TODO: emit event for app not subscriber
1020             if(g_app_list.contains(y.appid))
1021                 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
1022         }
1023     }
1024
1025     if (sync_draw_happen)
1026     {
1027         this->setTimer();
1028     }
1029     else
1030     {
1031         // deactivate only, no syncDraw
1032         // Make it deactivate here
1033         for (const auto &x : actions)
1034         {
1035             if (g_app_list.contains(x.appid))
1036             {
1037                 auto client = g_app_list.lookUpClient(x.appid);
1038                 this->deactivate(client->surfaceID(x.role));
1039             }
1040         }
1041         ret = NO_LAYOUT_CHANGE;
1042     }
1043     return ret;
1044 }
1045
1046 WMError WindowManager::setInvisibleTask(const std::string &role, bool split)
1047 {
1048     unsigned req_num = g_app_list.currentRequestNumber();
1049     HMI_SEQ_DEBUG(req_num, "set current visible app to invisible task");
1050     // This task is copied from original actiavete surface
1051     const char *drawing_name = role.c_str();
1052     auto const &surface_id = this->lookup_id(drawing_name);
1053     auto layer_id = this->layers.get_layer_id(*surface_id);
1054     auto o_state = *this->layers.get_layout_state(*surface_id);
1055     struct LayoutState &state = *o_state;
1056     std::string add_name, add_role;
1057     std::string add_area = "";
1058     int surface;
1059     TaskVisible task_visible = TaskVisible::INVISIBLE;
1060     bool end_draw_finished = true;
1061     bool found = false;
1062
1063     for (auto const &l : this->layers.mapping)
1064     {
1065         if (l.second.layer_id <= *layer_id)
1066         {
1067             continue;
1068         }
1069         HMI_DEBUG("wm", "debug: main %d , sub : %d", l.second.state.main, l.second.state.sub);
1070         if (l.second.state.main != -1)
1071         {
1072             //this->deactivate(l.second.state.main);
1073             surface = l.second.state.main;
1074             add_role = *this->id_alloc.lookup(surface);
1075             add_name = g_app_list.getAppID(surface, add_role, &found);
1076             if(!found){
1077                 return WMError::NOT_REGISTERED;
1078             }
1079             HMI_SEQ_INFO(req_num, "Invisible %s", add_name.c_str());
1080             WMAction act{add_name, add_role, add_area, task_visible, end_draw_finished};
1081             g_app_list.setAction(req_num, act);
1082             l.second.state.main = -1;
1083         }
1084
1085         if (l.second.state.sub != -1)
1086         {
1087             //this->deactivate(l.second.state.sub);
1088             surface = l.second.state.sub;
1089             add_role = *this->id_alloc.lookup(surface);
1090             add_name = g_app_list.getAppID(surface, add_role, &found);
1091             if (!found)
1092             {
1093                 return WMError::NOT_REGISTERED;
1094             }
1095             HMI_SEQ_INFO(req_num, "Invisible %s", add_name.c_str());
1096             WMAction act{add_name, add_role, add_area, task_visible, end_draw_finished};
1097             g_app_list.setAction(req_num, act);
1098             l.second.state.sub = -1;
1099         }
1100     }
1101
1102     // change current state here, but this is hack
1103     auto layer = this->layers.get_layer(*layer_id);
1104
1105     if (state.main == -1)
1106     {
1107         HMI_DEBUG("wm", "Layout: %s", kNameLayoutNormal);
1108     }
1109     else
1110     {
1111         if (0 != strcmp(drawing_name, "HomeScreen"))
1112         {
1113             if (split)
1114             {
1115                 if (state.sub != *surface_id)
1116                 {
1117                     if (state.sub != -1)
1118                     {
1119                         //this->deactivate(state.sub);
1120                         WMAction deact_sub;
1121                         deact_sub.role =
1122                             std::move(*this->id_alloc.lookup(state.sub));
1123                         deact_sub.area = add_area;
1124                         deact_sub.appid = g_app_list.getAppID(state.sub, deact_sub.role, &found);
1125                         if (!found)
1126                         {
1127                             HMI_SEQ_ERROR(req_num, "App doesn't exist for role : %s",
1128                                             deact_sub.role.c_str());
1129                             return WMError::NOT_REGISTERED;
1130                         }
1131                         deact_sub.visible = task_visible;
1132                         deact_sub.end_draw_finished = end_draw_finished;
1133                         HMI_SEQ_DEBUG(req_num, "Set invisible task for %s", deact_sub.appid.c_str());
1134                         g_app_list.setAction(req_num, deact_sub);
1135                     }
1136                 }
1137                 //state = LayoutState{state.main, *surface_id};
1138             }
1139             else
1140             {
1141                 HMI_DEBUG("wm", "Layout: %s", kNameLayoutNormal);
1142
1143                 //this->surface_set_layout(*surface_id);
1144                 if (state.main != *surface_id)
1145                 {
1146                     // this->deactivate(state.main);
1147                     WMAction deact_main;
1148                     deact_main.role = std::move(*this->id_alloc.lookup(state.main));
1149                     ;
1150                     deact_main.area = add_area;
1151                     deact_main.appid = g_app_list.getAppID(state.main, deact_main.role, &found);
1152                     if (!found)
1153                     {
1154                         HMI_SEQ_DEBUG(req_num, "sub surface ddoesn't exist");
1155                         return WMError::NOT_REGISTERED;
1156                     }
1157                     deact_main.visible = task_visible;
1158                     deact_main.end_draw_finished = end_draw_finished;
1159                     HMI_SEQ_DEBUG(req_num, "sub surface doesn't exist");
1160                     g_app_list.setAction(req_num, deact_main);
1161                 }
1162                 if (state.sub != -1)
1163                 {
1164                     if (state.sub != *surface_id)
1165                     {
1166                         //this->deactivate(state.sub);
1167                         WMAction deact_sub;
1168                         deact_sub.role = std::move(*this->id_alloc.lookup(state.sub));
1169                         ;
1170                         deact_sub.area = add_area;
1171                         deact_sub.appid = g_app_list.getAppID(state.sub, deact_sub.role, &found);
1172                         if (!found)
1173                         {
1174                             HMI_SEQ_DEBUG(req_num, "sub surface ddoesn't exist");
1175                             return WMError::NOT_REGISTERED;
1176                         }
1177                         deact_sub.visible = task_visible;
1178                         deact_sub.end_draw_finished = end_draw_finished;
1179                         HMI_SEQ_DEBUG(req_num, "sub surface doesn't exist");
1180                         g_app_list.setAction(req_num, deact_sub);
1181                     }
1182                 }
1183                 //state = LayoutState{*surface_id};
1184             }
1185         }
1186     }
1187     return WMError::SUCCESS;
1188 }
1189
1190 WMError WindowManager::doEndDraw(unsigned req_num)
1191 {
1192     // get actions
1193     bool found;
1194     auto actions = g_app_list.getActions(req_num, &found);
1195     WMError ret = WMError::SUCCESS;
1196     if (!found)
1197     {
1198         ret = WMError::NO_ENTRY;
1199         return ret;
1200     }
1201
1202     HMI_SEQ_INFO(req_num, "do endDraw");
1203
1204     // layout change and make it visible
1205     for (const auto &act : actions)
1206     {
1207         // layout change
1208         if(!g_app_list.contains(act.appid)){
1209             ret = WMError::NOT_REGISTERED;
1210         }
1211         ret = this->layoutChange(act);
1212         if(ret != WMError::SUCCESS)
1213         {
1214             HMI_SEQ_WARNING(req_num,
1215                 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
1216             return ret;
1217         }
1218         ret = this->visibilityChange(act);
1219         if (ret != WMError::SUCCESS)
1220         {
1221             HMI_SEQ_WARNING(req_num,
1222                 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
1223             return ret;
1224         }
1225         HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
1226         //this->lm_enddraw(act.role.c_str());
1227     }
1228
1229     // Change current state
1230     this->changeCurrentState(req_num);
1231
1232     HMI_SEQ_INFO(req_num, "emit flushDraw");
1233
1234     for(const auto &act_flush : actions)
1235     {
1236         if(act_flush.visible != TaskVisible::INVISIBLE)
1237         {
1238             this->emit_flushdraw(act_flush.role.c_str());
1239         }
1240     }
1241
1242     return ret;
1243 }
1244
1245 WMError WindowManager::layoutChange(const WMAction &action)
1246 {
1247     if (action.visible == TaskVisible::INVISIBLE)
1248     {
1249         // Visibility is not change -> no redraw is required
1250         return WMError::SUCCESS;
1251     }
1252     auto client = g_app_list.lookUpClient(action.appid);
1253     unsigned surface = client->surfaceID(action.role);
1254     if (surface == 0)
1255     {
1256         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
1257                       "client doesn't have surface with role(%s)", action.role.c_str());
1258         return WMError::NOT_REGISTERED;
1259     }
1260     // Layout Manager
1261     WMError ret = this->setSurfaceSize(surface, action.area);
1262     return ret;
1263 }
1264
1265 WMError WindowManager::visibilityChange(const WMAction &action)
1266 {
1267     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Change visibility");
1268     if(!g_app_list.contains(action.appid)){
1269         return WMError::NOT_REGISTERED;
1270     }
1271     auto client = g_app_list.lookUpClient(action.appid);
1272     unsigned surface = client->surfaceID(action.role);
1273     if(surface == 0)
1274     {
1275         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
1276                       "client doesn't have surface with role(%s)", action.role.c_str());
1277         return WMError::NOT_REGISTERED;
1278     }
1279
1280     if (action.visible != TaskVisible::INVISIBLE)
1281     {
1282         this->activate(surface); // Layout Manager task
1283     }
1284     else
1285     {
1286         this->deactivate(surface); // Layout Manager task
1287     }
1288     return WMError::SUCCESS;
1289 }
1290
1291 WMError WindowManager::setSurfaceSize(unsigned surface, const std::string &area)
1292 {
1293     this->surface_set_layout(surface, area);
1294
1295     return WMError::SUCCESS;
1296 }
1297
1298 WMError WindowManager::changeCurrentState(unsigned req_num)
1299 {
1300     HMI_SEQ_DEBUG(req_num, "Change current layout state");
1301     bool trigger_found = false, action_found = false;
1302     auto trigger = g_app_list.getRequest(req_num, &trigger_found);
1303     auto actions = g_app_list.getActions(req_num, &action_found);
1304     if (!trigger_found || !action_found)
1305     {
1306         HMI_SEQ_ERROR(req_num, "Action not found");
1307         return WMError::LAYOUT_CHANGE_FAIL;
1308     }
1309
1310     // Layout state reset
1311     struct LayoutState reset_state{-1, -1};
1312     HMI_SEQ_DEBUG(req_num,"Reset layout state");
1313     for (const auto &action : actions)
1314     {
1315         if(!g_app_list.contains(action.appid)){
1316             return WMError::NOT_REGISTERED;
1317         }
1318         auto client = g_app_list.lookUpClient(action.appid);
1319         auto pCurState = *this->layers.get_layout_state((int)client->surfaceID(action.role));
1320         if(pCurState == nullptr)
1321         {
1322             HMI_SEQ_ERROR(req_num, "Counldn't find current status");
1323             continue;
1324         }
1325         pCurState->main = reset_state.main;
1326         pCurState->sub = reset_state.sub;
1327     }
1328
1329     HMI_SEQ_DEBUG(req_num, "Change state");
1330     for (const auto &action : actions)
1331     {
1332         auto client = g_app_list.lookUpClient(action.appid);
1333         auto pLayerCurState = *this->layers.get_layout_state((int)client->surfaceID(action.role));
1334         if (pLayerCurState == nullptr)
1335         {
1336             HMI_SEQ_ERROR(req_num, "Counldn't find current status");
1337             continue;
1338         }
1339         int surface = -1;
1340
1341         if (action.visible != TaskVisible::INVISIBLE)
1342         {
1343             surface = (int)client->surfaceID(action.role);
1344             HMI_SEQ_INFO(req_num, "Change %s surface : %d, state visible area : %s",
1345                             action.role.c_str(), surface, action.area.c_str());
1346             // visible == true -> layout changes
1347             if(action.area == "normal.full" || action.area == "split.main")
1348             {
1349                 pLayerCurState->main = surface;
1350             }
1351             else if (action.area == "split.sub")
1352             {
1353                 pLayerCurState->sub = surface;
1354             }
1355             else
1356             {
1357                 // normalfull
1358                 pLayerCurState->main = surface;
1359             }
1360         }
1361     }
1362
1363     return WMError::SUCCESS;
1364 }
1365
1366 void WindowManager::setTimer()
1367 {
1368     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
1369     if (g_timer_ev_src == nullptr)
1370     {
1371         // firsttime set into sd_event
1372         int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
1373             CLOCK_REALTIME, time(NULL) * (1000000UL) + kTimeOut, 1, processTimerHandler, this);
1374         if (ret < 0)
1375         {
1376             HMI_ERROR("wm", "Could't set timer");
1377         }
1378     }
1379     else
1380     {
1381         // update timer limitation after second time
1382         sd_event_source_set_time(g_timer_ev_src, time(NULL) * (1000000UL) + kTimeOut);
1383         sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
1384     }
1385 }
1386
1387 void WindowManager::stopTimer()
1388 {
1389     unsigned req_num = g_app_list.currentRequestNumber();
1390     HMI_SEQ_DEBUG(req_num, "Timer stop");
1391     int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
1392     if (rc < 0)
1393     {
1394         HMI_SEQ_ERROR(req_num, "Timer stop failed");
1395     }
1396 }
1397
1398 void WindowManager::processNextRequest()
1399 {
1400     g_app_list.next();
1401     g_app_list.reqDump();
1402     unsigned req_num = g_app_list.currentRequestNumber();
1403     if (g_app_list.haveRequest())
1404     {
1405         HMI_SEQ_DEBUG(req_num, "Process next request");
1406         WMError rc = doTransition(req_num);
1407         if (rc != WMError::SUCCESS)
1408         {
1409             HMI_SEQ_ERROR(req_num, errorDescription(rc));
1410         }
1411     }
1412     else
1413     {
1414         HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
1415     }
1416 }
1417
1418 const char *WindowManager::check_surface_exist(const char *drawing_name)
1419 {
1420     auto const &surface_id = this->lookup_id(drawing_name);
1421     if (!surface_id)
1422     {
1423         return "Surface does not exist";
1424     }
1425
1426     if (!this->controller->surface_exists(*surface_id))
1427     {
1428         return "Surface does not exist in controller!";
1429     }
1430
1431     auto layer_id = this->layers.get_layer_id(*surface_id);
1432
1433     if (!layer_id)
1434     {
1435         return "Surface is not on any layer!";
1436     }
1437
1438     auto o_state = *this->layers.get_layout_state(*surface_id);
1439
1440     if (o_state == nullptr)
1441     {
1442         return "Could not find layer for surface";
1443     }
1444
1445     HMI_DEBUG("wm", "surface %d is detected", *surface_id);
1446     return nullptr;
1447 }
1448
1449 bool WindowManager::can_split(struct LayoutState const &state, int new_id)
1450 {
1451     if (state.main != -1 && state.main != new_id)
1452     {
1453         auto new_id_layer = this->layers.get_layer_id(new_id).value();
1454         auto current_id_layer = this->layers.get_layer_id(state.main).value();
1455
1456         // surfaces are on separate layers, don't bother.
1457         if (new_id_layer != current_id_layer)
1458         {
1459             return false;
1460         }
1461
1462         std::string const &new_id_str = this->lookup_name(new_id).value();
1463         std::string const &cur_id_str = this->lookup_name(state.main).value();
1464
1465         auto const &layer = this->layers.get_layer(new_id_layer);
1466
1467         HMI_DEBUG("wm", "layer info name: %s", layer->name.c_str());
1468
1469         if (layer->layouts.empty())
1470         {
1471             return false;
1472         }
1473
1474         for (auto i = layer->layouts.cbegin(); i != layer->layouts.cend(); i++)
1475         {
1476             HMI_DEBUG("wm", "%d main_match '%s'", new_id_layer, i->main_match.c_str());
1477             auto rem = std::regex(i->main_match);
1478             if (std::regex_match(cur_id_str, rem))
1479             {
1480                 // build the second one only if the first already matched
1481                 HMI_DEBUG("wm", "%d sub_match '%s'", new_id_layer, i->sub_match.c_str());
1482                 auto res = std::regex(i->sub_match);
1483                 if (std::regex_match(new_id_str, res))
1484                 {
1485                     HMI_DEBUG("wm", "layout matched!");
1486                     return true;
1487                 }
1488             }
1489         }
1490     }
1491
1492     return false;
1493 }
1494
1495 /**
1496  * controller_hooks
1497  */
1498 void controller_hooks::surface_created(uint32_t surface_id)
1499 {
1500     this->app->surface_created(surface_id);
1501 }
1502
1503 void controller_hooks::surface_removed(uint32_t surface_id)
1504 {
1505     this->app->surface_removed(surface_id);
1506 }
1507
1508 void controller_hooks::surface_visibility(uint32_t /*surface_id*/,
1509                                           uint32_t /*v*/) {}
1510
1511 void controller_hooks::surface_destination_rectangle(uint32_t /*surface_id*/,
1512                                                      uint32_t /*x*/,
1513                                                      uint32_t /*y*/,
1514                                                      uint32_t /*w*/,
1515                                                      uint32_t /*h*/) {}
1516
1517 } // namespace wm