get callback of surface_stats_received
[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::surface_properties(unsigned surface_id, unsigned pid)
612 {
613     HMI_DEBUG("wm", "get surface properties");
614
615     // search pid from surfaceID
616     /*json_object *response;
617     afb_service_call_sync("afm-main", "runners", nullptr, &response);
618
619     // retrieve appid from pid from application manager
620     std::string appid = "";
621     if(response == nullptr)
622     {
623         HMI_ERROR("wm", "No runners");
624     }
625     else
626     {
627         // check appid then add it to the client
628         HMI_INFO("wm", "Runners:%s", json_object_get_string(response));
629         int size = json_object_array_length(response);
630         for(int i = 0; i < size; i++)
631         {
632             json_object *j = json_object_array_get_idx(response, i);
633             const char* id = jh::getStringFromJson(j, "id");
634             int runid      = jh::getIntFromJson(j, "runid");
635             if(id && (runid > 0))
636             {
637                 if(runid == pid)
638                 {
639                     appid = id;
640                     break;
641                 }
642             }
643         }
644     }
645     json_object_put(response);
646
647     g_app_list.addFloatingSurface(appid, surface_id, pid);*/
648 }
649
650 void WindowManager::removeClient(const std::string &appid)
651 {
652     HMI_DEBUG("wm", "Remove clinet %s from list", appid.c_str());
653     g_app_list.removeClient(appid);
654 }
655
656 void WindowManager::exceptionProcessForTransition()
657 {
658     unsigned req_num = g_app_list.currentRequestNumber();
659     HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
660     g_app_list.removeRequest(req_num);
661     HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
662     this->processNextRequest();
663 }
664
665 void WindowManager::timerHandler()
666 {
667     unsigned req_num = g_app_list.currentRequestNumber();
668     HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
669     g_app_list.reqDump();
670     g_app_list.removeRequest(req_num);
671     this->processNextRequest();
672 }
673
674 void WindowManager::startTransitionWrapper(std::vector<WMAction> &actions)
675 {
676     WMError ret;
677     unsigned req_num = g_app_list.currentRequestNumber();
678
679     if (actions.empty())
680     {
681         if (g_app_list.haveRequest())
682         {
683             HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
684             goto proc_remove_request;
685         }
686         else
687         {
688             HMI_SEQ_DEBUG(req_num, "There is no request");
689             return;
690         }
691     }
692
693     for (auto &act : actions)
694     {
695         if ("" != act.role)
696         {
697             bool found;
698             auto const &surface_id = this->lookup_id(act.role.c_str());
699             std::string appid = g_app_list.getAppID(*surface_id, act.role, &found);
700             if (!found)
701             {
702                 if (TaskVisible::INVISIBLE == act.visible)
703                 {
704                     // App is killed, so do not set this action
705                     continue;
706                 }
707                 else
708                 {
709                     HMI_SEQ_ERROR(req_num, "appid which is visible is not found");
710                     ret = WMError::FAIL;
711                     goto error;
712                 }
713             }
714             act.appid = appid;
715         }
716
717         ret = g_app_list.setAction(req_num, act);
718         if (ret != WMError::SUCCESS)
719         {
720             HMI_SEQ_ERROR(req_num, "Setting action is failed");
721             goto error;
722         }
723     }
724
725     HMI_SEQ_DEBUG(req_num, "Start transition.");
726     ret = this->startTransition(req_num);
727     if (ret != WMError::SUCCESS)
728     {
729         if (ret == WMError::NO_LAYOUT_CHANGE)
730         {
731             goto proc_remove_request;
732         }
733         else
734         {
735             HMI_SEQ_ERROR(req_num, "Transition state is failed");
736             goto error;
737         }
738     }
739
740     return;
741
742 error:
743     //this->emit_error()
744     HMI_SEQ_ERROR(req_num, errorDescription(ret));
745     this->pmw.undoState();
746
747 proc_remove_request:
748     g_app_list.removeRequest(req_num);
749     this->processNextRequest();
750 }
751
752 void WindowManager::processError(WMError error)
753 {
754     unsigned req_num = g_app_list.currentRequestNumber();
755
756     //this->emit_error()
757     HMI_SEQ_ERROR(req_num, errorDescription(error));
758     g_app_list.removeRequest(req_num);
759     this->processNextRequest();
760 }
761
762 /*
763  ******* Private Functions *******
764  */
765
766 bool WindowManager::pop_pending_events()
767 {
768     bool x{true};
769     return this->pending_events.compare_exchange_strong(
770         x, false, std::memory_order_consume);
771 }
772
773 optional<int> WindowManager::lookup_id(char const *name)
774 {
775     return this->id_alloc.lookup(std::string(name));
776 }
777 optional<std::string> WindowManager::lookup_name(int id)
778 {
779     return this->id_alloc.lookup(id);
780 }
781
782 /**
783  * init_layers()
784  */
785 int WindowManager::init_layers()
786 {
787     if (!this->controller)
788     {
789         HMI_ERROR("wm", "ivi_controller global not available");
790         return -1;
791     }
792
793     if (this->outputs.empty())
794     {
795         HMI_ERROR("wm", "no output was set up!");
796         return -1;
797     }
798
799     auto &c = this->controller;
800
801     auto &o = this->outputs.front();
802     auto &s = c->screens.begin()->second;
803     auto &layers = c->layers;
804
805     // Write output dimensions to ivi controller...
806     c->output_size = compositor::size{uint32_t(o->width), uint32_t(o->height)};
807     c->physical_size = compositor::size{uint32_t(o->physical_width),
808                                         uint32_t(o->physical_height)};
809
810
811     HMI_DEBUG("wm", "SCALING: screen (%dx%d), physical (%dx%d)",
812               o->width, o->height, o->physical_width, o->physical_height);
813
814     this->layers.loadAreaDb();
815
816     const compositor::rect css_bg = this->layers.getAreaSize("fullscreen");
817     rectangle dp_bg(o->width, o->height);
818
819     dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h);
820     dp_bg.fit(o->width, o->height);
821     dp_bg.center(o->width, o->height);
822     HMI_DEBUG("wm", "SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)",
823               css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
824
825     // Clear scene
826     layers.clear();
827
828     // Clear screen
829     s->clear();
830
831     // Quick and dirty setup of layers
832     for (auto const &i : this->layers.mapping)
833     {
834         c->layer_create(i.second.layer_id, dp_bg.width(), dp_bg.height());
835         auto &l = layers[i.second.layer_id];
836         l->set_destination_rectangle(dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
837         l->set_visibility(1);
838         HMI_DEBUG("wm", "Setting up layer %s (%d) for surface role match \"%s\"",
839                   i.second.name.c_str(), i.second.layer_id, i.second.role.c_str());
840     }
841
842     // Add layers to screen
843     s->set_render_order(this->layers.layers);
844
845     this->layout_commit();
846
847     c->scale = static_cast<double>(dp_bg.height()) / css_bg.h;
848     this->layers.setupArea(c->scale);
849
850     return 0;
851 }
852
853 void WindowManager::surface_set_layout(int surface_id, const std::string& area)
854 {
855     if (!this->controller->surface_exists(surface_id))
856     {
857         HMI_ERROR("wm", "Surface %d does not exist", surface_id);
858         return;
859     }
860
861     auto o_layer_id = this->layers.get_layer_id(surface_id);
862
863     if (!o_layer_id)
864     {
865         HMI_ERROR("wm", "Surface %d is not associated with any layer!", surface_id);
866         return;
867     }
868
869     uint32_t layer_id = *o_layer_id;
870
871     auto const &layer = this->layers.get_layer(layer_id);
872     auto rect = this->layers.getAreaSize(area);
873     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "%s : x:%d y:%d w:%d h:%d", area.c_str(),
874                     rect.x, rect.y, rect.w, rect.h);
875     auto &s = this->controller->surfaces[surface_id];
876
877     int x = rect.x;
878     int y = rect.y;
879     int w = rect.w;
880     int h = rect.h;
881
882     HMI_DEBUG("wm", "surface_set_layout for surface %u on layer %u", surface_id,
883               layer_id);
884
885     // set destination to the display rectangle
886     s->set_destination_rectangle(x, y, w, h);
887
888     // update area information
889     this->area_info[surface_id].x = x;
890     this->area_info[surface_id].y = y;
891     this->area_info[surface_id].w = w;
892     this->area_info[surface_id].h = h;
893
894     HMI_DEBUG("wm", "Surface %u now on layer %u with rect { %d, %d, %d, %d }",
895               surface_id, layer_id, x, y, w, h);
896 }
897
898 void WindowManager::layout_commit()
899 {
900     this->controller->commit_changes();
901     this->display->flush();
902 }
903
904 void WindowManager::emit_activated(char const *label)
905 {
906     this->send_event(kListEventName[Event_Active], label);
907 }
908
909 void WindowManager::emit_deactivated(char const *label)
910 {
911     this->send_event(kListEventName[Event_Inactive], label);
912 }
913
914 void WindowManager::emit_syncdraw(char const *label, char const *area, int x, int y, int w, int h)
915 {
916     this->send_event(kListEventName[Event_SyncDraw], label, area, x, y, w, h);
917 }
918
919 void WindowManager::emit_syncdraw(const std::string &role, const std::string &area)
920 {
921     compositor::rect rect = this->layers.getAreaSize(area);
922     this->send_event(kListEventName[Event_SyncDraw],
923         role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
924 }
925
926 void WindowManager::emit_flushdraw(char const *label)
927 {
928     this->send_event(kListEventName[Event_FlushDraw], label);
929 }
930
931 void WindowManager::emit_visible(char const *label, bool is_visible)
932 {
933     this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], label);
934 }
935
936 void WindowManager::emit_invisible(char const *label)
937 {
938     return emit_visible(label, false);
939 }
940
941 void WindowManager::emit_visible(char const *label) { return emit_visible(label, true); }
942
943 void WindowManager::activate(int id)
944 {
945     auto ip = this->controller->sprops.find(id);
946     if (ip != this->controller->sprops.end())
947     {
948         this->controller->surfaces[id]->set_visibility(1);
949         char const *label =
950             this->lookup_name(id).value_or("unknown-name").c_str();
951
952          // FOR CES DEMO >>>
953         if ((0 == strcmp(label, "radio")) ||
954             (0 == strcmp(label, "music")) ||
955             (0 == strcmp(label, "video")) ||
956             (0 == strcmp(label, "map")))
957         {
958             for (auto i = surface_bg.begin(); i != surface_bg.end(); ++i)
959             {
960                 if (id == *i)
961                 {
962                     // Remove id
963                     this->surface_bg.erase(i);
964
965                     // Remove from BG layer (999)
966                     HMI_DEBUG("wm", "Remove %s(%d) from BG layer", label, id);
967                     this->controller->layers[999]->remove_surface(id);
968
969                     // Add to FG layer (1001)
970                     HMI_DEBUG("wm", "Add %s(%d) to FG layer", label, id);
971                     this->controller->layers[1001]->add_surface(id);
972
973                     for (int j : this->surface_bg)
974                     {
975                         HMI_DEBUG("wm", "Stored id:%d", j);
976                     }
977                     break;
978                 }
979             }
980         }
981         // <<< FOR CES DEMO
982
983         this->layout_commit();
984
985         // TODO: application requests by old role,
986         //       so convert role new to old for emitting event
987         const char* old_role = this->rolenew2old[label].c_str();
988
989         this->emit_visible(old_role);
990         this->emit_activated(old_role);
991     }
992 }
993
994 void WindowManager::deactivate(int id)
995 {
996     auto ip = this->controller->sprops.find(id);
997     if (ip != this->controller->sprops.end())
998     {
999         char const *label =
1000             this->lookup_name(id).value_or("unknown-name").c_str();
1001
1002         // FOR CES DEMO >>>
1003         if ((0 == strcmp(label, "radio")) ||
1004             (0 == strcmp(label, "music")) ||
1005             (0 == strcmp(label, "video")) ||
1006             (0 == strcmp(label, "map")))
1007         {
1008
1009             // Store id
1010             this->surface_bg.push_back(id);
1011
1012             // Remove from FG layer (1001)
1013             HMI_DEBUG("wm", "Remove %s(%d) from FG layer", label, id);
1014             this->controller->layers[1001]->remove_surface(id);
1015
1016             // Add to BG layer (999)
1017             HMI_DEBUG("wm", "Add %s(%d) to BG layer", label, id);
1018             this->controller->layers[999]->add_surface(id);
1019
1020             for (int j : surface_bg)
1021             {
1022                 HMI_DEBUG("wm", "Stored id:%d", j);
1023             }
1024         }
1025         else
1026         {
1027             this->controller->surfaces[id]->set_visibility(0);
1028         }
1029         // <<< FOR CES DEMO
1030
1031         this->layout_commit();
1032
1033         // TODO: application requests by old role,
1034         //       so convert role new to old for emitting event
1035         const char* old_role = this->rolenew2old[label].c_str();
1036
1037         this->emit_deactivated(old_role);
1038         this->emit_invisible(old_role);
1039     }
1040 }
1041
1042 WMError WindowManager::setRequest(const std::string& appid, const std::string &role, const std::string &area,
1043                             Task task, unsigned* req_num)
1044 {
1045     if (!g_app_list.contains(appid))
1046     {
1047         return WMError::NOT_REGISTERED;
1048     }
1049
1050     auto client = g_app_list.lookUpClient(appid);
1051
1052     /*
1053      * Queueing Phase
1054      */
1055     unsigned current = g_app_list.currentRequestNumber();
1056     unsigned requested_num = g_app_list.getRequestNumber(appid);
1057     if (requested_num != 0)
1058     {
1059         HMI_SEQ_INFO(requested_num,
1060             "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
1061         return REQ_REJECTED;
1062     }
1063
1064     WMRequest req = WMRequest(appid, role, area, task);
1065     unsigned new_req = g_app_list.addRequest(req);
1066     *req_num = new_req;
1067     g_app_list.reqDump();
1068
1069     HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
1070
1071     return WMError::SUCCESS;
1072 }
1073
1074 WMError WindowManager::doTransition(unsigned req_num)
1075 {
1076     HMI_SEQ_DEBUG(req_num, "check policy");
1077     WMError ret = this->checkPolicy(req_num);
1078     return ret;
1079 }
1080
1081 WMError WindowManager::checkPolicy(unsigned req_num)
1082 {
1083     /*
1084     * Check Policy
1085     */
1086     // get current trigger
1087     bool found = false;
1088     WMError ret = WMError::LAYOUT_CHANGE_FAIL;
1089     auto trigger = g_app_list.getRequest(req_num, &found);
1090     if (!found)
1091     {
1092         ret = WMError::NO_ENTRY;
1093         return ret;
1094     }
1095     std::string req_area = trigger.area;
1096
1097     if (trigger.task == Task::TASK_ALLOCATE)
1098     {
1099         const char *msg = this->check_surface_exist(trigger.role.c_str());
1100
1101         if (msg)
1102         {
1103             HMI_SEQ_ERROR(req_num, msg);
1104             return ret;
1105         }
1106     }
1107
1108     // Input event data to PolicyManager
1109     if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
1110     {
1111         HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
1112         return ret;
1113     }
1114
1115     // Execute state transition of PolicyManager
1116     if (0 > this->pmw.executeStateTransition())
1117     {
1118         HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
1119         return ret;
1120     }
1121
1122     ret = WMError::SUCCESS;
1123
1124     g_app_list.reqDump();
1125
1126     return ret;
1127 }
1128
1129 WMError WindowManager::startTransition(unsigned req_num)
1130 {
1131     bool sync_draw_happen = false;
1132     bool found = false;
1133     WMError ret = WMError::SUCCESS;
1134     auto actions = g_app_list.getActions(req_num, &found);
1135     if (!found)
1136     {
1137         ret = WMError::NO_ENTRY;
1138         HMI_SEQ_ERROR(req_num,
1139             "Window Manager bug :%s : Action is not set", errorDescription(ret));
1140         return ret;
1141     }
1142
1143     for (const auto &action : actions)
1144     {
1145         if (action.visible == TaskVisible::VISIBLE)
1146         {
1147             sync_draw_happen = true;
1148
1149             // TODO: application requests by old role,
1150             //       so convert role new to old for emitting event
1151             std::string old_role = this->rolenew2old[action.role];
1152
1153             this->emit_syncdraw(old_role, action.area);
1154             /* TODO: emit event for app not subscriber
1155             if(g_app_list.contains(y.appid))
1156                 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
1157         }
1158     }
1159
1160     if (sync_draw_happen)
1161     {
1162         this->setTimer();
1163     }
1164     else
1165     {
1166         // deactivate only, no syncDraw
1167         // Make it deactivate here
1168         for (const auto &x : actions)
1169         {
1170             if (g_app_list.contains(x.appid))
1171             {
1172                 auto client = g_app_list.lookUpClient(x.appid);
1173                 this->deactivate(client->surfaceID(x.role));
1174             }
1175         }
1176         ret = WMError::NO_LAYOUT_CHANGE;
1177     }
1178     return ret;
1179 }
1180
1181 WMError WindowManager::doEndDraw(unsigned req_num)
1182 {
1183     // get actions
1184     bool found;
1185     auto actions = g_app_list.getActions(req_num, &found);
1186     WMError ret = WMError::SUCCESS;
1187     if (!found)
1188     {
1189         ret = WMError::NO_ENTRY;
1190         return ret;
1191     }
1192
1193     HMI_SEQ_INFO(req_num, "do endDraw");
1194
1195     // layout change and make it visible
1196     for (const auto &act : actions)
1197     {
1198         if(act.visible != TaskVisible::NO_CHANGE)
1199         {
1200             // layout change
1201             if(!g_app_list.contains(act.appid)){
1202                 ret = WMError::NOT_REGISTERED;
1203             }
1204             ret = this->layoutChange(act);
1205             if(ret != WMError::SUCCESS)
1206             {
1207                 HMI_SEQ_WARNING(req_num,
1208                     "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
1209                 return ret;
1210             }
1211             ret = this->visibilityChange(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             HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
1219             //this->lm_enddraw(act.role.c_str());
1220         }
1221     }
1222     this->layout_commit();
1223
1224     HMI_SEQ_INFO(req_num, "emit flushDraw");
1225
1226     for(const auto &act_flush : actions)
1227     {
1228         if(act_flush.visible == TaskVisible::VISIBLE)
1229         {
1230             // TODO: application requests by old role,
1231             //       so convert role new to old for emitting event
1232             std::string old_role = this->rolenew2old[act_flush.role];
1233
1234             this->emit_flushdraw(old_role.c_str());
1235         }
1236     }
1237
1238     return ret;
1239 }
1240
1241 WMError WindowManager::layoutChange(const WMAction &action)
1242 {
1243     if (action.visible == TaskVisible::INVISIBLE)
1244     {
1245         // Visibility is not change -> no redraw is required
1246         return WMError::SUCCESS;
1247     }
1248     auto client = g_app_list.lookUpClient(action.appid);
1249     unsigned surface = client->surfaceID(action.role);
1250     if (surface == 0)
1251     {
1252         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
1253                       "client doesn't have surface with role(%s)", action.role.c_str());
1254         return WMError::NOT_REGISTERED;
1255     }
1256     // Layout Manager
1257     WMError ret = this->setSurfaceSize(surface, action.area);
1258     return ret;
1259 }
1260
1261 WMError WindowManager::visibilityChange(const WMAction &action)
1262 {
1263     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Change visibility");
1264     if(!g_app_list.contains(action.appid)){
1265         return WMError::NOT_REGISTERED;
1266     }
1267     auto client = g_app_list.lookUpClient(action.appid);
1268     unsigned surface = client->surfaceID(action.role);
1269     if(surface == 0)
1270     {
1271         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
1272                       "client doesn't have surface with role(%s)", action.role.c_str());
1273         return WMError::NOT_REGISTERED;
1274     }
1275
1276     if (action.visible != TaskVisible::INVISIBLE)
1277     {
1278         this->activate(surface); // Layout Manager task
1279     }
1280     else
1281     {
1282         this->deactivate(surface); // Layout Manager task
1283     }
1284     return WMError::SUCCESS;
1285 }
1286
1287 WMError WindowManager::setSurfaceSize(unsigned surface, const std::string &area)
1288 {
1289     this->surface_set_layout(surface, area);
1290
1291     return WMError::SUCCESS;
1292 }
1293
1294 void WindowManager::emitScreenUpdated(unsigned req_num)
1295 {
1296     // Get visible apps
1297     HMI_SEQ_DEBUG(req_num, "emit screen updated");
1298     bool found = false;
1299     auto actions = g_app_list.getActions(req_num, &found);
1300
1301     // create json object
1302     json_object *j = json_object_new_object();
1303     json_object *jarray = json_object_new_array();
1304
1305     for(const auto& action: actions)
1306     {
1307         if(action.visible != TaskVisible::INVISIBLE)
1308         {
1309             json_object_array_add(jarray, json_object_new_string(action.appid.c_str()));
1310         }
1311     }
1312     json_object_object_add(j, kKeyIds, jarray);
1313     HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
1314
1315     int ret = afb_event_push(
1316         this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
1317     if (ret != 0)
1318     {
1319         HMI_DEBUG("wm", "afb_event_push failed: %m");
1320     }
1321 }
1322
1323 void WindowManager::setTimer()
1324 {
1325     struct timespec ts;
1326     if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
1327         HMI_ERROR("wm", "Could't set time (clock_gettime() returns with error");
1328         return;
1329     }
1330
1331     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
1332     if (g_timer_ev_src == nullptr)
1333     {
1334         // firsttime set into sd_event
1335         int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
1336             CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
1337         if (ret < 0)
1338         {
1339             HMI_ERROR("wm", "Could't set timer");
1340         }
1341     }
1342     else
1343     {
1344         // update timer limitation after second time
1345         sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
1346         sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
1347     }
1348 }
1349
1350 void WindowManager::stopTimer()
1351 {
1352     unsigned req_num = g_app_list.currentRequestNumber();
1353     HMI_SEQ_DEBUG(req_num, "Timer stop");
1354     int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
1355     if (rc < 0)
1356     {
1357         HMI_SEQ_ERROR(req_num, "Timer stop failed");
1358     }
1359 }
1360
1361 void WindowManager::processNextRequest()
1362 {
1363     g_app_list.next();
1364     g_app_list.reqDump();
1365     unsigned req_num = g_app_list.currentRequestNumber();
1366     if (g_app_list.haveRequest())
1367     {
1368         HMI_SEQ_DEBUG(req_num, "Process next request");
1369         WMError rc = doTransition(req_num);
1370         if (rc != WMError::SUCCESS)
1371         {
1372             HMI_SEQ_ERROR(req_num, errorDescription(rc));
1373         }
1374     }
1375     else
1376     {
1377         HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
1378     }
1379 }
1380
1381 const char* WindowManager::convertRoleOldToNew(char const *old_role)
1382 {
1383     const char *new_role = nullptr;
1384
1385     for (auto const &on : this->roleold2new)
1386     {
1387         std::regex regex = std::regex(on.first);
1388         if (std::regex_match(old_role, regex))
1389         {
1390             // role is old. So convert to new.
1391             new_role = on.second.c_str();
1392             break;
1393         }
1394     }
1395
1396     if (nullptr == new_role)
1397     {
1398         // role is new or fallback.
1399         new_role = old_role;
1400     }
1401
1402     HMI_DEBUG("wm", "old:%s -> new:%s", old_role, new_role);
1403
1404     return new_role;
1405 }
1406
1407 int WindowManager::loadOldRoleDb()
1408 {
1409     // Get afm application installed dir
1410     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
1411     HMI_DEBUG("wm", "afm_app_install_dir:%s", afm_app_install_dir);
1412
1413     std::string file_name;
1414     if (!afm_app_install_dir)
1415     {
1416         HMI_ERROR("wm", "AFM_APP_INSTALL_DIR is not defined");
1417     }
1418     else
1419     {
1420         file_name = std::string(afm_app_install_dir) + std::string("/etc/old_roles.db");
1421     }
1422
1423     // Load old_role.db
1424     json_object* json_obj;
1425     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
1426     if (0 > ret)
1427     {
1428         HMI_ERROR("wm", "Could not open old_role.db, so use default old_role information");
1429         json_obj = json_tokener_parse(kDefaultOldRoleDb);
1430     }
1431     HMI_DEBUG("wm", "json_obj dump:%s", json_object_get_string(json_obj));
1432
1433     // Perse apps
1434     json_object* json_cfg;
1435     if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
1436     {
1437         HMI_ERROR("wm", "Parse Error!!");
1438         return -1;
1439     }
1440
1441     int len = json_object_array_length(json_cfg);
1442     HMI_DEBUG("wm", "json_cfg len:%d", len);
1443     HMI_DEBUG("wm", "json_cfg dump:%s", json_object_get_string(json_cfg));
1444
1445     for (int i=0; i<len; i++)
1446     {
1447         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
1448
1449         const char* old_role = jh::getStringFromJson(json_tmp, "name");
1450         if (nullptr == old_role)
1451         {
1452             HMI_ERROR("wm", "Parse Error!!");
1453             return -1;
1454         }
1455
1456         const char* new_role = jh::getStringFromJson(json_tmp, "new");
1457         if (nullptr == new_role)
1458         {
1459             HMI_ERROR("wm", "Parse Error!!");
1460             return -1;
1461         }
1462
1463         this->roleold2new[old_role] = std::string(new_role);
1464     }
1465
1466     // Check
1467     for(auto itr = this->roleold2new.begin();
1468       itr != this->roleold2new.end(); ++itr)
1469     {
1470         HMI_DEBUG("wm", ">>> role old:%s new:%s",
1471                   itr->first.c_str(), itr->second.c_str());
1472     }
1473
1474     // Release json_object
1475     json_object_put(json_obj);
1476
1477     return 0;
1478 }
1479
1480 const char *WindowManager::check_surface_exist(const char *drawing_name)
1481 {
1482     auto const &surface_id = this->lookup_id(drawing_name);
1483     if (!surface_id)
1484     {
1485         return "Surface does not exist";
1486     }
1487
1488     if (!this->controller->surface_exists(*surface_id))
1489     {
1490         return "Surface does not exist in controller!";
1491     }
1492
1493     auto layer_id = this->layers.get_layer_id(*surface_id);
1494
1495     if (!layer_id)
1496     {
1497         return "Surface is not on any layer!";
1498     }
1499
1500     HMI_DEBUG("wm", "surface %d is detected", *surface_id);
1501     return nullptr;
1502 }
1503
1504 const char* WindowManager::kDefaultOldRoleDb = "{ \
1505     \"old_roles\": [ \
1506         { \
1507             \"name\": \"HomeScreen\", \
1508             \"new\": \"homescreen\" \
1509         }, \
1510         { \
1511             \"name\": \"Music\", \
1512             \"new\": \"music\" \
1513         }, \
1514         { \
1515             \"name\": \"MediaPlayer\", \
1516             \"new\": \"music\" \
1517         }, \
1518         { \
1519             \"name\": \"Video\", \
1520             \"new\": \"video\" \
1521         }, \
1522         { \
1523             \"name\": \"VideoPlayer\", \
1524             \"new\": \"video\" \
1525         }, \
1526         { \
1527             \"name\": \"WebBrowser\", \
1528             \"new\": \"browser\" \
1529         }, \
1530         { \
1531             \"name\": \"Radio\", \
1532             \"new\": \"radio\" \
1533         }, \
1534         { \
1535             \"name\": \"Phone\", \
1536             \"new\": \"phone\" \
1537         }, \
1538         { \
1539             \"name\": \"Navigation\", \
1540             \"new\": \"map\" \
1541         }, \
1542         { \
1543             \"name\": \"HVAC\", \
1544             \"new\": \"hvac\" \
1545         }, \
1546         { \
1547             \"name\": \"Settings\", \
1548             \"new\": \"settings\" \
1549         }, \
1550         { \
1551             \"name\": \"Dashboard\", \
1552             \"new\": \"dashboard\" \
1553         }, \
1554         { \
1555             \"name\": \"POI\", \
1556             \"new\": \"poi\" \
1557         }, \
1558         { \
1559             \"name\": \"Mixer\", \
1560             \"new\": \"mixer\" \
1561         }, \
1562         { \
1563             \"name\": \"Restriction\", \
1564             \"new\": \"restriction\" \
1565         }, \
1566         { \
1567             \"name\": \"^OnScreen.*\", \
1568             \"new\": \"on_screen\" \
1569         } \
1570     ] \
1571 }";
1572
1573 /**
1574  * controller_hooks
1575  */
1576 void controller_hooks::surface_created(uint32_t surface_id)
1577 {
1578     this->wmgr->surface_created(surface_id);
1579 }
1580
1581 void controller_hooks::surface_removed(uint32_t surface_id)
1582 {
1583     this->wmgr->surface_removed(surface_id);
1584 }
1585
1586 void controller_hooks::surface_visibility(uint32_t /*surface_id*/,
1587                                           uint32_t /*v*/) {}
1588
1589 void controller_hooks::surface_destination_rectangle(uint32_t /*surface_id*/,
1590                                                      uint32_t /*x*/,
1591                                                      uint32_t /*y*/,
1592                                                      uint32_t /*w*/,
1593                                                      uint32_t /*h*/) {}
1594
1595 void controller_hooks::surface_properties(uint32_t surface_id, uint32_t pid)
1596 {
1597     this->wmgr->surface_properties(surface_id, pid);
1598 }
1599
1600 } // namespace wm