Convert the roles from old one to new
[apps/agl-service-windowmanager-2017.git] / src / layers.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 <regex>
18
19 #include "layers.hpp"
20 #include "hmi-debug.h"
21
22 namespace wm
23 {
24
25 using json = nlohmann::json;
26
27 layer::layer(nlohmann::json const &j)
28 {
29     this->role = j["role"];
30     this->name = j["name"];
31     this->layer_id = j["layer_id"];
32     this->rect = compositor::full_rect;
33     if (j["area"]["type"] == "rect")
34     {
35         auto jr = j["area"]["rect"];
36         this->rect = compositor::rect{
37             jr["width"],
38             jr["height"],
39             jr["x"],
40             jr["y"],
41         };
42     }
43
44     // Init flag of normal layout only
45     this->is_normal_layout_only = true;
46
47     auto split_layouts = j.find("split_layouts");
48     if (split_layouts != j.end())
49     {
50
51         // Clear flag of normal layout only
52         this->is_normal_layout_only = false;
53
54         auto &sls = j["split_layouts"];
55         // this->layouts.reserve(sls.size());
56         std::transform(std::cbegin(sls), std::cend(sls),
57                        std::back_inserter(this->layouts), [this](json const &sl) {
58                            struct split_layout l
59                            {
60                                sl["name"], sl["main_match"], sl["sub_match"]
61                            };
62                            HMI_DEBUG("wm",
63                                      "layer %d add split_layout \"%s\" (main: \"%s\") (sub: "
64                                      "\"%s\")",
65                                      this->layer_id,
66                                      l.name.c_str(), l.main_match.c_str(),
67                                      l.sub_match.c_str());
68                            return l;
69                        });
70     }
71     HMI_DEBUG("wm", "layer_id:%d is_normal_layout_only:%d\n",
72               this->layer_id, this->is_normal_layout_only);
73 }
74
75 struct result<struct layer_map> to_layer_map(nlohmann::json const &j)
76 {
77     try
78     {
79         layer_map stl{};
80         auto m = j["mappings"];
81
82         std::transform(std::cbegin(m), std::cend(m),
83                        std::inserter(stl.mapping, stl.mapping.end()),
84                        [](nlohmann::json const &j) {
85                            return std::pair<int, struct layer>(
86                                j.value("layer_id", -1), layer(j));
87                        });
88
89         // TODO: add sanity checks here?
90         // * check for double IDs
91         // * check for double names/roles
92
93         stl.layers.reserve(m.size());
94         std::transform(std::cbegin(stl.mapping), std::cend(stl.mapping),
95                        std::back_inserter(stl.layers),
96                        [&stl](std::pair<int, struct layer> const &k) {
97                            stl.roles.emplace_back(
98                                std::make_pair(k.second.role, k.second.layer_id));
99                            return unsigned(k.second.layer_id);
100                        });
101
102         std::sort(stl.layers.begin(), stl.layers.end());
103
104         for (auto i : stl.mapping)
105         {
106             if (i.second.name.empty())
107             {
108                 return Err<struct layer_map>("Found mapping w/o name");
109             }
110             if (i.second.layer_id == -1)
111             {
112                 return Err<struct layer_map>("Found invalid/unset IDs in mapping");
113             }
114         }
115
116         auto msi = j.find("main_surface");
117         if (msi != j.end())
118         {
119             stl.main_surface_name = msi->value("surface_role", "");
120             stl.main_surface = -1;
121         }
122
123         return Ok(stl);
124     }
125     catch (std::exception &e)
126     {
127         return Err<struct layer_map>(e.what());
128     }
129 }
130
131 optional<int>
132 layer_map::get_layer_id(int surface_id)
133 {
134     auto i = this->surfaces.find(surface_id);
135     if (i != this->surfaces.end())
136     {
137         return optional<int>(i->second);
138     }
139     return nullopt;
140 }
141
142 optional<int> layer_map::get_layer_id(std::string const &role)
143 {
144     for (auto const &r : this->roles)
145     {
146         auto re = std::regex(r.first);
147         if (std::regex_match(role, re))
148         {
149             HMI_DEBUG("wm", "role %s matches layer %d", role.c_str(), r.second);
150             return optional<int>(r.second);
151         }
152     }
153     HMI_DEBUG("wm", "role %s does NOT match any layer", role.c_str());
154     return nullopt;
155 }
156
157 json layer::to_json() const
158 {
159     auto is_full = this->rect == compositor::full_rect;
160
161     json r{};
162     if (is_full)
163     {
164         r = {{"type", "full"}};
165     }
166     else
167     {
168         r = {{"type", "rect"},
169              {"rect",
170               {{"x", this->rect.x},
171                {"y", this->rect.y},
172                {"width", this->rect.w},
173                {"height", this->rect.h}}}};
174     }
175
176     return {
177         {"name", this->name},
178         {"role", this->role},
179         {"layer_id", this->layer_id},
180         {"area", r},
181     };
182 }
183
184 json layer_map::to_json() const
185 {
186     json j{};
187     for (auto const &i : this->mapping)
188     {
189         j.push_back(i.second.to_json());
190     }
191     return j;
192 }
193
194 void layer_map::setupArea(int output_w, int output_h)
195 {
196     compositor::rect rct;
197     // setup normal.full
198     std::string area = "normal.full";
199     std::string role = "fallback";
200     auto l_id = this->get_layer_id(role);
201     auto l = this->get_layer(*l_id);
202     rct = l->rect;
203     if(rct.w < 0)
204         rct.w = output_w + 1 + rct.w;
205     if(rct.h < 0)
206         rct.h = output_h + 1 + rct.h;
207     this->area2size[area] = rct;
208     this->area2size["normalfull"] = rct;
209     this->area2size["normal"] = rct;
210
211     // setup split.main
212     area = "split.main";
213     rct.h = rct.h / 2;
214     this->area2size[area] = rct;
215
216     // setup split.sub
217     area = "split.sub";
218     rct.y = rct.y + rct.h;
219     this->area2size[area] = rct;
220
221     // setup homescreen
222     area = "fullscreen";
223     role = "homescreen";
224     rct = compositor::full_rect;
225     if (rct.w <= 0)
226         rct.w = output_w + rct.w + 1;
227     if (rct.h <= 0)
228         rct.h = output_h + rct.h + 1;
229     this->area2size[area] = rct;
230
231     // setup onscreen
232     area = "on_screen";
233     role = "on_screen";
234     auto ons_id = this->get_layer_id(role);
235     auto l_ons = this->get_layer(*ons_id);
236     rct = l_ons->rect;
237     if (rct.w < 0)
238         rct.w = output_w + 1 + rct.w;
239     if (rct.h < 0)
240         rct.h = output_h + 1 + rct.h;
241     this->area2size[area] = rct;
242 }
243
244 compositor::rect layer_map::getAreaSize(const std::string &area)
245 {
246     return area2size[area];
247 }
248
249 } // namespace wm