blob: d5b11ed123c92e42e81269d73e8989f182162843 [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
41 * - Next, a application ivi_layer to show application ivi_surfaces.
42 * - 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
52#include <sys/wait.h>
53#include <unistd.h>
54#include <stdlib.h>
55#include <stdio.h>
56#include <string.h>
57#include <linux/input.h>
58#include <assert.h>
59#include <time.h>
60
61#include "ivi-layout-export.h"
62#include "ivi-hmi-controller-server-protocol.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070063#include "shared/helpers.h"
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090064
65/*****************************************************************************
66 * structure, globals
67 ****************************************************************************/
68struct hmi_controller_layer {
69 struct ivi_layout_layer *ivilayer;
70 uint32_t id_layer;
71 int32_t x;
72 int32_t y;
73 int32_t width;
74 int32_t height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +090075 struct wl_list link;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090076};
77
78struct link_layer {
79 struct ivi_layout_layer *layout_layer;
80 struct wl_list link;
81};
82
83struct hmi_controller_fade {
84 uint32_t is_fade_in;
85 struct wl_list layer_list;
86};
87
88struct hmi_server_setting {
89 uint32_t base_layer_id;
90 uint32_t application_layer_id;
91 uint32_t workspace_background_layer_id;
92 uint32_t workspace_layer_id;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +090093 uint32_t base_layer_id_offset;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090094 int32_t panel_height;
95 uint32_t transition_duration;
96 char *ivi_homescreen;
97};
98
99struct ui_setting {
100 uint32_t background_id;
101 uint32_t panel_id;
102 uint32_t tiling_id;
103 uint32_t sidebyside_id;
104 uint32_t fullscreen_id;
105 uint32_t random_id;
106 uint32_t home_id;
107 uint32_t workspace_background_id;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900108 uint32_t surface_id_offset;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900109};
110
111struct hmi_controller {
112 struct hmi_server_setting *hmi_setting;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900113 /* List of struct hmi_controller_layer */
114 struct wl_list base_layer_list;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900115 struct wl_list application_layer_list;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900116 struct hmi_controller_layer workspace_background_layer;
117 struct hmi_controller_layer workspace_layer;
118 enum ivi_hmi_controller_layout_mode layout_mode;
119
120 struct hmi_controller_fade workspace_fade;
121
122 int32_t workspace_count;
123 struct wl_array ui_widgets;
124 int32_t is_initialized;
125
126 struct weston_compositor *compositor;
127 struct wl_listener destroy_listener;
128
129 struct wl_client *user_interface;
130 struct ui_setting ui_setting;
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900131
132 int32_t screen_num;
133 struct ivi_layout_screen **pp_screen;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900134};
135
136struct launcher_info {
137 uint32_t surface_id;
138 uint32_t workspace_id;
139 int32_t index;
140};
141
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000142const struct ivi_layout_interface *ivi_layout_interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900143
144int
145controller_module_init(struct weston_compositor *ec,
146 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000147 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900148 size_t interface_version);
149
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900150/*****************************************************************************
151 * local functions
152 ****************************************************************************/
153static void *
154fail_on_null(void *p, size_t size, char *file, int32_t line)
155{
156 if (size && !p) {
157 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
158 exit(EXIT_FAILURE);
159 }
160
161 return p;
162}
163
164static void *
165mem_alloc(size_t size, char *file, int32_t line)
166{
167 return fail_on_null(calloc(1, size), size, file, line);
168}
169
170#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
171
172static int32_t
173is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
174 struct ivi_layout_surface *ivisurf)
175{
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000176 uint32_t id = ivi_layout_interface->get_id_of_surface(ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900177
178 uint32_t *ui_widget_id = NULL;
179 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
180 if (*ui_widget_id == id)
181 return 1;
182 }
183
184 return 0;
185}
186
187static int
188compare_launcher_info(const void *lhs, const void *rhs)
189{
190 const struct launcher_info *left = lhs;
191 const struct launcher_info *right = rhs;
192
193 if (left->workspace_id < right->workspace_id)
194 return -1;
195
196 if (left->workspace_id > right->workspace_id)
197 return 1;
198
199 if (left->index < right->index)
200 return -1;
201
202 if (left->index > right->index)
203 return 1;
204
205 return 0;
206}
207
208/**
209 * Internal methods called by mainly ivi_hmi_controller_switch_mode
210 * This reference shows 4 examples how to use ivi_layout APIs.
211 */
212static void
213mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
214 struct ivi_layout_surface **pp_surface,
215 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900216 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900217{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900218 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900219 const float surface_width = (float)layer->width * 0.25;
220 const float surface_height = (float)layer->height * 0.5;
221 int32_t surface_x = 0;
222 int32_t surface_y = 0;
223 struct ivi_layout_surface *ivisurf = NULL;
224 struct ivi_layout_surface **surfaces;
225 struct ivi_layout_surface **new_order;
226 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900227 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900228
229 int32_t i = 0;
230 int32_t surf_num = 0;
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900231 int32_t idx = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900232
233 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
234 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
235
236 for (i = 0; i < surface_length; i++) {
237 ivisurf = pp_surface[i];
238
239 /* skip ui widgets */
240 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
241 continue;
242
243 surfaces[surf_num++] = ivisurf;
244 }
245
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900246 wl_list_for_each_reverse(layer, layer_list, link) {
247 if (idx >= surf_num)
248 break;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900249
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900250 ivilayer = layer->ivilayer;
251
252 for (i = 0; i < 8; i++, idx++) {
253 if (idx >= surf_num)
254 break;
255
256 ivisurf = surfaces[idx];
257 new_order[i] = ivisurf;
258 if (i < 4) {
259 surface_x = (int32_t)(i * (surface_width));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900260 surface_y = 0;
261 } else {
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900262 surface_x = (int32_t)((i - 4) * (surface_width));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900263 surface_y = (int32_t)surface_height;
264 }
265
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000266 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900267 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
268 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000269 ivi_layout_interface->surface_set_visibility(ivisurf, true);
270 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900271 surface_x, surface_y,
272 (int32_t)surface_width,
273 (int32_t)surface_height);
274
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900275 }
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900276 ivi_layout_interface->layer_set_render_order(ivilayer, new_order, i);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900277
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900278 ivi_layout_interface->layer_set_transition(ivilayer,
279 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
280 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900281 }
Nobuhiko Tanibataa8aa91c2015-12-09 15:43:30 +0900282 for (i = idx; i < surf_num; i++)
283 ivi_layout_interface->surface_set_visibility(surfaces[i], false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900284
285 free(surfaces);
286 free(new_order);
287}
288
289static void
290mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
291 struct ivi_layout_surface **pp_surface,
292 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900293 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900294{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900295 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900296 int32_t surface_width = layer->width / 2;
297 int32_t surface_height = layer->height;
298 struct ivi_layout_surface *ivisurf = NULL;
299
300 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
301 int32_t i = 0;
302 int32_t num = 1;
303
304 for (i = 0; i < surface_length; i++) {
305 ivisurf = pp_surface[i];
306
307 /* skip ui widgets */
308 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
309 continue;
310
311 if (num == 1) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000312 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900313 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
314 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000315 ivi_layout_interface->surface_set_visibility(ivisurf, true);
316 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900317 0, 0,
318 surface_width,
319 surface_height);
320
321 num++;
322 continue;
323 } else if (num == 2) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000324 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900325 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
326 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000327 ivi_layout_interface->surface_set_visibility(ivisurf, true);
328 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900329 surface_width, 0,
330 surface_width,
331 surface_height);
332
333 num++;
334 continue;
335 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000336 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900337 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
338 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000339 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900340 }
341}
342
343static void
344mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
345 struct ivi_layout_surface **pp_surface,
346 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900347 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900348{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900349 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900350 const int32_t surface_width = layer->width;
351 const int32_t surface_height = layer->height;
352 struct ivi_layout_surface *ivisurf = NULL;
353 int32_t i = 0;
354 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
355
356 for (i = 0; i < surface_length; i++) {
357 ivisurf = pp_surface[i];
358
359 /* skip ui widgets */
360 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
361 continue;
362
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000363 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900364 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
365 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000366 ivi_layout_interface->surface_set_visibility(ivisurf, true);
367 ivi_layout_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900368 surface_width,
369 surface_height);
370 }
371}
372
373static void
374mode_random_replace(struct hmi_controller *hmi_ctrl,
375 struct ivi_layout_surface **pp_surface,
376 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900377 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900378{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900379 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900380 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
381 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
382 int32_t surface_x = 0;
383 int32_t surface_y = 0;
384 struct ivi_layout_surface *ivisurf = NULL;
385 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
386 int32_t i = 0;
387
388 for (i = 0; i < surface_length; i++) {
389 ivisurf = pp_surface[i];
390
391 /* skip ui widgets */
392 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
393 continue;
394
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000395 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900396 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
397 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000398 ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900399 surface_x = rand() % (layer->width - surface_width);
400 surface_y = rand() % (layer->height - surface_height);
401
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000402 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900403 surface_x,
404 surface_y,
405 surface_width,
406 surface_height);
407 }
408}
409
410static int32_t
411has_application_surface(struct hmi_controller *hmi_ctrl,
412 struct ivi_layout_surface **pp_surface,
413 int32_t surface_length)
414{
415 struct ivi_layout_surface *ivisurf = NULL;
416 int32_t i = 0;
417
418 for (i = 0; i < surface_length; i++) {
419 ivisurf = pp_surface[i];
420
421 /* skip ui widgets */
422 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
423 continue;
424
425 return 1;
426 }
427
428 return 0;
429}
430
431/**
432 * Supports 4 example to layout of application ivi_surfaces;
433 * tiling, side by side, fullscreen, and random.
434 */
435static void
436switch_mode(struct hmi_controller *hmi_ctrl,
437 enum ivi_hmi_controller_layout_mode layout_mode)
438{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900439 struct wl_list *layer = &hmi_ctrl->application_layer_list;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900440 struct ivi_layout_surface **pp_surface = NULL;
441 int32_t surface_length = 0;
442 int32_t ret = 0;
443
444 if (!hmi_ctrl->is_initialized)
445 return;
446
447 hmi_ctrl->layout_mode = layout_mode;
448
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000449 ret = ivi_layout_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900450 assert(!ret);
451
452 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
453 free(pp_surface);
454 pp_surface = NULL;
455 return;
456 }
457
458 switch (layout_mode) {
459 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
460 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
461 layer);
462 break;
463 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
464 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
465 surface_length, layer);
466 break;
467 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
468 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
469 layer);
470 break;
471 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
472 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
473 layer);
474 break;
475 }
476
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000477 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900478 free(pp_surface);
479}
480
481/**
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900482 * Internal method to get screens from weston core
483 * TODO: shall support hotplug of screens
484 */
485static int32_t
486get_screens(struct hmi_controller *hmi_ctrl)
487{
488 hmi_ctrl->pp_screen = NULL;
489 hmi_ctrl->screen_num = 0;
490 ivi_layout_interface->get_screens(&hmi_ctrl->screen_num, &hmi_ctrl->pp_screen);
491
492 if (hmi_ctrl->pp_screen == NULL)
493 return -1;
494 else
495 return 0;
496}
497
498/**
499 * Internal method to get ivi_layout_screen
500 */
501static struct ivi_layout_screen *
502get_screen(int32_t screen_idx, struct hmi_controller *hmi_ctrl)
503{
504 struct ivi_layout_screen *iviscrn = NULL;
505
506 if (screen_idx > hmi_ctrl->screen_num - 1)
507 weston_log("Invalid index. Return NULL\n");
508 else
509 iviscrn = hmi_ctrl->pp_screen[screen_idx];
510
511 return iviscrn;
512}
513
514/**
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900515 * Internal method for transition
516 */
517static void
518hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
519 struct hmi_controller_fade *fade)
520{
521 double tint = is_fade_in ? 1.0 : 0.0;
522 struct link_layer *linklayer = NULL;
523 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
524
525 fade->is_fade_in = is_fade_in;
526
527 wl_list_for_each(linklayer, &fade->layer_list, link) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000528 ivi_layout_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900529 IVI_LAYOUT_TRANSITION_LAYER_FADE,
530 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000531 ivi_layout_interface->layer_set_fade_info(linklayer->layout_layer,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900532 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900533 }
534}
535
536/**
537 * Internal method to create ivi_layer with hmi_controller_layer and
538 * add to a ivi_screen
539 */
540static void
541create_layer(struct ivi_layout_screen *iviscrn,
542 struct hmi_controller_layer *layer)
543{
544 int32_t ret = 0;
545
546 layer->ivilayer =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000547 ivi_layout_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900548 layer->width,
549 layer->height);
550 assert(layer->ivilayer != NULL);
551
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000552 ret = ivi_layout_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900553 assert(!ret);
554
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000555 ret = ivi_layout_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900556 layer->x, layer->y,
557 layer->width,
558 layer->height);
559 assert(!ret);
560
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000561 ret = ivi_layout_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900562 assert(!ret);
563}
564
565/**
566 * Internal set notification
567 */
568static void
569set_notification_create_surface(struct ivi_layout_surface *ivisurf,
570 void *userdata)
571{
572 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900573 struct hmi_controller_layer *layer_link =
574 wl_container_of(hmi_ctrl->application_layer_list.prev,
575 layer_link,
576 link);
577 struct ivi_layout_layer *application_layer = layer_link->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900578 int32_t ret = 0;
579
580 /* skip ui widgets */
581 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
582 return;
583
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000584 ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900585 assert(!ret);
586}
587
588static void
589set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
590 void *userdata)
591{
592 struct hmi_controller *hmi_ctrl = userdata;
593
594 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
595}
596
597static void
598set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
599 void *userdata)
600{
601 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900602 struct hmi_controller_layer *layer_link = NULL;
603 struct ivi_layout_layer *application_layer = NULL;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900604 struct weston_surface *surface;
605 struct ivi_layout_surface **ivisurfs;
606 int32_t length = 0;
607 int32_t i;
608
609 /* return if the surface is not application content */
610 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
611 return;
612 }
613
614 /*
615 * if application changes size of wl_buffer. The source rectangle shall be
616 * fit to the size.
617 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000618 surface = ivi_layout_interface->surface_get_weston_surface(ivisurf);
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900619 if (surface) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000620 ivi_layout_interface->surface_set_source_rectangle(
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900621 ivisurf, 0, 0, surface->width,
622 surface->height);
623 }
624
625 /*
626 * search if the surface is already added to layer.
627 * If not yet, it is newly invoded application to go to switch_mode.
628 */
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900629 wl_list_for_each_reverse(layer_link, &hmi_ctrl->application_layer_list, link) {
630 application_layer = layer_link->ivilayer;
631 ivi_layout_interface->get_surfaces_on_layer(application_layer,
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900632 &length, &ivisurfs);
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900633 for (i = 0; i < length; i++) {
634 if (ivisurf == ivisurfs[i]) {
635 /*
636 * if it is non new invoked application, just call
637 * commit_changes to apply source_rectangle.
638 */
639 ivi_layout_interface->commit_changes();
640 return;
641 }
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900642 }
643 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900644
645 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
646}
647
648/**
649 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
650 * corresponding ivi_layer are defined in weston.ini. Default scene graph
651 * of ivi_layers are initialized in hmi_controller_create
652 */
653static struct hmi_server_setting *
654hmi_server_setting_create(struct weston_compositor *ec)
655{
656 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
657 struct weston_config *config = ec->config;
658 struct weston_config_section *shell_section = NULL;
659
660 shell_section = weston_config_get_section(config, "ivi-shell",
661 NULL, NULL);
662
663 weston_config_section_get_uint(shell_section, "base-layer-id",
664 &setting->base_layer_id, 1000);
665
666 weston_config_section_get_uint(shell_section,
667 "workspace-background-layer-id",
668 &setting->workspace_background_layer_id,
669 2000);
670
671 weston_config_section_get_uint(shell_section, "workspace-layer-id",
672 &setting->workspace_layer_id, 3000);
673
674 weston_config_section_get_uint(shell_section, "application-layer-id",
675 &setting->application_layer_id, 4000);
676
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900677 weston_config_section_get_uint(shell_section, "base-layer-id-offset",
678 &setting->base_layer_id_offset, 10000);
679
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900680 weston_config_section_get_uint(shell_section, "transition-duration",
681 &setting->transition_duration, 300);
682
683 setting->panel_height = 70;
684
685 weston_config_section_get_string(shell_section,
686 "ivi-shell-user-interface",
687 &setting->ivi_homescreen, NULL);
688
689 return setting;
690}
691
692static void
693hmi_controller_destroy(struct wl_listener *listener, void *data)
694{
695 struct link_layer *link = NULL;
696 struct link_layer *next = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900697 struct hmi_controller_layer *ctrl_layer_link = NULL;
698 struct hmi_controller_layer *ctrl_layer_next = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900699 struct hmi_controller *hmi_ctrl =
700 container_of(listener, struct hmi_controller, destroy_listener);
701
702 wl_list_for_each_safe(link, next,
703 &hmi_ctrl->workspace_fade.layer_list, link) {
704 wl_list_remove(&link->link);
705 free(link);
706 }
707
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900708 /* clear base_layer_list */
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900709 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
710 &hmi_ctrl->base_layer_list, link) {
711 wl_list_remove(&ctrl_layer_link->link);
712 free(ctrl_layer_link);
713 }
714
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900715 /* clear application_layer_list */
716 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
717 &hmi_ctrl->application_layer_list, link) {
718 wl_list_remove(&ctrl_layer_link->link);
719 free(ctrl_layer_link);
720 }
721
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900722 wl_array_release(&hmi_ctrl->ui_widgets);
723 free(hmi_ctrl->hmi_setting);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900724 free(hmi_ctrl->pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900725 free(hmi_ctrl);
726}
727
728/**
729 * This is a starting method called from module_init.
730 * This sets up scene graph of ivi_layers; base, application, workspace
731 * background, and workspace. These ivi_layers are created/added to
732 * ivi_screen in create_layer
733 *
734 * base: to group ivi_surfaces of panel and background
735 * application: to group ivi_surfaces of ivi_applications
736 * workspace background: to group a ivi_surface of background in workspace
737 * workspace: to group ivi_surfaces for launching ivi_applications
738 *
739 * ivi_layers of workspace background and workspace is set to invisible at
740 * first. The properties of it is updated with animation when
741 * ivi_hmi_controller_home is requested.
742 */
743static struct hmi_controller *
744hmi_controller_create(struct weston_compositor *ec)
745{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900746 struct ivi_layout_screen *iviscrn = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900747 int32_t screen_width = 0;
748 int32_t screen_height = 0;
749 struct link_layer *tmp_link_layer = NULL;
750 int32_t panel_height = 0;
751 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900752 struct hmi_controller_layer *base_layer = NULL;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900753 struct hmi_controller_layer *application_layer = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900754
755 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900756
757 wl_array_init(&hmi_ctrl->ui_widgets);
758 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
759 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
760 hmi_ctrl->compositor = ec;
761
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900762 /* TODO: shall support hotplug of screens */
763 if (get_screens(hmi_ctrl) < 0) {
764 weston_log("ivi-shell: Failed to get screens\n");
765 hmi_ctrl = NULL;
766 return hmi_ctrl;
767 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900768
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900769 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900770
771 /* init base ivi_layer*/
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900772 wl_list_init(&hmi_ctrl->base_layer_list);
773 for (i = 0; i < hmi_ctrl->screen_num; i++) {
774 ivi_layout_interface->get_screen_resolution(get_screen(i, hmi_ctrl),
775 &screen_width,
776 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900777
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900778 base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
779 base_layer->x = 0;
780 base_layer->y = 0;
781 base_layer->width = screen_width;
782 base_layer->height = screen_height;
783 base_layer->id_layer =
784 hmi_ctrl->hmi_setting->base_layer_id +
785 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
786 wl_list_insert(&hmi_ctrl->base_layer_list, &base_layer->link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900787
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900788 create_layer(get_screen(i, hmi_ctrl), base_layer);
789 }
790
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900791 panel_height = hmi_ctrl->hmi_setting->panel_height;
792
793 /* init application ivi_layer */
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900794 wl_list_init(&hmi_ctrl->application_layer_list);
795 for (i = 0; i < hmi_ctrl->screen_num; i++) {
796 ivi_layout_interface->get_screen_resolution(get_screen(i, hmi_ctrl),
797 &screen_width,
798 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900799
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900800 application_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
801 application_layer->x = 0;
802 application_layer->y = 0;
803 application_layer->width = screen_width;
804 application_layer->height = screen_height - panel_height;
805 application_layer->id_layer =
806 hmi_ctrl->hmi_setting->application_layer_id +
807 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
808 wl_list_insert(&hmi_ctrl->application_layer_list, &application_layer->link);
809
810 create_layer(get_screen(i, hmi_ctrl), application_layer);
811 }
812
813 ivi_layout_interface->get_screen_resolution(iviscrn, &screen_width,
814 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900815
816 /* init workspace background ivi_layer */
817 hmi_ctrl->workspace_background_layer.x = 0;
818 hmi_ctrl->workspace_background_layer.y = 0;
819 hmi_ctrl->workspace_background_layer.width = screen_width;
820 hmi_ctrl->workspace_background_layer.height =
821 screen_height - panel_height;
822
823 hmi_ctrl->workspace_background_layer.id_layer =
824 hmi_ctrl->hmi_setting->workspace_background_layer_id;
825
826 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000827 ivi_layout_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900828 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000829 ivi_layout_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900830 hmi_ctrl->workspace_background_layer.ivilayer, false);
831
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900832
833 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
834 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900835 tmp_link_layer->layout_layer =
836 hmi_ctrl->workspace_background_layer.ivilayer;
837 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
838 &tmp_link_layer->link);
839
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000840 ivi_layout_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900841 set_notification_create_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000842 ivi_layout_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900843 set_notification_remove_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000844 ivi_layout_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900845 set_notification_configure_surface, hmi_ctrl);
846
847 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
848 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
849 &hmi_ctrl->destroy_listener);
850
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900851 return hmi_ctrl;
852}
853
854/**
855 * Implementations of ivi-hmi-controller.xml
856 */
857
858/**
859 * A ivi_surface drawing background is identified by id_surface.
860 * Properties of the ivi_surface is set by using ivi_layout APIs according to
861 * the scene graph of UI defined in hmi_controller_create.
862 *
863 * UI ivi_layer is used to add this ivi_surface.
864 */
865static void
866ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
867 uint32_t id_surface)
868{
869 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900870 struct hmi_controller_layer *base_layer = NULL;
871 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900872 struct hmi_controller_layer *application_layer =
873 wl_container_of(hmi_ctrl->application_layer_list.prev,
874 application_layer,
875 link);
876 const int32_t dstx = application_layer->x;
877 const int32_t dsty = application_layer->y;
878 const int32_t width = application_layer->width;
879 const int32_t height = application_layer->height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900880 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900881 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900882
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900883 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
884 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
885 sizeof(*add_surface_id));
886 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900887
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900888 ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900889
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900890 ivisurf = ivi_layout_interface->get_surface_from_id(*add_surface_id);
891 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900892
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900893 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
894 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900895
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900896 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
897 dstx, dsty, width, height);
898 assert(!ret);
899
900 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
901 assert(!ret);
902
903 i++;
904 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900905}
906
907/**
908 * A ivi_surface drawing panel is identified by id_surface.
909 * Properties of the ivi_surface is set by using ivi_layout APIs according to
910 * the scene graph of UI defined in hmi_controller_create.
911 *
912 * UI ivi_layer is used to add this ivi_surface.
913 */
914static void
915ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
916 uint32_t id_surface)
917{
918 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900919 struct hmi_controller_layer *base_layer =
920 wl_container_of(hmi_ctrl->base_layer_list.prev,
921 base_layer,
922 link);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900923 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900924 const int32_t width = base_layer->width;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900925 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900926 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900927 const int32_t dstx = 0;
928 int32_t dsty = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900929 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900930
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900931 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
932 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
933 sizeof(*add_surface_id));
934 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900935
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900936 ivilayer = base_layer->ivilayer;
937 ivisurf = ivi_layout_interface->get_surface_from_id(*add_surface_id);
938 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900939
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900940 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
941 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900942
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900943 dsty = base_layer->height - panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900944
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900945 ret = ivi_layout_interface->surface_set_destination_rectangle(
946 ivisurf, dstx, dsty, width, panel_height);
947 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900948
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900949 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
950 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900951
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900952 i++;
953 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900954}
955
956/**
957 * A ivi_surface drawing buttons in panel is identified by id_surface.
958 * It can set several buttons. Properties of the ivi_surface is set by
959 * using ivi_layout APIs according to the scene graph of UI defined in
960 * hmi_controller_create. Additionally, the position of it is shifted to
961 * right when new one is requested.
962 *
963 * UI ivi_layer is used to add these ivi_surfaces.
964 */
965static void
966ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
967 uint32_t id_surface, int32_t number)
968{
969 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900970 struct hmi_controller_layer *base_layer =
971 wl_container_of(hmi_ctrl->base_layer_list.prev,
972 base_layer,
973 link);
974 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900975 const int32_t width = 48;
976 const int32_t height = 48;
977 int32_t ret = 0;
978 int32_t panel_height = 0;
979 int32_t dstx = 0;
980 int32_t dsty = 0;
981 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
982 sizeof(*add_surface_id));
983 *add_surface_id = id_surface;
984
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000985 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900986 assert(ivisurf != NULL);
987
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000988 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900989 assert(!ret);
990
991 panel_height = hmi_ctrl->hmi_setting->panel_height;
992
993 dstx = (60 * number) + 15;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900994 dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900995
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000996 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900997 ivisurf,dstx, dsty, width, height);
998 assert(!ret);
999
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001000 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001001 assert(!ret);
1002}
1003
1004/**
1005 * A ivi_surface drawing home button in panel is identified by id_surface.
1006 * Properties of the ivi_surface is set by using ivi_layout APIs according to
1007 * the scene graph of UI defined in hmi_controller_create.
1008 *
1009 * UI ivi_layer is used to add these ivi_surfaces.
1010 */
1011static void
1012ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
1013 uint32_t id_surface)
1014{
1015 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001016 struct hmi_controller_layer *base_layer =
1017 wl_container_of(hmi_ctrl->base_layer_list.prev,
1018 base_layer,
1019 link);
1020 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001021 int32_t ret = 0;
1022 int32_t size = 48;
1023 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001024 const int32_t dstx = (base_layer->width - size) / 2;
1025 const int32_t dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001026
1027 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1028 sizeof(*add_surface_id));
1029 *add_surface_id = id_surface;
1030
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001031 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001032 assert(ivisurf != NULL);
1033
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001034 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001035 assert(!ret);
1036
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001037 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001038 ivisurf, dstx, dsty, size, size);
1039 assert(!ret);
1040
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001041 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001042 assert(!ret);
1043}
1044
1045/**
1046 * A ivi_surface drawing background of workspace is identified by id_surface.
1047 * Properties of the ivi_surface is set by using ivi_layout APIs according to
1048 * the scene graph of UI defined in hmi_controller_create.
1049 *
1050 * A ivi_layer of workspace_background is used to add this ivi_surface.
1051 */
1052static void
1053ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
1054 uint32_t id_surface)
1055{
1056 struct ivi_layout_surface *ivisurf = NULL;
1057 struct ivi_layout_layer *ivilayer = NULL;
1058 const int32_t width = hmi_ctrl->workspace_background_layer.width;
1059 const int32_t height = hmi_ctrl->workspace_background_layer.height;
1060 int32_t ret = 0;
1061
1062 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1063 sizeof(*add_surface_id));
1064 *add_surface_id = id_surface;
1065 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
1066
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001067 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001068 assert(ivisurf != NULL);
1069
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001070 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001071 assert(!ret);
1072
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001073 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001074 0, 0, width, height);
1075 assert(!ret);
1076
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001077 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001078 assert(!ret);
1079}
1080
1081/**
1082 * A list of ivi_surfaces drawing launchers in workspace is identified by
1083 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
1084 * APIs according to the scene graph of UI defined in hmi_controller_create.
1085 *
1086 * The workspace can have several pages to group ivi_surfaces of launcher.
1087 * Each call of this interface increments a number of page to add a group
1088 * of ivi_surfaces
1089 */
1090static void
1091ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
1092 int32_t icon_size)
1093{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001094 int32_t minspace_x = 10;
1095 int32_t minspace_y = minspace_x;
1096
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001097 int32_t width = hmi_ctrl->workspace_background_layer.width;
1098 int32_t height = hmi_ctrl->workspace_background_layer.height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001099
1100 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
1101 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
1102 float fcell_size_x = icon_size + space_x;
1103
1104 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
1105 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
1106 float fcell_size_y = icon_size + space_y;
1107
1108 struct weston_config *config = NULL;
1109 struct weston_config_section *section = NULL;
1110 const char *name = NULL;
1111 int launcher_count = 0;
1112 struct wl_array launchers;
1113 int32_t nx = 0;
1114 int32_t ny = 0;
1115 int32_t prev = -1;
1116 struct launcher_info *data = NULL;
1117
1118 uint32_t surfaceid = 0;
1119 uint32_t workspaceid = 0;
1120 struct launcher_info *info = NULL;
1121
1122 int32_t x = 0;
1123 int32_t y = 0;
1124 int32_t ret = 0;
1125 struct ivi_layout_surface* layout_surface = NULL;
1126 uint32_t *add_surface_id = NULL;
1127
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001128 struct ivi_layout_screen *iviscrn = NULL;
1129 struct link_layer *tmp_link_layer = NULL;
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001130
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001131 if (0 == x_count)
1132 x_count = 1;
1133
1134 if (0 == y_count)
1135 y_count = 1;
1136
1137 config = hmi_ctrl->compositor->config;
1138 if (!config)
1139 return;
1140
1141 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1142 if (!section)
1143 return;
1144
1145 wl_array_init(&launchers);
1146
1147 while (weston_config_next_section(config, &section, &name)) {
1148 surfaceid = 0;
1149 workspaceid = 0;
1150 info = NULL;
1151 if (0 != strcmp(name, "ivi-launcher"))
1152 continue;
1153
1154 if (0 != weston_config_section_get_uint(section, "icon-id",
1155 &surfaceid, 0))
1156 continue;
1157
1158 if (0 != weston_config_section_get_uint(section,
1159 "workspace-id",
1160 &workspaceid, 0))
1161 continue;
1162
1163 info = wl_array_add(&launchers, sizeof(*info));
1164
1165 if (info) {
1166 info->surface_id = surfaceid;
1167 info->workspace_id = workspaceid;
1168 info->index = launcher_count;
1169 ++launcher_count;
1170 }
1171 }
1172
1173 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1174 compare_launcher_info);
1175
1176 wl_array_for_each(data, &launchers) {
1177 x = 0;
1178 y = 0;
1179 ret = 0;
1180 layout_surface = NULL;
1181 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1182 sizeof(*add_surface_id));
1183
1184 *add_surface_id = data->surface_id;
1185
1186 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1187 nx = 0;
1188 ny = 0;
1189 prev = data->workspace_id;
1190
1191 if (0 <= prev)
1192 hmi_ctrl->workspace_count++;
1193 }
1194
1195 if (y_count == ny) {
1196 ny = 0;
1197 hmi_ctrl->workspace_count++;
1198 }
1199
1200 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1201 y = ny * fcell_size_y + space_y;
1202
1203 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001204 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001205 assert(layout_surface);
1206
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001207 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001208 layout_surface, x, y, icon_size, icon_size);
1209 assert(!ret);
1210
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001211 nx++;
1212
1213 if (x_count == nx) {
1214 ny++;
1215 nx = 0;
1216 }
1217 }
1218
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001219 /* init workspace ivi_layer */
1220 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1221 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1222 hmi_ctrl->workspace_layer.width =
1223 hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1224 hmi_ctrl->workspace_layer.height =
1225 hmi_ctrl->workspace_background_layer.height;
1226 hmi_ctrl->workspace_layer.id_layer =
1227 hmi_ctrl->hmi_setting->workspace_layer_id;
1228
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001229 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001230 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001231 ivi_layout_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1232 ivi_layout_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001233 false);
1234
1235 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1236 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1237 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1238 &tmp_link_layer->link);
1239
1240 /* Add surface to layer */
1241 wl_array_for_each(data, &launchers) {
1242 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001243 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001244 assert(layout_surface);
1245
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001246 ret = ivi_layout_interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001247 layout_surface);
1248 assert(!ret);
1249
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001250 ret = ivi_layout_interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001251 assert(!ret);
1252 }
1253
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001254 wl_array_release(&launchers);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001255 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001256}
1257
1258static void
1259ivi_hmi_controller_UI_ready(struct wl_client *client,
1260 struct wl_resource *resource)
1261{
1262 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1263
1264 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1265 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1266 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1267 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1268 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1269 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1270 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1271 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001272 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001273
1274 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1275 hmi_ctrl->is_initialized = 1;
1276}
1277
1278/**
1279 * Implementation of request and event of ivi_hmi_controller_workspace_control
1280 * and controlling workspace.
1281 *
1282 * When motion of input is detected in a ivi_surface of workspace background,
1283 * ivi_hmi_controller_workspace_control shall be invoked and to start
1284 * controlling of workspace. The workspace has several pages to show several
1285 * groups of applications.
1286 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1287 * according to motion. When motion finished, e.g. touch up detected, control is
1288 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1289 */
1290struct pointer_grab {
1291 struct weston_pointer_grab grab;
1292 struct ivi_layout_layer *layer;
1293 struct wl_resource *resource;
1294};
1295
1296struct touch_grab {
1297 struct weston_touch_grab grab;
1298 struct ivi_layout_layer *layer;
1299 struct wl_resource *resource;
1300};
1301
1302struct move_grab {
1303 wl_fixed_t dst[2];
1304 wl_fixed_t rgn[2][2];
1305 double v[2];
1306 struct timespec start_time;
1307 struct timespec pre_time;
1308 wl_fixed_t start_pos[2];
1309 wl_fixed_t pos[2];
1310 int32_t is_moved;
1311};
1312
1313struct pointer_move_grab {
1314 struct pointer_grab base;
1315 struct move_grab move;
1316};
1317
1318struct touch_move_grab {
1319 struct touch_grab base;
1320 struct move_grab move;
1321 int32_t is_active;
1322};
1323
1324static void
1325pointer_grab_start(struct pointer_grab *grab,
1326 struct ivi_layout_layer *layer,
1327 const struct weston_pointer_grab_interface *interface,
1328 struct weston_pointer *pointer)
1329{
1330 grab->grab.interface = interface;
1331 grab->layer = layer;
1332 weston_pointer_start_grab(pointer, &grab->grab);
1333}
1334
1335static void
1336touch_grab_start(struct touch_grab *grab,
1337 struct ivi_layout_layer *layer,
1338 const struct weston_touch_grab_interface *interface,
1339 struct weston_touch* touch)
1340{
1341 grab->grab.interface = interface;
1342 grab->layer = layer;
1343 weston_touch_start_grab(touch, &grab->grab);
1344}
1345
1346static int32_t
1347clamp(int32_t val, int32_t min, int32_t max)
1348{
1349 if (val < min)
1350 return min;
1351
1352 if (max < val)
1353 return max;
1354
1355 return val;
1356}
1357
1358static void
1359move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1360 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1361{
1362 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1363 int32_t width = hmi_ctrl->workspace_background_layer.width;
1364
1365 struct timespec time = {0};
1366 double grab_time = 0.0;
1367 double from_motion_time = 0.0;
1368 double pointer_v = 0.0;
1369 int32_t is_flick = 0;
1370 int32_t pos_x = 0;
1371 int32_t pos_y = 0;
1372 int page_no = 0;
1373 double end_pos = 0.0;
1374 uint32_t duration = 0;
1375
1376 clock_gettime(CLOCK_MONOTONIC, &time);
1377
1378 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1379 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1380
1381 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1382 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1383
1384 pointer_v = move->v[0];
1385
1386 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1387 if (200 < from_motion_time)
1388 pointer_v = 0.0;
1389
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001390 ivi_layout_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001391
1392
1393 if (is_flick) {
1394 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1395 page_no = (-orgx + width / 2) / width;
1396
1397 if (pointer_v < 0.0)
1398 page_no++;
1399 else
1400 page_no--;
1401 } else {
1402 page_no = (-pos_x + width / 2) / width;
1403 }
1404
1405 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1406 end_pos = -page_no * width;
1407
1408 duration = hmi_ctrl->hmi_setting->transition_duration;
1409 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001410 ivi_layout_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001411 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1412 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001413 ivi_layout_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001414 end_pos, pos_y,
Nobuhiko Tanibata4412cd12015-08-24 09:12:37 +09001415 hmi_ctrl->workspace_layer.width,
1416 hmi_ctrl->workspace_layer.height);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001417 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001418}
1419
1420static void
1421pointer_move_workspace_grab_end(struct pointer_grab *grab)
1422{
1423 struct pointer_move_grab *pnt_move_grab =
1424 (struct pointer_move_grab *)grab;
1425 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1426
1427 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1428 grab->grab.pointer->grab_x, layer);
1429
1430 weston_pointer_end_grab(grab->grab.pointer);
1431}
1432
1433static void
1434touch_move_workspace_grab_end(struct touch_grab *grab)
1435{
1436 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1437 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1438
1439 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1440 grab->grab.touch->grab_x, layer);
1441
1442 weston_touch_end_grab(grab->grab.touch);
1443}
1444
1445static void
1446pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1447{
1448}
1449
1450static void
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001451pointer_default_grab_axis(struct weston_pointer_grab *grab,
1452 uint32_t time, uint32_t axis, wl_fixed_t value)
1453{
1454 weston_pointer_send_axis(grab->pointer, time, axis, value);
1455}
1456
1457static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001458move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1459{
1460 struct timespec timestamp = {0};
1461 int32_t ii = 0;
1462 double dt = 0.0;
1463
1464 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1465 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1466 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1467
1468 if (dt < 1e-6)
1469 dt = 1e-6;
1470
1471 move->pre_time = timestamp;
1472
1473 for (ii = 0; ii < 2; ii++) {
1474 wl_fixed_t prepos = move->pos[ii];
1475 move->pos[ii] = pointer[ii] + move->dst[ii];
1476
1477 if (move->pos[ii] < move->rgn[0][ii]) {
1478 move->pos[ii] = move->rgn[0][ii];
1479 move->dst[ii] = move->pos[ii] - pointer[ii];
1480 } else if (move->rgn[1][ii] < move->pos[ii]) {
1481 move->pos[ii] = move->rgn[1][ii];
1482 move->dst[ii] = move->pos[ii] - pointer[ii];
1483 }
1484
1485 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1486
1487 if (!move->is_moved &&
1488 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1489 move->is_moved = 1;
1490 }
1491}
1492
1493static void
1494layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1495 wl_fixed_t pos_y)
1496{
1497 int32_t layout_pos_x = 0;
1498 int32_t layout_pos_y = 0;
1499
1500 layout_pos_x = wl_fixed_to_int(pos_x);
1501 layout_pos_y = wl_fixed_to_int(pos_y);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001502 ivi_layout_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1503 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001504}
1505
1506static void
1507pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001508 struct weston_pointer_motion_event *event)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001509{
1510 struct pointer_move_grab *pnt_move_grab =
1511 (struct pointer_move_grab *)grab;
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001512 wl_fixed_t pointer_pos[2];
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001513
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001514 weston_pointer_motion_to_abs(grab->pointer, event,
1515 &pointer_pos[0], &pointer_pos[1]);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001516 move_grab_update(&pnt_move_grab->move, pointer_pos);
1517 layer_set_pos(pnt_move_grab->base.layer,
1518 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001519 weston_pointer_move(pnt_move_grab->base.grab.pointer, event);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001520}
1521
1522static void
1523touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1524 int touch_id, wl_fixed_t x, wl_fixed_t y)
1525{
1526 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1527
1528 if (!tch_move_grab->is_active)
1529 return;
1530
1531 wl_fixed_t pointer_pos[2] = {
1532 grab->touch->grab_x,
1533 grab->touch->grab_y
1534 };
1535
1536 move_grab_update(&tch_move_grab->move, pointer_pos);
1537 layer_set_pos(tch_move_grab->base.layer,
1538 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1539}
1540
1541static void
1542pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1543 uint32_t time, uint32_t button,
1544 uint32_t state_w)
1545{
1546 if (BTN_LEFT == button &&
1547 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1548 struct pointer_grab *pg = (struct pointer_grab *)grab;
1549
1550 pointer_move_workspace_grab_end(pg);
1551 free(grab);
1552 }
1553}
1554
1555static void
1556touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1557 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1558{
1559}
1560
1561static void
1562touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1563 int touch_id)
1564{
1565 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1566
1567 if (0 == touch_id)
1568 tch_move_grab->is_active = 0;
1569
1570 if (0 == grab->touch->num_tp) {
1571 touch_move_workspace_grab_end(&tch_move_grab->base);
1572 free(grab);
1573 }
1574}
1575
1576static void
1577pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1578{
1579 struct pointer_grab *pg = (struct pointer_grab *)grab;
1580
1581 pointer_move_workspace_grab_end(pg);
1582 free(grab);
1583}
1584
1585static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001586touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1587{
1588}
1589
1590static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001591touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1592{
1593 struct touch_grab *tg = (struct touch_grab *)grab;
1594
1595 touch_move_workspace_grab_end(tg);
1596 free(grab);
1597}
1598
1599static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1600 pointer_noop_grab_focus,
1601 pointer_move_grab_motion,
1602 pointer_move_workspace_grab_button,
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001603 pointer_default_grab_axis,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001604 pointer_move_workspace_grab_cancel
1605};
1606
1607static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1608 touch_nope_grab_down,
1609 touch_move_workspace_grab_up,
1610 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001611 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001612 touch_move_workspace_grab_cancel
1613};
1614
1615enum HMI_GRAB_DEVICE {
1616 HMI_GRAB_DEVICE_NONE,
1617 HMI_GRAB_DEVICE_POINTER,
1618 HMI_GRAB_DEVICE_TOUCH
1619};
1620
1621static enum HMI_GRAB_DEVICE
1622get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1623{
Derek Foreman1281a362015-07-31 16:55:32 -05001624 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1625 struct weston_touch *touch = weston_seat_get_touch(seat);
1626
1627 if (pointer &&
1628 pointer->focus &&
1629 pointer->button_count &&
1630 pointer->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001631 return HMI_GRAB_DEVICE_POINTER;
1632
Derek Foreman1281a362015-07-31 16:55:32 -05001633 if (touch &&
1634 touch->focus &&
1635 touch->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001636 return HMI_GRAB_DEVICE_TOUCH;
1637
1638 return HMI_GRAB_DEVICE_NONE;
1639}
1640
1641static void
1642move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1643 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1644 struct wl_resource* resource)
1645{
1646 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1647 move->pre_time = move->start_time;
1648 move->pos[0] = start_pos[0];
1649 move->pos[1] = start_pos[1];
1650 move->start_pos[0] = start_pos[0];
1651 move->start_pos[1] = start_pos[1];
1652 move->dst[0] = start_pos[0] - grab_pos[0];
1653 move->dst[1] = start_pos[1] - grab_pos[1];
1654 memcpy(move->rgn, rgn, sizeof(move->rgn));
1655}
1656
1657static void
1658move_grab_init_workspace(struct move_grab* move,
1659 wl_fixed_t grab_x, wl_fixed_t grab_y,
1660 struct wl_resource *resource)
1661{
1662 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1663 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1664 int32_t workspace_count = hmi_ctrl->workspace_count;
1665 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1666 int32_t layer_pos_x = 0;
1667 int32_t layer_pos_y = 0;
1668 wl_fixed_t start_pos[2] = {0};
1669 wl_fixed_t rgn[2][2] = {{0}};
1670 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1671
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001672 ivi_layout_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001673
1674 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1675 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1676
1677 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1678
1679 rgn[0][1] = wl_fixed_from_int(0);
1680 rgn[1][0] = wl_fixed_from_int(0);
1681 rgn[1][1] = wl_fixed_from_int(0);
1682
1683 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1684}
1685
1686static struct pointer_move_grab *
1687create_workspace_pointer_move(struct weston_pointer *pointer,
1688 struct wl_resource* resource)
1689{
1690 struct pointer_move_grab *pnt_move_grab =
1691 MEM_ALLOC(sizeof(*pnt_move_grab));
1692
1693 pnt_move_grab->base.resource = resource;
1694 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1695 pointer->grab_y, resource);
1696
1697 return pnt_move_grab;
1698}
1699
1700static struct touch_move_grab *
1701create_workspace_touch_move(struct weston_touch *touch,
1702 struct wl_resource* resource)
1703{
1704 struct touch_move_grab *tch_move_grab =
1705 MEM_ALLOC(sizeof(*tch_move_grab));
1706
1707 tch_move_grab->base.resource = resource;
1708 tch_move_grab->is_active = 1;
1709 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1710 touch->grab_y, resource);
1711
1712 return tch_move_grab;
1713}
1714
1715static void
1716ivi_hmi_controller_workspace_control(struct wl_client *client,
1717 struct wl_resource *resource,
1718 struct wl_resource *seat_resource,
1719 uint32_t serial)
1720{
1721 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1722 struct ivi_layout_layer *layer = NULL;
1723 struct pointer_move_grab *pnt_move_grab = NULL;
1724 struct touch_move_grab *tch_move_grab = NULL;
1725 struct weston_seat *seat = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001726 struct weston_pointer *pointer;
1727 struct weston_touch *touch;
1728
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001729 enum HMI_GRAB_DEVICE device;
1730
1731 if (hmi_ctrl->workspace_count < 2)
1732 return;
1733
1734 seat = wl_resource_get_user_data(seat_resource);
1735 device = get_hmi_grab_device(seat, serial);
1736
1737 if (HMI_GRAB_DEVICE_POINTER != device &&
1738 HMI_GRAB_DEVICE_TOUCH != device)
1739 return;
1740
1741 layer = hmi_ctrl->workspace_layer.ivilayer;
1742
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001743 ivi_layout_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001744
1745 switch (device) {
1746 case HMI_GRAB_DEVICE_POINTER:
Derek Foreman1281a362015-07-31 16:55:32 -05001747 pointer = weston_seat_get_pointer(seat);
1748 pnt_move_grab = create_workspace_pointer_move(pointer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001749 resource);
1750
1751 pointer_grab_start(&pnt_move_grab->base, layer,
1752 &pointer_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001753 pointer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001754 break;
1755
1756 case HMI_GRAB_DEVICE_TOUCH:
Derek Foreman1281a362015-07-31 16:55:32 -05001757 touch = weston_seat_get_touch(seat);
1758 tch_move_grab = create_workspace_touch_move(touch,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001759 resource);
1760
1761 touch_grab_start(&tch_move_grab->base, layer,
1762 &touch_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001763 touch);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001764 break;
1765
1766 default:
1767 break;
1768 }
1769}
1770
1771/**
1772 * Implementation of switch_mode
1773 */
1774static void
1775ivi_hmi_controller_switch_mode(struct wl_client *client,
1776 struct wl_resource *resource,
1777 uint32_t layout_mode)
1778{
1779 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1780
1781 switch_mode(hmi_ctrl, layout_mode);
1782}
1783
1784/**
1785 * Implementation of on/off displaying workspace and workspace background
1786 * ivi_layers.
1787 */
1788static void
1789ivi_hmi_controller_home(struct wl_client *client,
1790 struct wl_resource *resource,
1791 uint32_t home)
1792{
1793 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1794 uint32_t is_fade_in;
1795
1796 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1797 !hmi_ctrl->workspace_fade.is_fade_in) ||
1798 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1799 hmi_ctrl->workspace_fade.is_fade_in)) {
1800 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1801 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1802 &hmi_ctrl->workspace_fade);
1803 }
1804
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001805 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001806}
1807
1808/**
1809 * binding ivi-hmi-controller implementation
1810 */
1811static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1812 ivi_hmi_controller_UI_ready,
1813 ivi_hmi_controller_workspace_control,
1814 ivi_hmi_controller_switch_mode,
1815 ivi_hmi_controller_home
1816};
1817
1818static void
1819unbind_hmi_controller(struct wl_resource *resource)
1820{
1821}
1822
1823static void
1824bind_hmi_controller(struct wl_client *client,
1825 void *data, uint32_t version, uint32_t id)
1826{
1827 struct wl_resource *resource = NULL;
1828 struct hmi_controller *hmi_ctrl = data;
1829
1830 if (hmi_ctrl->user_interface != client) {
1831 struct wl_resource *res = wl_client_get_object(client, 1);
1832 wl_resource_post_error(res,
1833 WL_DISPLAY_ERROR_INVALID_OBJECT,
1834 "hmi-controller failed: permission denied");
1835 return;
1836 }
1837
1838 resource = wl_resource_create(
1839 client, &ivi_hmi_controller_interface, 1, id);
1840
1841 wl_resource_set_implementation(
1842 resource, &ivi_hmi_controller_implementation,
1843 hmi_ctrl, unbind_hmi_controller);
1844}
1845
1846static int32_t
1847initialize(struct hmi_controller *hmi_ctrl)
1848{
1849 struct config_command {
1850 char *key;
1851 uint32_t *dest;
1852 };
1853
1854 struct weston_config *config = hmi_ctrl->compositor->config;
1855 struct weston_config_section *section = NULL;
1856 int result = 0;
1857 int i = 0;
1858
1859 const struct config_command uint_commands[] = {
1860 { "background-id", &hmi_ctrl->ui_setting.background_id },
1861 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1862 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1863 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1864 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1865 { "random-id", &hmi_ctrl->ui_setting.random_id },
1866 { "home-id", &hmi_ctrl->ui_setting.home_id },
1867 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +09001868 { "surface-id-offset", &hmi_ctrl->ui_setting.surface_id_offset },
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001869 { NULL, NULL }
1870 };
1871
1872 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1873
1874 for (i = 0; -1 != result; ++i) {
1875 const struct config_command *command = &uint_commands[i];
1876
1877 if (!command->key)
1878 break;
1879
1880 if (weston_config_section_get_uint(
1881 section, command->key, command->dest, 0) != 0)
1882 result = -1;
1883 }
1884
1885 if (-1 == result) {
1886 weston_log("Failed to initialize hmi-controller\n");
1887 return 0;
1888 }
1889
1890 return 1;
1891}
1892
1893static void
1894launch_hmi_client_process(void *data)
1895{
1896 struct hmi_controller *hmi_ctrl =
1897 (struct hmi_controller *)data;
1898
1899 hmi_ctrl->user_interface =
1900 weston_client_start(hmi_ctrl->compositor,
1901 hmi_ctrl->hmi_setting->ivi_homescreen);
1902
1903 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1904}
1905
1906/*****************************************************************************
1907 * exported functions
1908 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001909WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001910controller_module_init(struct weston_compositor *ec,
1911 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001912 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001913 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001914{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001915 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001916 struct wl_event_loop *loop = NULL;
1917
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001918 if (interface_version < sizeof(struct ivi_layout_interface)) {
Chris Michaelc083af92015-10-01 10:51:29 -04001919 weston_log("ivi-shell: version mismatch of controller interface\n");
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001920 return -1;
1921 }
1922
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001923 ivi_layout_interface = interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001924
1925 hmi_ctrl = hmi_controller_create(ec);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001926 if (hmi_ctrl == NULL)
1927 return -1;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001928
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001929 if (!initialize(hmi_ctrl)) {
1930 return -1;
1931 }
1932
1933 if (wl_global_create(ec->wl_display,
1934 &ivi_hmi_controller_interface, 1,
1935 hmi_ctrl, bind_hmi_controller) == NULL) {
1936 return -1;
1937 }
1938
1939 loop = wl_display_get_event_loop(ec->wl_display);
1940 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1941
1942 return 0;
1943}