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