Clean: Remove split_layout structure
[apps/agl-service-windowmanager.git] / src / layers.cpp
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3  * Copyright (c) 2018 Konsulko Group
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <regex>
19
20 #include "layers.hpp"
21 #include "json_helper.hpp"
22 #include "util.hpp"
23 #include "hmi-debug.h"
24
25 namespace wm
26 {
27
28 using json = nlohmann::json;
29
30 layer::layer(nlohmann::json const &j)
31 {
32     this->role = j["role"];
33     this->name = j["name"];
34     this->layer_id = j["layer_id"];
35
36     HMI_DEBUG("wm", "layer_id:%d name:%s", this->layer_id, this->name.c_str());
37 }
38
39 struct result<struct layer_map> to_layer_map(nlohmann::json const &j)
40 {
41     try
42     {
43         layer_map stl{};
44         auto m = j["mappings"];
45
46         std::transform(std::cbegin(m), std::cend(m),
47                        std::inserter(stl.mapping, stl.mapping.end()),
48                        [](nlohmann::json const &j) {
49                            return std::pair<int, struct layer>(
50                                j.value("layer_id", -1), layer(j));
51                        });
52
53         // TODO: add sanity checks here?
54         // * check for double IDs
55         // * check for double names/roles
56
57         stl.layers.reserve(m.size());
58         std::transform(std::cbegin(stl.mapping), std::cend(stl.mapping),
59                        std::back_inserter(stl.layers),
60                        [&stl](std::pair<int, struct layer> const &k) {
61                            stl.roles.emplace_back(
62                                std::make_pair(k.second.role, k.second.layer_id));
63                            return unsigned(k.second.layer_id);
64                        });
65
66         std::sort(stl.layers.begin(), stl.layers.end());
67
68         for (auto i : stl.mapping)
69         {
70             if (i.second.name.empty())
71             {
72                 return Err<struct layer_map>("Found mapping w/o name");
73             }
74             if (i.second.layer_id == -1)
75             {
76                 return Err<struct layer_map>("Found invalid/unset IDs in mapping");
77             }
78         }
79
80         auto msi = j.find("main_surface");
81         if (msi != j.end())
82         {
83             stl.main_surface_name = msi->value("surface_role", "");
84             stl.main_surface = -1;
85         }
86
87         return Ok(stl);
88     }
89     catch (std::exception &e)
90     {
91         return Err<struct layer_map>(e.what());
92     }
93 }
94
95 optional<int>
96 layer_map::get_layer_id(int surface_id)
97 {
98     auto i = this->surfaces.find(surface_id);
99     if (i != this->surfaces.end())
100     {
101         return optional<int>(i->second);
102     }
103     return nullopt;
104 }
105
106 optional<int> layer_map::get_layer_id(std::string const &role)
107 {
108     for (auto const &r : this->roles)
109     {
110         auto re = std::regex(r.first);
111         if (std::regex_match(role, re))
112         {
113             HMI_DEBUG("wm", "role %s matches layer %d", role.c_str(), r.second);
114             return optional<int>(r.second);
115         }
116     }
117     HMI_DEBUG("wm", "role %s does NOT match any layer", role.c_str());
118     return nullopt;
119 }
120
121 json layer::to_json() const
122 {
123     auto is_full = this->rect == compositor::full_rect;
124
125     json r{};
126     if (is_full)
127     {
128         r = {{"type", "full"}};
129     }
130     else
131     {
132         r = {{"type", "rect"},
133              {"rect",
134               {{"x", this->rect.x},
135                {"y", this->rect.y},
136                {"width", this->rect.w},
137                {"height", this->rect.h}}}};
138     }
139
140     return {
141         {"name", this->name},
142         {"role", this->role},
143         {"layer_id", this->layer_id},
144         {"area", r},
145     };
146 }
147
148 json layer_map::to_json() const
149 {
150     json j{};
151     for (auto const &i : this->mapping)
152     {
153         j.push_back(i.second.to_json());
154     }
155     return j;
156 }
157
158 void layer_map::setupArea(double scaling)
159 {
160     compositor::rect rct;
161
162     rct = this->area2size["normal.full"];
163     this->area2size["normalfull"] = rct;
164     this->area2size["normal"] = rct;
165
166     for (auto &i : this->area2size)
167     {
168         i.second.x = static_cast<int>(scaling * i.second.x + 0.5);
169         i.second.y = static_cast<int>(scaling * i.second.y + 0.5);
170         i.second.w = static_cast<int>(scaling * i.second.w + 0.5);
171         i.second.h = static_cast<int>(scaling * i.second.h + 0.5);
172
173         HMI_DEBUG("wm:lm", "area:%s size(after) : x:%d y:%d w:%d h:%d",
174             i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h);
175     }
176 }
177
178 compositor::rect layer_map::getAreaSize(const std::string &area)
179 {
180     return area2size[area];
181 }
182
183 int layer_map::loadAreaDb()
184 {
185     HMI_DEBUG("wm:lm", "Call");
186
187     std::string file_name(get_file_path("areas.db"));
188
189     // Load area.db
190     json_object *json_obj;
191     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
192     if (0 > ret)
193     {
194         HMI_DEBUG("wm:lm", "Could not open area.db, so use default area information");
195         json_obj = json_tokener_parse(kDefaultAreaDb);
196     }
197     HMI_DEBUG("wm:lm", "json_obj dump:%s", json_object_get_string(json_obj));
198
199     // Perse areas
200     HMI_DEBUG("wm:lm", "Perse areas");
201     json_object *json_cfg;
202     if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))
203     {
204         HMI_ERROR("wm:lm", "Parse Error!!");
205         return -1;
206     }
207
208     int len = json_object_array_length(json_cfg);
209     HMI_DEBUG("wm:lm", "json_cfg len:%d", len);
210     HMI_DEBUG("wm:lm", "json_cfg dump:%s", json_object_get_string(json_cfg));
211
212     const char *area;
213     for (int i = 0; i < len; i++)
214     {
215         json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
216         HMI_DEBUG("wm:lm", "> json_tmp dump:%s", json_object_get_string(json_tmp));
217
218         area = jh::getStringFromJson(json_tmp, "name");
219         if (nullptr == area)
220         {
221             HMI_ERROR("wm:lm", "Parse Error!!");
222             return -1;
223         }
224         HMI_DEBUG("wm:lm", "> area:%s", area);
225
226         json_object *json_rect;
227         if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))
228         {
229             HMI_ERROR("wm:lm", "Parse Error!!");
230             return -1;
231         }
232         HMI_DEBUG("wm:lm", "> json_rect dump:%s", json_object_get_string(json_rect));
233
234         compositor::rect area_size;
235         area_size.x = jh::getIntFromJson(json_rect, "x");
236         area_size.y = jh::getIntFromJson(json_rect, "y");
237         area_size.w = jh::getIntFromJson(json_rect, "w");
238         area_size.h = jh::getIntFromJson(json_rect, "h");
239
240         this->area2size[area] = area_size;
241     }
242
243     // Check
244     for (auto itr = this->area2size.begin();
245          itr != this->area2size.end(); ++itr)
246     {
247         HMI_DEBUG("wm:lm", "area:%s x:%d y:%d w:%d h:%d",
248                   itr->first.c_str(), itr->second.x, itr->second.y,
249                   itr->second.w, itr->second.h);
250     }
251
252     // Release json_object
253     json_object_put(json_obj);
254
255     return 0;
256 }
257
258 const char* layer_map::kDefaultAreaDb = "{ \
259     \"areas\": [ \
260         { \
261             \"name\": \"fullscreen\", \
262             \"rect\": { \
263                 \"x\": 0, \
264                 \"y\": 0, \
265                 \"w\": 1080, \
266                 \"h\": 1920 \
267             } \
268         }, \
269         { \
270             \"name\": \"normal.full\", \
271             \"rect\": { \
272                 \"x\": 0, \
273                 \"y\": 218, \
274                 \"w\": 1080, \
275                 \"h\": 1488 \
276             } \
277         }, \
278         { \
279             \"name\": \"split.main\", \
280             \"rect\": { \
281                 \"x\": 0, \
282                 \"y\": 218, \
283                 \"w\": 1080, \
284                 \"h\": 744 \
285             } \
286         }, \
287         { \
288             \"name\": \"split.sub\", \
289             \"rect\": { \
290                 \"x\": 0, \
291                 \"y\": 962, \
292                 \"w\": 1080, \
293                 \"h\": 744 \
294             } \
295         }, \
296         { \
297             \"name\": \"software_keyboard\", \
298             \"rect\": { \
299                 \"x\": 0, \
300                 \"y\": 962, \
301                 \"w\": 1080, \
302                 \"h\": 744 \
303             } \
304         }, \
305         { \
306             \"name\": \"restriction.normal\", \
307             \"rect\": { \
308                 \"x\": 0, \
309                 \"y\": 218, \
310                 \"w\": 1080, \
311                 \"h\": 1488 \
312             } \
313         }, \
314         { \
315             \"name\": \"restriction.split.main\", \
316             \"rect\": { \
317                 \"x\": 0, \
318                 \"y\": 218, \
319                 \"w\": 1080, \
320                 \"h\": 744 \
321             } \
322         }, \
323         { \
324             \"name\": \"restriction.split.sub\", \
325             \"rect\": { \
326                 \"x\": 0, \
327                 \"y\": 962, \
328                 \"w\": 1080, \
329                 \"h\": 744 \
330             } \
331         }, \
332         { \
333             \"name\": \"on_screen\", \
334             \"rect\": { \
335                 \"x\": 0, \
336                 \"y\": 218, \
337                 \"w\": 1080, \
338                 \"h\": 1488 \
339             } \
340         } \
341     ] \
342 }";
343
344 } // namespace wm