blob: 230e788ba6954ac4393998c235194c99d99b2380 [file] [log] [blame]
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001/*
2 * Copyright (C) 2014 DENSO CORPORATION
3 *
Bryce Harringtonaf637c22015-06-11 12:55:55 -07004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090011 *
Bryce Harringtonaf637c22015-06-11 12:55:55 -070012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090024 */
25
26/**
27 * A reference implementation how to use ivi-layout APIs in order to manage
28 * layout of ivi_surfaces/ivi_layers. Layout change is triggered by
29 * ivi-hmi-controller protocol, ivi-hmi-controller.xml. A reference how to
30 * use the protocol, see hmi-controller-homescreen.
31 *
32 * In-Vehicle Infotainment system usually manage properties of
33 * ivi_surfaces/ivi_layers by only a central component which decide where
34 * ivi_surfaces/ivi_layers shall be. This reference show examples to
35 * implement the central component as a module of weston.
36 *
37 * Default Scene graph of UI is defined in hmi_controller_create. It
38 * consists of
39 * - In the bottom, a base ivi_layer to group ivi_surfaces of background,
40 * panel, and buttons
Abdur Rehmanb833d742017-01-01 19:46:34 +050041 * - Next, an application ivi_layer to show application ivi_surfaces.
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090042 * - Workspace background ivi_layer to show a ivi_surface of background image.
43 * - Workspace ivi_layer to show launcher to launch application with icons.
44 * Paths to binary and icon are defined in weston.ini. The width of this
45 * ivi_layer is longer than the size of ivi_screen because a workspace has
46 * several pages and is controlled by motion of input.
47 *
48 * TODO: animation method shall be refined
49 * TODO: support fade-in when UI is ready
50 */
51
Marius Vlad6bc37252018-12-13 16:31:14 +020052#include "config.h"
53
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090054#include <sys/wait.h>
55#include <unistd.h>
56#include <stdlib.h>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030057#include <stdint.h>
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090058#include <stdio.h>
59#include <string.h>
60#include <linux/input.h>
61#include <assert.h>
62#include <time.h>
63
64#include "ivi-layout-export.h"
65#include "ivi-hmi-controller-server-protocol.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070066#include "shared/helpers.h"
Bryce Harringtone99e4bf2016-03-16 14:15:18 -070067#include "shared/xalloc.h"
Pekka Paalanen58f98c92016-06-03 16:45:21 +030068#include "compositor/weston.h"
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090069
70/*****************************************************************************
71 * structure, globals
72 ****************************************************************************/
73struct hmi_controller_layer {
74 struct ivi_layout_layer *ivilayer;
75 uint32_t id_layer;
76 int32_t x;
77 int32_t y;
78 int32_t width;
79 int32_t height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +090080 struct wl_list link;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090081};
82
83struct link_layer {
84 struct ivi_layout_layer *layout_layer;
85 struct wl_list link;
86};
87
88struct hmi_controller_fade {
89 uint32_t is_fade_in;
90 struct wl_list layer_list;
91};
92
93struct hmi_server_setting {
94 uint32_t base_layer_id;
95 uint32_t application_layer_id;
96 uint32_t workspace_background_layer_id;
97 uint32_t workspace_layer_id;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +090098 uint32_t base_layer_id_offset;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090099 int32_t panel_height;
100 uint32_t transition_duration;
101 char *ivi_homescreen;
102};
103
104struct ui_setting {
105 uint32_t background_id;
106 uint32_t panel_id;
107 uint32_t tiling_id;
108 uint32_t sidebyside_id;
109 uint32_t fullscreen_id;
110 uint32_t random_id;
111 uint32_t home_id;
112 uint32_t workspace_background_id;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900113 uint32_t surface_id_offset;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900114};
115
116struct hmi_controller {
117 struct hmi_server_setting *hmi_setting;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900118 /* List of struct hmi_controller_layer */
119 struct wl_list base_layer_list;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900120 struct wl_list application_layer_list;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900121 struct hmi_controller_layer workspace_background_layer;
122 struct hmi_controller_layer workspace_layer;
123 enum ivi_hmi_controller_layout_mode layout_mode;
124
125 struct hmi_controller_fade workspace_fade;
126
127 int32_t workspace_count;
128 struct wl_array ui_widgets;
129 int32_t is_initialized;
130
131 struct weston_compositor *compositor;
132 struct wl_listener destroy_listener;
133
Ucan, Emre (ADITG/SW1)67f0aa82016-04-04 08:05:18 +0000134 struct wl_listener surface_removed;
Ucan, Emre (ADITG/SW1)c49aa5a2016-04-04 08:05:20 +0000135 struct wl_listener surface_configured;
Michael Teyfele894b3e2018-04-09 14:14:50 +0200136 struct wl_listener desktop_surface_configured;
Ucan, Emre (ADITG/SW1)970f8312016-04-04 08:05:09 +0000137
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900138 struct wl_client *user_interface;
139 struct ui_setting ui_setting;
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900140
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000141 struct weston_output * workspace_background_output;
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900142 int32_t screen_num;
Emre Ucana9db8d72018-01-25 14:36:11 +0100143
144 const struct ivi_layout_interface *interface;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900145};
146
147struct launcher_info {
148 uint32_t surface_id;
149 uint32_t workspace_id;
150 int32_t index;
151};
152
153/*****************************************************************************
154 * local functions
155 ****************************************************************************/
156static void *
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900157mem_alloc(size_t size, char *file, int32_t line)
158{
159 return fail_on_null(calloc(1, size), size, file, line);
160}
161
162#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
163
164static int32_t
165is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
166 struct ivi_layout_surface *ivisurf)
167{
Emre Ucana9db8d72018-01-25 14:36:11 +0100168 uint32_t id = hmi_ctrl->interface->get_id_of_surface(ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900169
170 uint32_t *ui_widget_id = NULL;
171 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
172 if (*ui_widget_id == id)
173 return 1;
174 }
175
176 return 0;
177}
178
179static int
180compare_launcher_info(const void *lhs, const void *rhs)
181{
182 const struct launcher_info *left = lhs;
183 const struct launcher_info *right = rhs;
184
185 if (left->workspace_id < right->workspace_id)
186 return -1;
187
188 if (left->workspace_id > right->workspace_id)
189 return 1;
190
191 if (left->index < right->index)
192 return -1;
193
194 if (left->index > right->index)
195 return 1;
196
197 return 0;
198}
199
200/**
201 * Internal methods called by mainly ivi_hmi_controller_switch_mode
202 * This reference shows 4 examples how to use ivi_layout APIs.
203 */
204static void
205mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
206 struct ivi_layout_surface **pp_surface,
207 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900208 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900209{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900210 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900211 const float surface_width = (float)layer->width * 0.25;
212 const float surface_height = (float)layer->height * 0.5;
213 int32_t surface_x = 0;
214 int32_t surface_y = 0;
215 struct ivi_layout_surface *ivisurf = NULL;
216 struct ivi_layout_surface **surfaces;
217 struct ivi_layout_surface **new_order;
218 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900219 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900220
221 int32_t i = 0;
222 int32_t surf_num = 0;
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900223 int32_t idx = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900224
225 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
226 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
227
228 for (i = 0; i < surface_length; i++) {
229 ivisurf = pp_surface[i];
230
231 /* skip ui widgets */
232 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
233 continue;
234
235 surfaces[surf_num++] = ivisurf;
236 }
237
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900238 wl_list_for_each_reverse(layer, layer_list, link) {
239 if (idx >= surf_num)
240 break;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900241
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900242 ivilayer = layer->ivilayer;
243
244 for (i = 0; i < 8; i++, idx++) {
245 if (idx >= surf_num)
246 break;
247
248 ivisurf = surfaces[idx];
249 new_order[i] = ivisurf;
250 if (i < 4) {
251 surface_x = (int32_t)(i * (surface_width));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900252 surface_y = 0;
253 } else {
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900254 surface_x = (int32_t)((i - 4) * (surface_width));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900255 surface_y = (int32_t)surface_height;
256 }
257
Emre Ucana9db8d72018-01-25 14:36:11 +0100258 hmi_ctrl->interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900259 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
260 duration);
Emre Ucana9db8d72018-01-25 14:36:11 +0100261 hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
262 hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900263 surface_x, surface_y,
264 (int32_t)surface_width,
265 (int32_t)surface_height);
266
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900267 }
Emre Ucana9db8d72018-01-25 14:36:11 +0100268 hmi_ctrl->interface->layer_set_render_order(ivilayer, new_order, i);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900269
Emre Ucana9db8d72018-01-25 14:36:11 +0100270 hmi_ctrl->interface->layer_set_transition(ivilayer,
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900271 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
272 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900273 }
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900274 for (i = idx; i < surf_num; i++)
Emre Ucana9db8d72018-01-25 14:36:11 +0100275 hmi_ctrl->interface->surface_set_visibility(surfaces[i], false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900276
277 free(surfaces);
278 free(new_order);
279}
280
281static void
282mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
283 struct ivi_layout_surface **pp_surface,
284 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900285 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900286{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900287 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900288 int32_t surface_width = layer->width / 2;
289 int32_t surface_height = layer->height;
290 struct ivi_layout_surface *ivisurf = NULL;
291
292 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
293 int32_t i = 0;
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900294 struct ivi_layout_surface **surfaces;
295 struct ivi_layout_surface **new_order;
296 struct ivi_layout_layer *ivilayer = NULL;
297 int32_t surf_num = 0;
298 int32_t idx = 0;
299
300 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
301 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900302
303 for (i = 0; i < surface_length; i++) {
304 ivisurf = pp_surface[i];
305
306 /* skip ui widgets */
307 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
308 continue;
309
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900310 surfaces[surf_num++] = ivisurf;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900311 }
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900312
313 wl_list_for_each_reverse(layer, layer_list, link) {
314 if (idx >= surf_num)
315 break;
316
317 ivilayer = layer->ivilayer;
318
319 for (i = 0; i < 2; i++, idx++) {
320 if (idx >= surf_num)
321 break;
322
323 ivisurf = surfaces[idx];
324 new_order[i] = ivisurf;
325
Emre Ucana9db8d72018-01-25 14:36:11 +0100326 hmi_ctrl->interface->surface_set_transition(ivisurf,
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900327 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
328 duration);
Emre Ucana9db8d72018-01-25 14:36:11 +0100329 hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900330
Emre Ucana9db8d72018-01-25 14:36:11 +0100331 hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900332 i * surface_width, 0,
333 surface_width,
334 surface_height);
335 }
Emre Ucana9db8d72018-01-25 14:36:11 +0100336 hmi_ctrl->interface->layer_set_render_order(ivilayer, new_order, i);
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900337 }
338
339 for (i = idx; i < surf_num; i++) {
Emre Ucana9db8d72018-01-25 14:36:11 +0100340 hmi_ctrl->interface->surface_set_transition(surfaces[i],
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900341 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
342 duration);
Emre Ucana9db8d72018-01-25 14:36:11 +0100343 hmi_ctrl->interface->surface_set_visibility(surfaces[i], false);
Nobuhiko Tanibatad156d9c2015-12-09 15:44:07 +0900344 }
345
346 free(surfaces);
347 free(new_order);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900348}
349
350static void
351mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
352 struct ivi_layout_surface **pp_surface,
353 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900354 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900355{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900356 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900357 const int32_t surface_width = layer->width;
358 const int32_t surface_height = layer->height;
359 struct ivi_layout_surface *ivisurf = NULL;
360 int32_t i = 0;
361 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
Nobuhiko Tanibataa7ffa682015-12-09 15:45:20 +0900362 int32_t surf_num = 0;
363 struct ivi_layout_surface **surfaces;
364
365 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900366
367 for (i = 0; i < surface_length; i++) {
368 ivisurf = pp_surface[i];
369
370 /* skip ui widgets */
371 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
372 continue;
373
Nobuhiko Tanibataa7ffa682015-12-09 15:45:20 +0900374 surfaces[surf_num++] = ivisurf;
375 }
Emre Ucana9db8d72018-01-25 14:36:11 +0100376 hmi_ctrl->interface->layer_set_render_order(layer->ivilayer, surfaces, surf_num);
Nobuhiko Tanibataa7ffa682015-12-09 15:45:20 +0900377
378 for (i = 0; i < surf_num; i++) {
379 ivisurf = surfaces[i];
380
381 if ((i > 0) && (i < hmi_ctrl->screen_num)) {
382 layer = wl_container_of(layer->link.prev, layer, link);
Emre Ucana9db8d72018-01-25 14:36:11 +0100383 hmi_ctrl->interface->layer_set_render_order(layer->ivilayer, &ivisurf, 1);
Nobuhiko Tanibataa7ffa682015-12-09 15:45:20 +0900384 }
385
Emre Ucana9db8d72018-01-25 14:36:11 +0100386 hmi_ctrl->interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900387 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
388 duration);
Emre Ucana9db8d72018-01-25 14:36:11 +0100389 hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
390 hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900391 surface_width,
392 surface_height);
393 }
Nobuhiko Tanibataa7ffa682015-12-09 15:45:20 +0900394
395 free(surfaces);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900396}
397
398static void
399mode_random_replace(struct hmi_controller *hmi_ctrl,
400 struct ivi_layout_surface **pp_surface,
401 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900402 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900403{
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900404 struct hmi_controller_layer *application_layer = NULL;
405 struct hmi_controller_layer **layers = NULL;
406 int32_t surface_width = 0;
407 int32_t surface_height = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900408 int32_t surface_x = 0;
409 int32_t surface_y = 0;
410 struct ivi_layout_surface *ivisurf = NULL;
411 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
412 int32_t i = 0;
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900413 int32_t layer_idx = 0;
414
415 layers = MEM_ALLOC(sizeof(*layers) * hmi_ctrl->screen_num);
416
417 wl_list_for_each(application_layer, layer_list, link) {
418 layers[layer_idx] = application_layer;
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900419 layer_idx++;
420 }
421
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900422 for (i = 0; i < surface_length; i++) {
423 ivisurf = pp_surface[i];
424
425 /* skip ui widgets */
426 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
427 continue;
428
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900429 /* surface determined at random a layer that belongs */
430 layer_idx = rand() % hmi_ctrl->screen_num;
431
Emre Ucana9db8d72018-01-25 14:36:11 +0100432 hmi_ctrl->interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900433 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
434 duration);
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900435
Emre Ucana9db8d72018-01-25 14:36:11 +0100436 hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900437
438 surface_width = (int32_t)(layers[layer_idx]->width * 0.25f);
439 surface_height = (int32_t)(layers[layer_idx]->height * 0.25f);
440 surface_x = rand() % (layers[layer_idx]->width - surface_width);
441 surface_y = rand() % (layers[layer_idx]->height - surface_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900442
Emre Ucana9db8d72018-01-25 14:36:11 +0100443 hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900444 surface_x,
445 surface_y,
446 surface_width,
447 surface_height);
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900448
Emre Ucana9db8d72018-01-25 14:36:11 +0100449 hmi_ctrl->interface->layer_add_surface(layers[layer_idx]->ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900450 }
Nobuhiko Tanibata1c2201b2015-12-09 15:45:52 +0900451
452 free(layers);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900453}
454
455static int32_t
456has_application_surface(struct hmi_controller *hmi_ctrl,
457 struct ivi_layout_surface **pp_surface,
458 int32_t surface_length)
459{
460 struct ivi_layout_surface *ivisurf = NULL;
461 int32_t i = 0;
462
463 for (i = 0; i < surface_length; i++) {
464 ivisurf = pp_surface[i];
465
466 /* skip ui widgets */
467 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
468 continue;
469
470 return 1;
471 }
472
473 return 0;
474}
475
476/**
477 * Supports 4 example to layout of application ivi_surfaces;
478 * tiling, side by side, fullscreen, and random.
479 */
480static void
481switch_mode(struct hmi_controller *hmi_ctrl,
482 enum ivi_hmi_controller_layout_mode layout_mode)
483{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900484 struct wl_list *layer = &hmi_ctrl->application_layer_list;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900485 struct ivi_layout_surface **pp_surface = NULL;
486 int32_t surface_length = 0;
487 int32_t ret = 0;
488
489 if (!hmi_ctrl->is_initialized)
490 return;
491
492 hmi_ctrl->layout_mode = layout_mode;
493
Emre Ucana9db8d72018-01-25 14:36:11 +0100494 ret = hmi_ctrl->interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900495 assert(!ret);
496
497 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
498 free(pp_surface);
499 pp_surface = NULL;
500 return;
501 }
502
503 switch (layout_mode) {
504 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
505 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
506 layer);
507 break;
508 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
509 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
510 surface_length, layer);
511 break;
512 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
513 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
514 layer);
515 break;
516 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
517 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
518 layer);
519 break;
520 }
521
Emre Ucana9db8d72018-01-25 14:36:11 +0100522 hmi_ctrl->interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900523 free(pp_surface);
524}
525
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900526/**
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900527 * Internal method for transition
528 */
529static void
530hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
531 struct hmi_controller_fade *fade)
532{
533 double tint = is_fade_in ? 1.0 : 0.0;
534 struct link_layer *linklayer = NULL;
535 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
536
537 fade->is_fade_in = is_fade_in;
538
539 wl_list_for_each(linklayer, &fade->layer_list, link) {
Emre Ucana9db8d72018-01-25 14:36:11 +0100540 hmi_ctrl->interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900541 IVI_LAYOUT_TRANSITION_LAYER_FADE,
542 duration);
Emre Ucana9db8d72018-01-25 14:36:11 +0100543 hmi_ctrl->interface->layer_set_fade_info(linklayer->layout_layer,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900544 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900545 }
546}
547
548/**
549 * Internal method to create ivi_layer with hmi_controller_layer and
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000550 * add to a weston_output
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900551 */
552static void
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000553create_layer(struct weston_output *output,
Emre Ucana9db8d72018-01-25 14:36:11 +0100554 struct hmi_controller_layer *layer,
555 struct hmi_controller *hmi_ctrl)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900556{
557 int32_t ret = 0;
558
559 layer->ivilayer =
Emre Ucana9db8d72018-01-25 14:36:11 +0100560 hmi_ctrl->interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900561 layer->width,
562 layer->height);
563 assert(layer->ivilayer != NULL);
564
Emre Ucana9db8d72018-01-25 14:36:11 +0100565 ret = hmi_ctrl->interface->screen_add_layer(output, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900566 assert(!ret);
567
Emre Ucana9db8d72018-01-25 14:36:11 +0100568 ret = hmi_ctrl->interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900569 layer->x, layer->y,
570 layer->width,
571 layer->height);
572 assert(!ret);
573
Emre Ucana9db8d72018-01-25 14:36:11 +0100574 ret = hmi_ctrl->interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900575 assert(!ret);
576}
577
578/**
579 * Internal set notification
580 */
581static void
Ucan, Emre (ADITG/SW1)67f0aa82016-04-04 08:05:18 +0000582set_notification_remove_surface(struct wl_listener *listener, void *data)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900583{
Ucan, Emre (ADITG/SW1)67f0aa82016-04-04 08:05:18 +0000584 struct hmi_controller *hmi_ctrl =
585 wl_container_of(listener, hmi_ctrl,
586 surface_removed);
587 (void)data;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900588
589 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
590}
591
592static void
Ucan, Emre (ADITG/SW1)c49aa5a2016-04-04 08:05:20 +0000593set_notification_configure_surface(struct wl_listener *listener, void *data)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900594{
Ucan, Emre (ADITG/SW1)c49aa5a2016-04-04 08:05:20 +0000595 struct hmi_controller *hmi_ctrl =
596 wl_container_of(listener, hmi_ctrl,
597 surface_configured);
598 struct ivi_layout_surface *ivisurf = data;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900599 struct hmi_controller_layer *layer_link = NULL;
600 struct ivi_layout_layer *application_layer = NULL;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900601 struct weston_surface *surface;
Wataru Natsume9d8b4412016-03-03 19:56:52 +0900602 struct ivi_layout_surface **ivisurfs = NULL;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900603 int32_t length = 0;
604 int32_t i;
605
606 /* return if the surface is not application content */
607 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
608 return;
609 }
610
611 /*
612 * if application changes size of wl_buffer. The source rectangle shall be
613 * fit to the size.
614 */
Emre Ucana9db8d72018-01-25 14:36:11 +0100615 surface = hmi_ctrl->interface->surface_get_weston_surface(ivisurf);
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900616 if (surface) {
Emre Ucana9db8d72018-01-25 14:36:11 +0100617 hmi_ctrl->interface->surface_set_source_rectangle(
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900618 ivisurf, 0, 0, surface->width,
619 surface->height);
620 }
621
622 /*
623 * search if the surface is already added to layer.
624 * If not yet, it is newly invoded application to go to switch_mode.
625 */
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900626 wl_list_for_each_reverse(layer_link, &hmi_ctrl->application_layer_list, link) {
627 application_layer = layer_link->ivilayer;
Emre Ucana9db8d72018-01-25 14:36:11 +0100628 hmi_ctrl->interface->get_surfaces_on_layer(application_layer,
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900629 &length, &ivisurfs);
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900630 for (i = 0; i < length; i++) {
631 if (ivisurf == ivisurfs[i]) {
632 /*
633 * if it is non new invoked application, just call
634 * commit_changes to apply source_rectangle.
635 */
Emre Ucana9db8d72018-01-25 14:36:11 +0100636 hmi_ctrl->interface->commit_changes();
Wataru Natsume9d8b4412016-03-03 19:56:52 +0900637 free(ivisurfs);
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900638 return;
639 }
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900640 }
Wataru Natsume9d8b4412016-03-03 19:56:52 +0900641 free(ivisurfs);
642 ivisurfs = NULL;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900643 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900644
645 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
646}
647
Michael Teyfele894b3e2018-04-09 14:14:50 +0200648static void
649set_notification_configure_desktop_surface(struct wl_listener *listener, void *data)
650{
651 struct hmi_controller *hmi_ctrl =
652 wl_container_of(listener, hmi_ctrl,
653 desktop_surface_configured);
654 struct ivi_layout_surface *ivisurf = data;
655 struct hmi_controller_layer *layer_link =
656 wl_container_of(hmi_ctrl->application_layer_list.prev,
657 layer_link,
658 link);
659 struct ivi_layout_layer *application_layer = layer_link->ivilayer;
660 struct weston_surface *surface;
661 int32_t ret = 0;
662
663 /* skip ui widgets */
664 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
665 return;
666
667 ret = hmi_ctrl->interface->layer_add_surface(application_layer, ivisurf);
668 assert(!ret);
669
670 /*
671 * if application changes size of wl_buffer. The source rectangle shall be
672 * fit to the size.
673 */
674 surface = hmi_ctrl->interface->surface_get_weston_surface(ivisurf);
675 if (surface) {
676 hmi_ctrl->interface->surface_set_source_rectangle(ivisurf, 0,
677 0, surface->width, surface->height);
678 }
679
680 hmi_ctrl->interface->commit_changes();
681 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
682}
683
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900684/**
685 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
686 * corresponding ivi_layer are defined in weston.ini. Default scene graph
687 * of ivi_layers are initialized in hmi_controller_create
688 */
689static struct hmi_server_setting *
690hmi_server_setting_create(struct weston_compositor *ec)
691{
692 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
Giulio Camuffod52f3b72016-06-02 21:48:11 +0300693 struct weston_config *config = wet_get_config(ec);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900694 struct weston_config_section *shell_section = NULL;
Daniel Stone78a42112016-11-28 15:54:06 +0000695 char *ivi_ui_config;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900696
697 shell_section = weston_config_get_section(config, "ivi-shell",
698 NULL, NULL);
699
700 weston_config_section_get_uint(shell_section, "base-layer-id",
701 &setting->base_layer_id, 1000);
702
703 weston_config_section_get_uint(shell_section,
704 "workspace-background-layer-id",
705 &setting->workspace_background_layer_id,
706 2000);
707
708 weston_config_section_get_uint(shell_section, "workspace-layer-id",
709 &setting->workspace_layer_id, 3000);
710
711 weston_config_section_get_uint(shell_section, "application-layer-id",
712 &setting->application_layer_id, 4000);
713
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900714 weston_config_section_get_uint(shell_section, "base-layer-id-offset",
715 &setting->base_layer_id_offset, 10000);
716
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900717 weston_config_section_get_uint(shell_section, "transition-duration",
718 &setting->transition_duration, 300);
719
720 setting->panel_height = 70;
721
722 weston_config_section_get_string(shell_section,
723 "ivi-shell-user-interface",
Daniel Stone78a42112016-11-28 15:54:06 +0000724 &ivi_ui_config, NULL);
725 if (ivi_ui_config && ivi_ui_config[0] != '/') {
Marius Vlad64fbd0f2018-12-15 15:51:57 +0200726 setting->ivi_homescreen = wet_get_libexec_path(ivi_ui_config);
Daniel Stone78a42112016-11-28 15:54:06 +0000727 if (setting->ivi_homescreen)
728 free(ivi_ui_config);
729 else
730 setting->ivi_homescreen = ivi_ui_config;
731 } else {
732 setting->ivi_homescreen = ivi_ui_config;
733 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900734
735 return setting;
736}
737
738static void
739hmi_controller_destroy(struct wl_listener *listener, void *data)
740{
741 struct link_layer *link = NULL;
742 struct link_layer *next = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900743 struct hmi_controller_layer *ctrl_layer_link = NULL;
744 struct hmi_controller_layer *ctrl_layer_next = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900745 struct hmi_controller *hmi_ctrl =
746 container_of(listener, struct hmi_controller, destroy_listener);
747
748 wl_list_for_each_safe(link, next,
749 &hmi_ctrl->workspace_fade.layer_list, link) {
750 wl_list_remove(&link->link);
751 free(link);
752 }
753
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900754 /* clear base_layer_list */
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900755 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
756 &hmi_ctrl->base_layer_list, link) {
757 wl_list_remove(&ctrl_layer_link->link);
758 free(ctrl_layer_link);
759 }
760
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900761 /* clear application_layer_list */
762 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
763 &hmi_ctrl->application_layer_list, link) {
764 wl_list_remove(&ctrl_layer_link->link);
765 free(ctrl_layer_link);
766 }
767
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900768 wl_array_release(&hmi_ctrl->ui_widgets);
769 free(hmi_ctrl->hmi_setting);
770 free(hmi_ctrl);
771}
772
773/**
774 * This is a starting method called from module_init.
775 * This sets up scene graph of ivi_layers; base, application, workspace
776 * background, and workspace. These ivi_layers are created/added to
777 * ivi_screen in create_layer
778 *
779 * base: to group ivi_surfaces of panel and background
780 * application: to group ivi_surfaces of ivi_applications
781 * workspace background: to group a ivi_surface of background in workspace
782 * workspace: to group ivi_surfaces for launching ivi_applications
783 *
784 * ivi_layers of workspace background and workspace is set to invisible at
785 * first. The properties of it is updated with animation when
786 * ivi_hmi_controller_home is requested.
787 */
788static struct hmi_controller *
Emre Ucanffaf09e2018-01-25 14:36:12 +0100789hmi_controller_create(struct weston_compositor *ec)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900790{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900791 struct link_layer *tmp_link_layer = NULL;
792 int32_t panel_height = 0;
Emre Ucanffaf09e2018-01-25 14:36:12 +0100793 struct hmi_controller *hmi_ctrl;
794 const struct ivi_layout_interface *interface;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900795 struct hmi_controller_layer *base_layer = NULL;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900796 struct hmi_controller_layer *application_layer = NULL;
Ucan, Emre (ADITG/SW1)ff6a9f82016-03-17 15:30:35 +0000797 struct weston_output *output;
Emre Ucanffaf09e2018-01-25 14:36:12 +0100798 int32_t i;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900799
Emre Ucanffaf09e2018-01-25 14:36:12 +0100800 interface = ivi_layout_get_api(ec);
801
802 if (!interface) {
803 weston_log("Cannot use ivi_layout_interface.\n");
804 return NULL;
805 }
806
807 hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
808 i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900809
810 wl_array_init(&hmi_ctrl->ui_widgets);
811 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
812 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
813 hmi_ctrl->compositor = ec;
Ucan, Emre (ADITG/SW1)3a8521e2016-03-17 15:30:39 +0000814 hmi_ctrl->screen_num = wl_list_length(&ec->output_list);
Emre Ucana9db8d72018-01-25 14:36:11 +0100815 hmi_ctrl->interface = interface;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900816
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900817 /* init base ivi_layer*/
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900818 wl_list_init(&hmi_ctrl->base_layer_list);
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000819 wl_list_for_each(output, &ec->output_list, link) {
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900820 base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
821 base_layer->x = 0;
822 base_layer->y = 0;
Ucan, Emre (ADITG/SW1)ff6a9f82016-03-17 15:30:35 +0000823 base_layer->width = output->current_mode->width;
824 base_layer->height = output->current_mode->height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900825 base_layer->id_layer =
826 hmi_ctrl->hmi_setting->base_layer_id +
827 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
828 wl_list_insert(&hmi_ctrl->base_layer_list, &base_layer->link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900829
Emre Ucana9db8d72018-01-25 14:36:11 +0100830 create_layer(output, base_layer, hmi_ctrl);
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000831 i++;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900832 }
833
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000834 i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900835 panel_height = hmi_ctrl->hmi_setting->panel_height;
836
837 /* init application ivi_layer */
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900838 wl_list_init(&hmi_ctrl->application_layer_list);
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000839 wl_list_for_each(output, &ec->output_list, link) {
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900840 application_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
841 application_layer->x = 0;
842 application_layer->y = 0;
Ucan, Emre (ADITG/SW1)ff6a9f82016-03-17 15:30:35 +0000843 application_layer->width = output->current_mode->width;
844 application_layer->height = output->current_mode->height - panel_height;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900845 application_layer->id_layer =
846 hmi_ctrl->hmi_setting->application_layer_id +
847 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
848 wl_list_insert(&hmi_ctrl->application_layer_list, &application_layer->link);
849
Emre Ucana9db8d72018-01-25 14:36:11 +0100850 create_layer(output, application_layer, hmi_ctrl);
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000851 i++;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900852 }
853
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900854 /* init workspace background ivi_layer */
Ucan, Emre (ADITG/SW1)273874e2016-03-17 15:30:42 +0000855 output = wl_container_of(ec->output_list.next, output, link);
856 hmi_ctrl->workspace_background_output = output;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900857 hmi_ctrl->workspace_background_layer.x = 0;
858 hmi_ctrl->workspace_background_layer.y = 0;
Ucan, Emre (ADITG/SW1)ff6a9f82016-03-17 15:30:35 +0000859 hmi_ctrl->workspace_background_layer.width =
860 output->current_mode->width;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900861 hmi_ctrl->workspace_background_layer.height =
Ucan, Emre (ADITG/SW1)ff6a9f82016-03-17 15:30:35 +0000862 output->current_mode->height - panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900863
864 hmi_ctrl->workspace_background_layer.id_layer =
865 hmi_ctrl->hmi_setting->workspace_background_layer_id;
866
Emre Ucana9db8d72018-01-25 14:36:11 +0100867 create_layer(output, &hmi_ctrl->workspace_background_layer, hmi_ctrl);
868 hmi_ctrl->interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900869 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Emre Ucana9db8d72018-01-25 14:36:11 +0100870 hmi_ctrl->interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900871 hmi_ctrl->workspace_background_layer.ivilayer, false);
872
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900873
874 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
875 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900876 tmp_link_layer->layout_layer =
877 hmi_ctrl->workspace_background_layer.ivilayer;
878 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
879 &tmp_link_layer->link);
880
Ucan, Emre (ADITG/SW1)67f0aa82016-04-04 08:05:18 +0000881 hmi_ctrl->surface_removed.notify = set_notification_remove_surface;
Emre Ucana9db8d72018-01-25 14:36:11 +0100882 hmi_ctrl->interface->add_listener_remove_surface(&hmi_ctrl->surface_removed);
Ucan, Emre (ADITG/SW1)c49aa5a2016-04-04 08:05:20 +0000883
884 hmi_ctrl->surface_configured.notify = set_notification_configure_surface;
Emre Ucana9db8d72018-01-25 14:36:11 +0100885 hmi_ctrl->interface->add_listener_configure_surface(&hmi_ctrl->surface_configured);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900886
Michael Teyfele894b3e2018-04-09 14:14:50 +0200887 hmi_ctrl->desktop_surface_configured.notify = set_notification_configure_desktop_surface;
888 hmi_ctrl->interface->add_listener_configure_desktop_surface(&hmi_ctrl->desktop_surface_configured);
889
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900890 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
891 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
892 &hmi_ctrl->destroy_listener);
893
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900894 return hmi_ctrl;
895}
896
897/**
898 * Implementations of ivi-hmi-controller.xml
899 */
900
901/**
902 * A ivi_surface drawing background is identified by id_surface.
903 * Properties of the ivi_surface is set by using ivi_layout APIs according to
904 * the scene graph of UI defined in hmi_controller_create.
905 *
906 * UI ivi_layer is used to add this ivi_surface.
907 */
908static void
909ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
910 uint32_t id_surface)
911{
912 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900913 struct hmi_controller_layer *base_layer = NULL;
914 struct ivi_layout_layer *ivilayer = NULL;
Ucan, Emre (ADITG/SW1)783cb4d2016-03-17 14:36:51 +0000915 int32_t dstx;
916 int32_t dsty;
917 int32_t width;
918 int32_t height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900919 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900920 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900921
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900922 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
923 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
924 sizeof(*add_surface_id));
925 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Ucan, Emre (ADITG/SW1)783cb4d2016-03-17 14:36:51 +0000926 dstx = base_layer->x;
927 dsty = base_layer->y;
928 width = base_layer->width;
929 height = base_layer->height;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900930 ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900931
Emre Ucana9db8d72018-01-25 14:36:11 +0100932 ivisurf = hmi_ctrl->interface->get_surface_from_id(*add_surface_id);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900933 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900934
Emre Ucana9db8d72018-01-25 14:36:11 +0100935 ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900936 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900937
Emre Ucana9db8d72018-01-25 14:36:11 +0100938 ret = hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900939 dstx, dsty, width, height);
940 assert(!ret);
941
Emre Ucana9db8d72018-01-25 14:36:11 +0100942 ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900943 assert(!ret);
944
945 i++;
946 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900947}
948
949/**
950 * A ivi_surface drawing panel is identified by id_surface.
951 * Properties of the ivi_surface is set by using ivi_layout APIs according to
952 * the scene graph of UI defined in hmi_controller_create.
953 *
954 * UI ivi_layer is used to add this ivi_surface.
955 */
956static void
957ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
958 uint32_t id_surface)
959{
960 struct ivi_layout_surface *ivisurf = NULL;
Ucan, Emre (ADITG/SW1)c6459c492016-03-17 14:36:52 +0000961 struct hmi_controller_layer *base_layer;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900962 struct ivi_layout_layer *ivilayer = NULL;
Ucan, Emre (ADITG/SW1)c6459c492016-03-17 14:36:52 +0000963 int32_t width;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900964 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900965 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900966 const int32_t dstx = 0;
967 int32_t dsty = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900968 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900969
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900970 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
971 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
972 sizeof(*add_surface_id));
973 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900974
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900975 ivilayer = base_layer->ivilayer;
Emre Ucana9db8d72018-01-25 14:36:11 +0100976 ivisurf = hmi_ctrl->interface->get_surface_from_id(*add_surface_id);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900977 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900978
Emre Ucana9db8d72018-01-25 14:36:11 +0100979 ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900980 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900981
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900982 dsty = base_layer->height - panel_height;
Ucan, Emre (ADITG/SW1)c6459c492016-03-17 14:36:52 +0000983 width = base_layer->width;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900984
Emre Ucana9db8d72018-01-25 14:36:11 +0100985 ret = hmi_ctrl->interface->surface_set_destination_rectangle(
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900986 ivisurf, dstx, dsty, width, panel_height);
987 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900988
Emre Ucana9db8d72018-01-25 14:36:11 +0100989 ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900990 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900991
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900992 i++;
993 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900994}
995
996/**
997 * A ivi_surface drawing buttons in panel is identified by id_surface.
998 * It can set several buttons. Properties of the ivi_surface is set by
999 * using ivi_layout APIs according to the scene graph of UI defined in
1000 * hmi_controller_create. Additionally, the position of it is shifted to
1001 * right when new one is requested.
1002 *
1003 * UI ivi_layer is used to add these ivi_surfaces.
1004 */
1005static void
1006ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
1007 uint32_t id_surface, int32_t number)
1008{
1009 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001010 struct hmi_controller_layer *base_layer =
1011 wl_container_of(hmi_ctrl->base_layer_list.prev,
1012 base_layer,
1013 link);
1014 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001015 const int32_t width = 48;
1016 const int32_t height = 48;
1017 int32_t ret = 0;
1018 int32_t panel_height = 0;
1019 int32_t dstx = 0;
1020 int32_t dsty = 0;
1021 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1022 sizeof(*add_surface_id));
1023 *add_surface_id = id_surface;
1024
Emre Ucana9db8d72018-01-25 14:36:11 +01001025 ivisurf = hmi_ctrl->interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001026 assert(ivisurf != NULL);
1027
Emre Ucana9db8d72018-01-25 14:36:11 +01001028 ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001029 assert(!ret);
1030
1031 panel_height = hmi_ctrl->hmi_setting->panel_height;
1032
1033 dstx = (60 * number) + 15;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001034 dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001035
Emre Ucana9db8d72018-01-25 14:36:11 +01001036 ret = hmi_ctrl->interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001037 ivisurf,dstx, dsty, width, height);
1038 assert(!ret);
1039
Emre Ucana9db8d72018-01-25 14:36:11 +01001040 ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001041 assert(!ret);
1042}
1043
1044/**
1045 * A ivi_surface drawing home button in panel is identified by id_surface.
1046 * Properties of the ivi_surface is set by using ivi_layout APIs according to
1047 * the scene graph of UI defined in hmi_controller_create.
1048 *
1049 * UI ivi_layer is used to add these ivi_surfaces.
1050 */
1051static void
1052ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
1053 uint32_t id_surface)
1054{
1055 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001056 struct hmi_controller_layer *base_layer =
1057 wl_container_of(hmi_ctrl->base_layer_list.prev,
1058 base_layer,
1059 link);
1060 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001061 int32_t ret = 0;
1062 int32_t size = 48;
1063 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001064 const int32_t dstx = (base_layer->width - size) / 2;
1065 const int32_t dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001066
1067 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1068 sizeof(*add_surface_id));
1069 *add_surface_id = id_surface;
1070
Emre Ucana9db8d72018-01-25 14:36:11 +01001071 ivisurf = hmi_ctrl->interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001072 assert(ivisurf != NULL);
1073
Emre Ucana9db8d72018-01-25 14:36:11 +01001074 ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001075 assert(!ret);
1076
Emre Ucana9db8d72018-01-25 14:36:11 +01001077 ret = hmi_ctrl->interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001078 ivisurf, dstx, dsty, size, size);
1079 assert(!ret);
1080
Emre Ucana9db8d72018-01-25 14:36:11 +01001081 ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001082 assert(!ret);
1083}
1084
1085/**
1086 * A ivi_surface drawing background of workspace is identified by id_surface.
1087 * Properties of the ivi_surface is set by using ivi_layout APIs according to
1088 * the scene graph of UI defined in hmi_controller_create.
1089 *
1090 * A ivi_layer of workspace_background is used to add this ivi_surface.
1091 */
1092static void
1093ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
1094 uint32_t id_surface)
1095{
1096 struct ivi_layout_surface *ivisurf = NULL;
1097 struct ivi_layout_layer *ivilayer = NULL;
1098 const int32_t width = hmi_ctrl->workspace_background_layer.width;
1099 const int32_t height = hmi_ctrl->workspace_background_layer.height;
1100 int32_t ret = 0;
1101
1102 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1103 sizeof(*add_surface_id));
1104 *add_surface_id = id_surface;
1105 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
1106
Emre Ucana9db8d72018-01-25 14:36:11 +01001107 ivisurf = hmi_ctrl->interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001108 assert(ivisurf != NULL);
1109
Emre Ucana9db8d72018-01-25 14:36:11 +01001110 ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001111 assert(!ret);
1112
Emre Ucana9db8d72018-01-25 14:36:11 +01001113 ret = hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001114 0, 0, width, height);
1115 assert(!ret);
1116
Emre Ucana9db8d72018-01-25 14:36:11 +01001117 ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001118 assert(!ret);
1119}
1120
1121/**
1122 * A list of ivi_surfaces drawing launchers in workspace is identified by
1123 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
1124 * APIs according to the scene graph of UI defined in hmi_controller_create.
1125 *
1126 * The workspace can have several pages to group ivi_surfaces of launcher.
1127 * Each call of this interface increments a number of page to add a group
1128 * of ivi_surfaces
1129 */
1130static void
1131ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
1132 int32_t icon_size)
1133{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001134 int32_t minspace_x = 10;
1135 int32_t minspace_y = minspace_x;
1136
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001137 int32_t width = hmi_ctrl->workspace_background_layer.width;
1138 int32_t height = hmi_ctrl->workspace_background_layer.height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001139
1140 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
1141 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
1142 float fcell_size_x = icon_size + space_x;
1143
1144 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
1145 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
1146 float fcell_size_y = icon_size + space_y;
1147
1148 struct weston_config *config = NULL;
1149 struct weston_config_section *section = NULL;
1150 const char *name = NULL;
1151 int launcher_count = 0;
1152 struct wl_array launchers;
1153 int32_t nx = 0;
1154 int32_t ny = 0;
1155 int32_t prev = -1;
1156 struct launcher_info *data = NULL;
1157
1158 uint32_t surfaceid = 0;
1159 uint32_t workspaceid = 0;
1160 struct launcher_info *info = NULL;
1161
1162 int32_t x = 0;
1163 int32_t y = 0;
1164 int32_t ret = 0;
1165 struct ivi_layout_surface* layout_surface = NULL;
1166 uint32_t *add_surface_id = NULL;
1167
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001168 struct link_layer *tmp_link_layer = NULL;
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001169
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001170 if (0 == x_count)
1171 x_count = 1;
1172
1173 if (0 == y_count)
1174 y_count = 1;
1175
Giulio Camuffod52f3b72016-06-02 21:48:11 +03001176 config = wet_get_config(hmi_ctrl->compositor);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001177 if (!config)
1178 return;
1179
1180 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1181 if (!section)
1182 return;
1183
1184 wl_array_init(&launchers);
1185
1186 while (weston_config_next_section(config, &section, &name)) {
1187 surfaceid = 0;
1188 workspaceid = 0;
1189 info = NULL;
1190 if (0 != strcmp(name, "ivi-launcher"))
1191 continue;
1192
1193 if (0 != weston_config_section_get_uint(section, "icon-id",
1194 &surfaceid, 0))
1195 continue;
1196
1197 if (0 != weston_config_section_get_uint(section,
1198 "workspace-id",
1199 &workspaceid, 0))
1200 continue;
1201
1202 info = wl_array_add(&launchers, sizeof(*info));
1203
1204 if (info) {
1205 info->surface_id = surfaceid;
1206 info->workspace_id = workspaceid;
1207 info->index = launcher_count;
1208 ++launcher_count;
1209 }
1210 }
1211
1212 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1213 compare_launcher_info);
1214
1215 wl_array_for_each(data, &launchers) {
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001216 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1217 sizeof(*add_surface_id));
1218
1219 *add_surface_id = data->surface_id;
1220
1221 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1222 nx = 0;
1223 ny = 0;
1224 prev = data->workspace_id;
1225
1226 if (0 <= prev)
1227 hmi_ctrl->workspace_count++;
1228 }
1229
1230 if (y_count == ny) {
1231 ny = 0;
1232 hmi_ctrl->workspace_count++;
1233 }
1234
1235 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1236 y = ny * fcell_size_y + space_y;
1237
1238 layout_surface =
Emre Ucana9db8d72018-01-25 14:36:11 +01001239 hmi_ctrl->interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001240 assert(layout_surface);
1241
Emre Ucana9db8d72018-01-25 14:36:11 +01001242 ret = hmi_ctrl->interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001243 layout_surface, x, y, icon_size, icon_size);
1244 assert(!ret);
1245
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001246 nx++;
1247
1248 if (x_count == nx) {
1249 ny++;
1250 nx = 0;
1251 }
1252 }
1253
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001254 /* init workspace ivi_layer */
1255 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1256 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1257 hmi_ctrl->workspace_layer.width =
1258 hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1259 hmi_ctrl->workspace_layer.height =
1260 hmi_ctrl->workspace_background_layer.height;
1261 hmi_ctrl->workspace_layer.id_layer =
1262 hmi_ctrl->hmi_setting->workspace_layer_id;
1263
Emre Ucana9db8d72018-01-25 14:36:11 +01001264 create_layer(hmi_ctrl->workspace_background_output,
1265 &hmi_ctrl->workspace_layer, hmi_ctrl);
1266 hmi_ctrl->interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1267 hmi_ctrl->interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001268 false);
1269
1270 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1271 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1272 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1273 &tmp_link_layer->link);
1274
1275 /* Add surface to layer */
1276 wl_array_for_each(data, &launchers) {
1277 layout_surface =
Emre Ucana9db8d72018-01-25 14:36:11 +01001278 hmi_ctrl->interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001279 assert(layout_surface);
1280
Emre Ucana9db8d72018-01-25 14:36:11 +01001281 ret = hmi_ctrl->interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001282 layout_surface);
1283 assert(!ret);
1284
Emre Ucana9db8d72018-01-25 14:36:11 +01001285 ret = hmi_ctrl->interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001286 assert(!ret);
1287 }
1288
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001289 wl_array_release(&launchers);
Emre Ucana9db8d72018-01-25 14:36:11 +01001290 hmi_ctrl->interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001291}
1292
1293static void
1294ivi_hmi_controller_UI_ready(struct wl_client *client,
1295 struct wl_resource *resource)
1296{
1297 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1298
1299 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1300 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1301 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1302 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1303 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1304 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1305 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1306 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Emre Ucana9db8d72018-01-25 14:36:11 +01001307 hmi_ctrl->interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001308
1309 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1310 hmi_ctrl->is_initialized = 1;
1311}
1312
1313/**
1314 * Implementation of request and event of ivi_hmi_controller_workspace_control
1315 * and controlling workspace.
1316 *
1317 * When motion of input is detected in a ivi_surface of workspace background,
1318 * ivi_hmi_controller_workspace_control shall be invoked and to start
1319 * controlling of workspace. The workspace has several pages to show several
1320 * groups of applications.
Abdur Rehmanb833d742017-01-01 19:46:34 +05001321 * The workspace is slid by using ivi-layout to select a page in layer_set_pos
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001322 * according to motion. When motion finished, e.g. touch up detected, control is
1323 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1324 */
1325struct pointer_grab {
1326 struct weston_pointer_grab grab;
1327 struct ivi_layout_layer *layer;
1328 struct wl_resource *resource;
1329};
1330
1331struct touch_grab {
1332 struct weston_touch_grab grab;
1333 struct ivi_layout_layer *layer;
1334 struct wl_resource *resource;
1335};
1336
1337struct move_grab {
1338 wl_fixed_t dst[2];
1339 wl_fixed_t rgn[2][2];
1340 double v[2];
1341 struct timespec start_time;
1342 struct timespec pre_time;
1343 wl_fixed_t start_pos[2];
1344 wl_fixed_t pos[2];
1345 int32_t is_moved;
1346};
1347
1348struct pointer_move_grab {
1349 struct pointer_grab base;
1350 struct move_grab move;
1351};
1352
1353struct touch_move_grab {
1354 struct touch_grab base;
1355 struct move_grab move;
1356 int32_t is_active;
1357};
1358
1359static void
1360pointer_grab_start(struct pointer_grab *grab,
1361 struct ivi_layout_layer *layer,
1362 const struct weston_pointer_grab_interface *interface,
1363 struct weston_pointer *pointer)
1364{
1365 grab->grab.interface = interface;
1366 grab->layer = layer;
1367 weston_pointer_start_grab(pointer, &grab->grab);
1368}
1369
1370static void
1371touch_grab_start(struct touch_grab *grab,
1372 struct ivi_layout_layer *layer,
1373 const struct weston_touch_grab_interface *interface,
1374 struct weston_touch* touch)
1375{
1376 grab->grab.interface = interface;
1377 grab->layer = layer;
1378 weston_touch_start_grab(touch, &grab->grab);
1379}
1380
1381static int32_t
1382clamp(int32_t val, int32_t min, int32_t max)
1383{
1384 if (val < min)
1385 return min;
1386
1387 if (max < val)
1388 return max;
1389
1390 return val;
1391}
1392
1393static void
1394move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1395 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1396{
1397 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1398 int32_t width = hmi_ctrl->workspace_background_layer.width;
Ucan, Emre \(ADITG/SW1\)dfc2d762016-03-04 12:50:24 +00001399 const struct ivi_layout_layer_properties *prop;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001400
1401 struct timespec time = {0};
1402 double grab_time = 0.0;
1403 double from_motion_time = 0.0;
1404 double pointer_v = 0.0;
1405 int32_t is_flick = 0;
1406 int32_t pos_x = 0;
1407 int32_t pos_y = 0;
1408 int page_no = 0;
1409 double end_pos = 0.0;
1410 uint32_t duration = 0;
1411
1412 clock_gettime(CLOCK_MONOTONIC, &time);
1413
1414 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1415 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1416
1417 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1418 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1419
1420 pointer_v = move->v[0];
1421
1422 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1423 if (200 < from_motion_time)
1424 pointer_v = 0.0;
1425
Emre Ucana9db8d72018-01-25 14:36:11 +01001426 prop = hmi_ctrl->interface->get_properties_of_layer(layer);
Ucan, Emre \(ADITG/SW1\)dfc2d762016-03-04 12:50:24 +00001427 pos_x = prop->dest_x;
1428 pos_y = prop->dest_y;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001429
1430 if (is_flick) {
1431 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1432 page_no = (-orgx + width / 2) / width;
1433
1434 if (pointer_v < 0.0)
1435 page_no++;
1436 else
1437 page_no--;
1438 } else {
1439 page_no = (-pos_x + width / 2) / width;
1440 }
1441
1442 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1443 end_pos = -page_no * width;
1444
1445 duration = hmi_ctrl->hmi_setting->transition_duration;
1446 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Emre Ucana9db8d72018-01-25 14:36:11 +01001447 hmi_ctrl->interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001448 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1449 duration);
Emre Ucana9db8d72018-01-25 14:36:11 +01001450 hmi_ctrl->interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001451 end_pos, pos_y,
Nobuhiko Tanibata4412cd12015-08-24 09:12:37 +09001452 hmi_ctrl->workspace_layer.width,
1453 hmi_ctrl->workspace_layer.height);
Emre Ucana9db8d72018-01-25 14:36:11 +01001454 hmi_ctrl->interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001455}
1456
1457static void
1458pointer_move_workspace_grab_end(struct pointer_grab *grab)
1459{
1460 struct pointer_move_grab *pnt_move_grab =
1461 (struct pointer_move_grab *)grab;
1462 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1463
1464 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1465 grab->grab.pointer->grab_x, layer);
1466
1467 weston_pointer_end_grab(grab->grab.pointer);
1468}
1469
1470static void
1471touch_move_workspace_grab_end(struct touch_grab *grab)
1472{
1473 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1474 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1475
1476 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1477 grab->grab.touch->grab_x, layer);
1478
1479 weston_touch_end_grab(grab->grab.touch);
1480}
1481
1482static void
1483pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1484{
1485}
1486
1487static void
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001488pointer_default_grab_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +02001489 const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001490 struct weston_pointer_axis_event *event)
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001491{
Peter Hutterer89b6a492016-01-18 15:58:17 +10001492 weston_pointer_send_axis(grab->pointer, time, event);
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001493}
1494
1495static void
Peter Hutterer87743e92016-01-18 16:38:22 +10001496pointer_default_grab_axis_source(struct weston_pointer_grab *grab,
1497 uint32_t source)
1498{
1499 weston_pointer_send_axis_source(grab->pointer, source);
1500}
1501
1502static void
1503pointer_default_grab_frame(struct weston_pointer_grab *grab)
1504{
1505 weston_pointer_send_frame(grab->pointer);
1506}
1507
1508static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001509move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1510{
1511 struct timespec timestamp = {0};
1512 int32_t ii = 0;
1513 double dt = 0.0;
1514
1515 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1516 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1517 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1518
1519 if (dt < 1e-6)
1520 dt = 1e-6;
1521
1522 move->pre_time = timestamp;
1523
1524 for (ii = 0; ii < 2; ii++) {
1525 wl_fixed_t prepos = move->pos[ii];
1526 move->pos[ii] = pointer[ii] + move->dst[ii];
1527
1528 if (move->pos[ii] < move->rgn[0][ii]) {
1529 move->pos[ii] = move->rgn[0][ii];
1530 move->dst[ii] = move->pos[ii] - pointer[ii];
1531 } else if (move->rgn[1][ii] < move->pos[ii]) {
1532 move->pos[ii] = move->rgn[1][ii];
1533 move->dst[ii] = move->pos[ii] - pointer[ii];
1534 }
1535
1536 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1537
1538 if (!move->is_moved &&
1539 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1540 move->is_moved = 1;
1541 }
1542}
1543
1544static void
Emre Ucana9db8d72018-01-25 14:36:11 +01001545layer_set_pos(struct hmi_controller *hmi_ctrl, struct ivi_layout_layer *layer,
1546 wl_fixed_t pos_x, wl_fixed_t pos_y)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001547{
Ucan, Emre \(ADITG/SW1\)e62bfd82016-03-04 12:50:46 +00001548 const struct ivi_layout_layer_properties *prop;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001549 int32_t layout_pos_x = 0;
1550 int32_t layout_pos_y = 0;
1551
Emre Ucana9db8d72018-01-25 14:36:11 +01001552 prop = hmi_ctrl->interface->get_properties_of_layer(layer);
Ucan, Emre \(ADITG/SW1\)e62bfd82016-03-04 12:50:46 +00001553
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001554 layout_pos_x = wl_fixed_to_int(pos_x);
1555 layout_pos_y = wl_fixed_to_int(pos_y);
Emre Ucana9db8d72018-01-25 14:36:11 +01001556 hmi_ctrl->interface->layer_set_destination_rectangle(layer,
Ucan, Emre \(ADITG/SW1\)e62bfd82016-03-04 12:50:46 +00001557 layout_pos_x, layout_pos_y, prop->dest_width, prop->dest_height);
Emre Ucana9db8d72018-01-25 14:36:11 +01001558 hmi_ctrl->interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001559}
1560
1561static void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02001562pointer_move_grab_motion(struct weston_pointer_grab *grab,
1563 const struct timespec *time,
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001564 struct weston_pointer_motion_event *event)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001565{
1566 struct pointer_move_grab *pnt_move_grab =
1567 (struct pointer_move_grab *)grab;
Emre Ucana9db8d72018-01-25 14:36:11 +01001568 struct hmi_controller *hmi_ctrl =
1569 wl_resource_get_user_data(pnt_move_grab->base.resource);
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001570 wl_fixed_t pointer_pos[2];
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001571
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001572 weston_pointer_motion_to_abs(grab->pointer, event,
1573 &pointer_pos[0], &pointer_pos[1]);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001574 move_grab_update(&pnt_move_grab->move, pointer_pos);
Emre Ucana9db8d72018-01-25 14:36:11 +01001575 layer_set_pos(hmi_ctrl, pnt_move_grab->base.layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001576 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001577 weston_pointer_move(pnt_move_grab->base.grab.pointer, event);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001578}
1579
1580static void
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +02001581touch_move_grab_motion(struct weston_touch_grab *grab,
1582 const struct timespec *time, int touch_id,
1583 wl_fixed_t x, wl_fixed_t y)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001584{
1585 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
Emre Ucana9db8d72018-01-25 14:36:11 +01001586 struct hmi_controller *hmi_ctrl =
1587 wl_resource_get_user_data(tch_move_grab->base.resource);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001588
1589 if (!tch_move_grab->is_active)
1590 return;
1591
1592 wl_fixed_t pointer_pos[2] = {
1593 grab->touch->grab_x,
1594 grab->touch->grab_y
1595 };
1596
1597 move_grab_update(&tch_move_grab->move, pointer_pos);
Emre Ucana9db8d72018-01-25 14:36:11 +01001598 layer_set_pos(hmi_ctrl, tch_move_grab->base.layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001599 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1600}
1601
1602static void
1603pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02001604 const struct timespec *time, uint32_t button,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001605 uint32_t state_w)
1606{
1607 if (BTN_LEFT == button &&
1608 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1609 struct pointer_grab *pg = (struct pointer_grab *)grab;
1610
1611 pointer_move_workspace_grab_end(pg);
1612 free(grab);
1613 }
1614}
1615
1616static void
Alexandros Frantzis9448deb2017-11-16 18:20:58 +02001617touch_nope_grab_down(struct weston_touch_grab *grab,
1618 const struct timespec *time,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001619 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1620{
1621}
1622
1623static void
Alexandros Frantzis27a51b82017-11-16 18:20:59 +02001624touch_move_workspace_grab_up(struct weston_touch_grab *grab,
1625 const struct timespec *time,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001626 int touch_id)
1627{
1628 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1629
1630 if (0 == touch_id)
1631 tch_move_grab->is_active = 0;
1632
1633 if (0 == grab->touch->num_tp) {
1634 touch_move_workspace_grab_end(&tch_move_grab->base);
1635 free(grab);
1636 }
1637}
1638
1639static void
1640pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1641{
1642 struct pointer_grab *pg = (struct pointer_grab *)grab;
1643
1644 pointer_move_workspace_grab_end(pg);
1645 free(grab);
1646}
1647
1648static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001649touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1650{
1651}
1652
1653static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001654touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1655{
1656 struct touch_grab *tg = (struct touch_grab *)grab;
1657
1658 touch_move_workspace_grab_end(tg);
1659 free(grab);
1660}
1661
1662static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1663 pointer_noop_grab_focus,
1664 pointer_move_grab_motion,
1665 pointer_move_workspace_grab_button,
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001666 pointer_default_grab_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +10001667 pointer_default_grab_axis_source,
1668 pointer_default_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001669 pointer_move_workspace_grab_cancel
1670};
1671
1672static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1673 touch_nope_grab_down,
1674 touch_move_workspace_grab_up,
1675 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001676 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001677 touch_move_workspace_grab_cancel
1678};
1679
1680enum HMI_GRAB_DEVICE {
1681 HMI_GRAB_DEVICE_NONE,
1682 HMI_GRAB_DEVICE_POINTER,
1683 HMI_GRAB_DEVICE_TOUCH
1684};
1685
1686static enum HMI_GRAB_DEVICE
1687get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1688{
Derek Foreman1281a362015-07-31 16:55:32 -05001689 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1690 struct weston_touch *touch = weston_seat_get_touch(seat);
1691
1692 if (pointer &&
1693 pointer->focus &&
1694 pointer->button_count &&
1695 pointer->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001696 return HMI_GRAB_DEVICE_POINTER;
1697
Derek Foreman1281a362015-07-31 16:55:32 -05001698 if (touch &&
1699 touch->focus &&
1700 touch->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001701 return HMI_GRAB_DEVICE_TOUCH;
1702
1703 return HMI_GRAB_DEVICE_NONE;
1704}
1705
1706static void
1707move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1708 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1709 struct wl_resource* resource)
1710{
1711 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1712 move->pre_time = move->start_time;
1713 move->pos[0] = start_pos[0];
1714 move->pos[1] = start_pos[1];
1715 move->start_pos[0] = start_pos[0];
1716 move->start_pos[1] = start_pos[1];
1717 move->dst[0] = start_pos[0] - grab_pos[0];
1718 move->dst[1] = start_pos[1] - grab_pos[1];
1719 memcpy(move->rgn, rgn, sizeof(move->rgn));
1720}
1721
1722static void
1723move_grab_init_workspace(struct move_grab* move,
1724 wl_fixed_t grab_x, wl_fixed_t grab_y,
1725 struct wl_resource *resource)
1726{
1727 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1728 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
Ucan, Emre \(ADITG/SW1\)dfc2d762016-03-04 12:50:24 +00001729 const struct ivi_layout_layer_properties *prop;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001730 int32_t workspace_count = hmi_ctrl->workspace_count;
1731 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1732 int32_t layer_pos_x = 0;
1733 int32_t layer_pos_y = 0;
1734 wl_fixed_t start_pos[2] = {0};
1735 wl_fixed_t rgn[2][2] = {{0}};
1736 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1737
Emre Ucana9db8d72018-01-25 14:36:11 +01001738 prop = hmi_ctrl->interface->get_properties_of_layer(layer);
Ucan, Emre \(ADITG/SW1\)dfc2d762016-03-04 12:50:24 +00001739 layer_pos_x = prop->dest_x;
1740 layer_pos_y = prop->dest_y;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001741
1742 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1743 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1744
1745 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1746
1747 rgn[0][1] = wl_fixed_from_int(0);
1748 rgn[1][0] = wl_fixed_from_int(0);
1749 rgn[1][1] = wl_fixed_from_int(0);
1750
1751 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1752}
1753
1754static struct pointer_move_grab *
1755create_workspace_pointer_move(struct weston_pointer *pointer,
1756 struct wl_resource* resource)
1757{
1758 struct pointer_move_grab *pnt_move_grab =
1759 MEM_ALLOC(sizeof(*pnt_move_grab));
1760
1761 pnt_move_grab->base.resource = resource;
1762 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1763 pointer->grab_y, resource);
1764
1765 return pnt_move_grab;
1766}
1767
1768static struct touch_move_grab *
1769create_workspace_touch_move(struct weston_touch *touch,
1770 struct wl_resource* resource)
1771{
1772 struct touch_move_grab *tch_move_grab =
1773 MEM_ALLOC(sizeof(*tch_move_grab));
1774
1775 tch_move_grab->base.resource = resource;
1776 tch_move_grab->is_active = 1;
1777 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1778 touch->grab_y, resource);
1779
1780 return tch_move_grab;
1781}
1782
1783static void
1784ivi_hmi_controller_workspace_control(struct wl_client *client,
1785 struct wl_resource *resource,
1786 struct wl_resource *seat_resource,
1787 uint32_t serial)
1788{
1789 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1790 struct ivi_layout_layer *layer = NULL;
1791 struct pointer_move_grab *pnt_move_grab = NULL;
1792 struct touch_move_grab *tch_move_grab = NULL;
1793 struct weston_seat *seat = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001794 struct weston_pointer *pointer;
1795 struct weston_touch *touch;
1796
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001797 enum HMI_GRAB_DEVICE device;
1798
1799 if (hmi_ctrl->workspace_count < 2)
1800 return;
1801
1802 seat = wl_resource_get_user_data(seat_resource);
1803 device = get_hmi_grab_device(seat, serial);
1804
1805 if (HMI_GRAB_DEVICE_POINTER != device &&
1806 HMI_GRAB_DEVICE_TOUCH != device)
1807 return;
1808
1809 layer = hmi_ctrl->workspace_layer.ivilayer;
1810
Emre Ucana9db8d72018-01-25 14:36:11 +01001811 hmi_ctrl->interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001812
1813 switch (device) {
1814 case HMI_GRAB_DEVICE_POINTER:
Derek Foreman1281a362015-07-31 16:55:32 -05001815 pointer = weston_seat_get_pointer(seat);
1816 pnt_move_grab = create_workspace_pointer_move(pointer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001817 resource);
1818
1819 pointer_grab_start(&pnt_move_grab->base, layer,
1820 &pointer_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001821 pointer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001822 break;
1823
1824 case HMI_GRAB_DEVICE_TOUCH:
Derek Foreman1281a362015-07-31 16:55:32 -05001825 touch = weston_seat_get_touch(seat);
1826 tch_move_grab = create_workspace_touch_move(touch,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001827 resource);
1828
1829 touch_grab_start(&tch_move_grab->base, layer,
1830 &touch_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001831 touch);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001832 break;
1833
1834 default:
1835 break;
1836 }
1837}
1838
1839/**
1840 * Implementation of switch_mode
1841 */
1842static void
1843ivi_hmi_controller_switch_mode(struct wl_client *client,
1844 struct wl_resource *resource,
1845 uint32_t layout_mode)
1846{
1847 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1848
1849 switch_mode(hmi_ctrl, layout_mode);
1850}
1851
1852/**
1853 * Implementation of on/off displaying workspace and workspace background
1854 * ivi_layers.
1855 */
1856static void
1857ivi_hmi_controller_home(struct wl_client *client,
1858 struct wl_resource *resource,
1859 uint32_t home)
1860{
1861 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1862 uint32_t is_fade_in;
1863
1864 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1865 !hmi_ctrl->workspace_fade.is_fade_in) ||
1866 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1867 hmi_ctrl->workspace_fade.is_fade_in)) {
1868 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1869 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1870 &hmi_ctrl->workspace_fade);
1871 }
1872
Emre Ucana9db8d72018-01-25 14:36:11 +01001873 hmi_ctrl->interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001874}
1875
1876/**
1877 * binding ivi-hmi-controller implementation
1878 */
1879static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1880 ivi_hmi_controller_UI_ready,
1881 ivi_hmi_controller_workspace_control,
1882 ivi_hmi_controller_switch_mode,
1883 ivi_hmi_controller_home
1884};
1885
1886static void
1887unbind_hmi_controller(struct wl_resource *resource)
1888{
1889}
1890
1891static void
1892bind_hmi_controller(struct wl_client *client,
1893 void *data, uint32_t version, uint32_t id)
1894{
1895 struct wl_resource *resource = NULL;
1896 struct hmi_controller *hmi_ctrl = data;
1897
1898 if (hmi_ctrl->user_interface != client) {
1899 struct wl_resource *res = wl_client_get_object(client, 1);
1900 wl_resource_post_error(res,
1901 WL_DISPLAY_ERROR_INVALID_OBJECT,
1902 "hmi-controller failed: permission denied");
1903 return;
1904 }
1905
1906 resource = wl_resource_create(
1907 client, &ivi_hmi_controller_interface, 1, id);
1908
1909 wl_resource_set_implementation(
1910 resource, &ivi_hmi_controller_implementation,
1911 hmi_ctrl, unbind_hmi_controller);
1912}
1913
1914static int32_t
1915initialize(struct hmi_controller *hmi_ctrl)
1916{
1917 struct config_command {
1918 char *key;
1919 uint32_t *dest;
1920 };
1921
Giulio Camuffod52f3b72016-06-02 21:48:11 +03001922 struct weston_config *config = wet_get_config(hmi_ctrl->compositor);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001923 struct weston_config_section *section = NULL;
1924 int result = 0;
1925 int i = 0;
1926
1927 const struct config_command uint_commands[] = {
1928 { "background-id", &hmi_ctrl->ui_setting.background_id },
1929 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1930 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1931 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1932 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1933 { "random-id", &hmi_ctrl->ui_setting.random_id },
1934 { "home-id", &hmi_ctrl->ui_setting.home_id },
1935 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +09001936 { "surface-id-offset", &hmi_ctrl->ui_setting.surface_id_offset },
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001937 { NULL, NULL }
1938 };
1939
1940 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1941
1942 for (i = 0; -1 != result; ++i) {
1943 const struct config_command *command = &uint_commands[i];
1944
1945 if (!command->key)
1946 break;
1947
1948 if (weston_config_section_get_uint(
1949 section, command->key, command->dest, 0) != 0)
1950 result = -1;
1951 }
1952
1953 if (-1 == result) {
1954 weston_log("Failed to initialize hmi-controller\n");
1955 return 0;
1956 }
1957
1958 return 1;
1959}
1960
1961static void
1962launch_hmi_client_process(void *data)
1963{
1964 struct hmi_controller *hmi_ctrl =
1965 (struct hmi_controller *)data;
1966
1967 hmi_ctrl->user_interface =
1968 weston_client_start(hmi_ctrl->compositor,
1969 hmi_ctrl->hmi_setting->ivi_homescreen);
1970
1971 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1972}
1973
1974/*****************************************************************************
1975 * exported functions
1976 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001977WL_EXPORT int
Emre Ucanffaf09e2018-01-25 14:36:12 +01001978wet_module_init(struct weston_compositor *ec,
1979 int *argc, char *argv[])
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001980{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001981 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001982 struct wl_event_loop *loop = NULL;
1983
Pekka Paalanen6ffbba32019-11-06 12:59:32 +02001984 /* ad hoc weston_compositor_add_destroy_listener_once() */
1985 if (wl_signal_get(&ec->destroy_signal, hmi_controller_destroy))
1986 return 0;
1987
Emre Ucanffaf09e2018-01-25 14:36:12 +01001988 hmi_ctrl = hmi_controller_create(ec);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001989 if (hmi_ctrl == NULL)
1990 return -1;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001991
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001992 if (!initialize(hmi_ctrl)) {
1993 return -1;
1994 }
1995
1996 if (wl_global_create(ec->wl_display,
1997 &ivi_hmi_controller_interface, 1,
1998 hmi_ctrl, bind_hmi_controller) == NULL) {
1999 return -1;
2000 }
2001
2002 loop = wl_display_get_event_loop(ec->wl_display);
2003 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
2004
2005 return 0;
2006}