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