blob: 34a7b24bde70ed13716c3e393c20dc658f618f14 [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"
63
64/*****************************************************************************
65 * structure, globals
66 ****************************************************************************/
67struct hmi_controller_layer {
68 struct ivi_layout_layer *ivilayer;
69 uint32_t id_layer;
70 int32_t x;
71 int32_t y;
72 int32_t width;
73 int32_t height;
74};
75
76struct link_layer {
77 struct ivi_layout_layer *layout_layer;
78 struct wl_list link;
79};
80
81struct hmi_controller_fade {
82 uint32_t is_fade_in;
83 struct wl_list layer_list;
84};
85
86struct hmi_server_setting {
87 uint32_t base_layer_id;
88 uint32_t application_layer_id;
89 uint32_t workspace_background_layer_id;
90 uint32_t workspace_layer_id;
91 int32_t panel_height;
92 uint32_t transition_duration;
93 char *ivi_homescreen;
94};
95
96struct ui_setting {
97 uint32_t background_id;
98 uint32_t panel_id;
99 uint32_t tiling_id;
100 uint32_t sidebyside_id;
101 uint32_t fullscreen_id;
102 uint32_t random_id;
103 uint32_t home_id;
104 uint32_t workspace_background_id;
105};
106
107struct hmi_controller {
108 struct hmi_server_setting *hmi_setting;
109 struct hmi_controller_layer base_layer;
110 struct hmi_controller_layer application_layer;
111 struct hmi_controller_layer workspace_background_layer;
112 struct hmi_controller_layer workspace_layer;
113 enum ivi_hmi_controller_layout_mode layout_mode;
114
115 struct hmi_controller_fade workspace_fade;
116
117 int32_t workspace_count;
118 struct wl_array ui_widgets;
119 int32_t is_initialized;
120
121 struct weston_compositor *compositor;
122 struct wl_listener destroy_listener;
123
124 struct wl_client *user_interface;
125 struct ui_setting ui_setting;
126};
127
128struct launcher_info {
129 uint32_t surface_id;
130 uint32_t workspace_id;
131 int32_t index;
132};
133
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900134const struct ivi_controller_interface *ivi_controller_interface;
135
136int
137controller_module_init(struct weston_compositor *ec,
138 int *argc, char *argv[],
139 const struct ivi_controller_interface *interface,
140 size_t interface_version);
141
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900142/*****************************************************************************
143 * local functions
144 ****************************************************************************/
145static void *
146fail_on_null(void *p, size_t size, char *file, int32_t line)
147{
148 if (size && !p) {
149 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
150 exit(EXIT_FAILURE);
151 }
152
153 return p;
154}
155
156static void *
157mem_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{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900168 uint32_t id = ivi_controller_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,
208 struct hmi_controller_layer *layer)
209{
210 const float surface_width = (float)layer->width * 0.25;
211 const float surface_height = (float)layer->height * 0.5;
212 int32_t surface_x = 0;
213 int32_t surface_y = 0;
214 struct ivi_layout_surface *ivisurf = NULL;
215 struct ivi_layout_surface **surfaces;
216 struct ivi_layout_surface **new_order;
217 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
218
219 int32_t i = 0;
220 int32_t surf_num = 0;
221 uint32_t num = 1;
222
223 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
224 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
225
226 for (i = 0; i < surface_length; i++) {
227 ivisurf = pp_surface[i];
228
229 /* skip ui widgets */
230 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
231 continue;
232
233 surfaces[surf_num++] = ivisurf;
234 }
235
236 for (i = 0; i < surf_num; i++) {
237 ivisurf = surfaces[i];
238 new_order[i] = ivisurf;
239
240 if (num <= 8) {
241 if (num < 5) {
242 surface_x = (int32_t)((num - 1) * (surface_width));
243 surface_y = 0;
244 } else {
245 surface_x = (int32_t)((num - 5) * (surface_width));
246 surface_y = (int32_t)surface_height;
247 }
248
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900249 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900250 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
251 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900252 ivi_controller_interface->surface_set_visibility(ivisurf, true);
253 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900254 surface_x, surface_y,
255 (int32_t)surface_width,
256 (int32_t)surface_height);
257
258 num++;
259 continue;
260 }
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900261 ivi_controller_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900262 }
263
264 if (surf_num > 0) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900265 ivi_controller_interface->layer_set_transition(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900266 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
267 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900268 }
269
270 free(surfaces);
271 free(new_order);
272}
273
274static void
275mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
276 struct ivi_layout_surface **pp_surface,
277 int32_t surface_length,
278 struct hmi_controller_layer *layer)
279{
280 int32_t surface_width = layer->width / 2;
281 int32_t surface_height = layer->height;
282 struct ivi_layout_surface *ivisurf = NULL;
283
284 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
285 int32_t i = 0;
286 int32_t num = 1;
287
288 for (i = 0; i < surface_length; i++) {
289 ivisurf = pp_surface[i];
290
291 /* skip ui widgets */
292 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
293 continue;
294
295 if (num == 1) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900296 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900297 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
298 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900299 ivi_controller_interface->surface_set_visibility(ivisurf, true);
300 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900301 0, 0,
302 surface_width,
303 surface_height);
304
305 num++;
306 continue;
307 } else if (num == 2) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900308 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900309 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
310 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900311 ivi_controller_interface->surface_set_visibility(ivisurf, true);
312 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900313 surface_width, 0,
314 surface_width,
315 surface_height);
316
317 num++;
318 continue;
319 }
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900320 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900321 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
322 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900323 ivi_controller_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900324 }
325}
326
327static void
328mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
329 struct ivi_layout_surface **pp_surface,
330 int32_t surface_length,
331 struct hmi_controller_layer *layer)
332{
333 const int32_t surface_width = layer->width;
334 const int32_t surface_height = layer->height;
335 struct ivi_layout_surface *ivisurf = NULL;
336 int32_t i = 0;
337 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
338
339 for (i = 0; i < surface_length; i++) {
340 ivisurf = pp_surface[i];
341
342 /* skip ui widgets */
343 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
344 continue;
345
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900346 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900347 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
348 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900349 ivi_controller_interface->surface_set_visibility(ivisurf, true);
350 ivi_controller_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900351 surface_width,
352 surface_height);
353 }
354}
355
356static void
357mode_random_replace(struct hmi_controller *hmi_ctrl,
358 struct ivi_layout_surface **pp_surface,
359 int32_t surface_length,
360 struct hmi_controller_layer *layer)
361{
362 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
363 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
364 int32_t surface_x = 0;
365 int32_t surface_y = 0;
366 struct ivi_layout_surface *ivisurf = NULL;
367 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
368 int32_t i = 0;
369
370 for (i = 0; i < surface_length; i++) {
371 ivisurf = pp_surface[i];
372
373 /* skip ui widgets */
374 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
375 continue;
376
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900377 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900378 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
379 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900380 ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900381 surface_x = rand() % (layer->width - surface_width);
382 surface_y = rand() % (layer->height - surface_height);
383
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900384 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900385 surface_x,
386 surface_y,
387 surface_width,
388 surface_height);
389 }
390}
391
392static int32_t
393has_application_surface(struct hmi_controller *hmi_ctrl,
394 struct ivi_layout_surface **pp_surface,
395 int32_t surface_length)
396{
397 struct ivi_layout_surface *ivisurf = NULL;
398 int32_t i = 0;
399
400 for (i = 0; i < surface_length; i++) {
401 ivisurf = pp_surface[i];
402
403 /* skip ui widgets */
404 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
405 continue;
406
407 return 1;
408 }
409
410 return 0;
411}
412
413/**
414 * Supports 4 example to layout of application ivi_surfaces;
415 * tiling, side by side, fullscreen, and random.
416 */
417static void
418switch_mode(struct hmi_controller *hmi_ctrl,
419 enum ivi_hmi_controller_layout_mode layout_mode)
420{
421 struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
422 struct ivi_layout_surface **pp_surface = NULL;
423 int32_t surface_length = 0;
424 int32_t ret = 0;
425
426 if (!hmi_ctrl->is_initialized)
427 return;
428
429 hmi_ctrl->layout_mode = layout_mode;
430
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900431 ret = ivi_controller_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900432 assert(!ret);
433
434 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
435 free(pp_surface);
436 pp_surface = NULL;
437 return;
438 }
439
440 switch (layout_mode) {
441 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
442 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
443 layer);
444 break;
445 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
446 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
447 surface_length, layer);
448 break;
449 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
450 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
451 layer);
452 break;
453 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
454 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
455 layer);
456 break;
457 }
458
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900459 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900460 free(pp_surface);
461}
462
463/**
464 * Internal method for transition
465 */
466static void
467hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
468 struct hmi_controller_fade *fade)
469{
470 double tint = is_fade_in ? 1.0 : 0.0;
471 struct link_layer *linklayer = NULL;
472 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
473
474 fade->is_fade_in = is_fade_in;
475
476 wl_list_for_each(linklayer, &fade->layer_list, link) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900477 ivi_controller_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900478 IVI_LAYOUT_TRANSITION_LAYER_FADE,
479 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900480 ivi_controller_interface->layer_set_fade_info(linklayer->layout_layer,
481 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900482 }
483}
484
485/**
486 * Internal method to create ivi_layer with hmi_controller_layer and
487 * add to a ivi_screen
488 */
489static void
490create_layer(struct ivi_layout_screen *iviscrn,
491 struct hmi_controller_layer *layer)
492{
493 int32_t ret = 0;
494
495 layer->ivilayer =
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900496 ivi_controller_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900497 layer->width,
498 layer->height);
499 assert(layer->ivilayer != NULL);
500
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900501 ret = ivi_controller_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900502 assert(!ret);
503
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900504 ret = ivi_controller_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900505 layer->x, layer->y,
506 layer->width,
507 layer->height);
508 assert(!ret);
509
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900510 ret = ivi_controller_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900511 assert(!ret);
512}
513
514/**
515 * Internal set notification
516 */
517static void
518set_notification_create_surface(struct ivi_layout_surface *ivisurf,
519 void *userdata)
520{
521 struct hmi_controller *hmi_ctrl = userdata;
522 struct ivi_layout_layer *application_layer =
523 hmi_ctrl->application_layer.ivilayer;
524 int32_t ret = 0;
525
526 /* skip ui widgets */
527 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
528 return;
529
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900530 ret = ivi_controller_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900531 assert(!ret);
532}
533
534static void
535set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
536 void *userdata)
537{
538 struct hmi_controller *hmi_ctrl = userdata;
539
540 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
541}
542
543static void
544set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
545 void *userdata)
546{
547 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900548 struct ivi_layout_layer *application_layer =
549 hmi_ctrl->application_layer.ivilayer;
550 struct weston_surface *surface;
551 struct ivi_layout_surface **ivisurfs;
552 int32_t length = 0;
553 int32_t i;
554
555 /* return if the surface is not application content */
556 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
557 return;
558 }
559
560 /*
561 * if application changes size of wl_buffer. The source rectangle shall be
562 * fit to the size.
563 */
564 surface = ivi_controller_interface->surface_get_weston_surface(ivisurf);
565 if (surface) {
566 ivi_controller_interface->surface_set_source_rectangle(
567 ivisurf, 0, 0, surface->width,
568 surface->height);
569 }
570
571 /*
572 * search if the surface is already added to layer.
573 * If not yet, it is newly invoded application to go to switch_mode.
574 */
575 ivi_controller_interface->get_surfaces_on_layer(application_layer,
576 &length, &ivisurfs);
577 for (i = 0; i < length; i++) {
578 if (ivisurf == ivisurfs[i]) {
Michael Vetter2a18a522015-05-15 17:17:47 +0200579 /*
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900580 * if it is non new invoked application, just call
581 * commit_changes to apply source_rectangle.
582 */
583 ivi_controller_interface->commit_changes();
584 return;
585 }
586 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900587
588 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
589}
590
591/**
592 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
593 * corresponding ivi_layer are defined in weston.ini. Default scene graph
594 * of ivi_layers are initialized in hmi_controller_create
595 */
596static struct hmi_server_setting *
597hmi_server_setting_create(struct weston_compositor *ec)
598{
599 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
600 struct weston_config *config = ec->config;
601 struct weston_config_section *shell_section = NULL;
602
603 shell_section = weston_config_get_section(config, "ivi-shell",
604 NULL, NULL);
605
606 weston_config_section_get_uint(shell_section, "base-layer-id",
607 &setting->base_layer_id, 1000);
608
609 weston_config_section_get_uint(shell_section,
610 "workspace-background-layer-id",
611 &setting->workspace_background_layer_id,
612 2000);
613
614 weston_config_section_get_uint(shell_section, "workspace-layer-id",
615 &setting->workspace_layer_id, 3000);
616
617 weston_config_section_get_uint(shell_section, "application-layer-id",
618 &setting->application_layer_id, 4000);
619
620 weston_config_section_get_uint(shell_section, "transition-duration",
621 &setting->transition_duration, 300);
622
623 setting->panel_height = 70;
624
625 weston_config_section_get_string(shell_section,
626 "ivi-shell-user-interface",
627 &setting->ivi_homescreen, NULL);
628
629 return setting;
630}
631
632static void
633hmi_controller_destroy(struct wl_listener *listener, void *data)
634{
635 struct link_layer *link = NULL;
636 struct link_layer *next = NULL;
637 struct hmi_controller *hmi_ctrl =
638 container_of(listener, struct hmi_controller, destroy_listener);
639
640 wl_list_for_each_safe(link, next,
641 &hmi_ctrl->workspace_fade.layer_list, link) {
642 wl_list_remove(&link->link);
643 free(link);
644 }
645
646 wl_array_release(&hmi_ctrl->ui_widgets);
647 free(hmi_ctrl->hmi_setting);
648 free(hmi_ctrl);
649}
650
651/**
652 * This is a starting method called from module_init.
653 * This sets up scene graph of ivi_layers; base, application, workspace
654 * background, and workspace. These ivi_layers are created/added to
655 * ivi_screen in create_layer
656 *
657 * base: to group ivi_surfaces of panel and background
658 * application: to group ivi_surfaces of ivi_applications
659 * workspace background: to group a ivi_surface of background in workspace
660 * workspace: to group ivi_surfaces for launching ivi_applications
661 *
662 * ivi_layers of workspace background and workspace is set to invisible at
663 * first. The properties of it is updated with animation when
664 * ivi_hmi_controller_home is requested.
665 */
666static struct hmi_controller *
667hmi_controller_create(struct weston_compositor *ec)
668{
669 struct ivi_layout_screen **pp_screen = NULL;
670 struct ivi_layout_screen *iviscrn = NULL;
671 int32_t screen_length = 0;
672 int32_t screen_width = 0;
673 int32_t screen_height = 0;
674 struct link_layer *tmp_link_layer = NULL;
675 int32_t panel_height = 0;
676 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
677
678 wl_array_init(&hmi_ctrl->ui_widgets);
679 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
680 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
681 hmi_ctrl->compositor = ec;
682
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900683 ivi_controller_interface->get_screens(&screen_length, &pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900684
685 iviscrn = pp_screen[0];
686
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900687 ivi_controller_interface->get_screen_resolution(iviscrn, &screen_width,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900688 &screen_height);
689
690 /* init base ivi_layer*/
691 hmi_ctrl->base_layer.x = 0;
692 hmi_ctrl->base_layer.y = 0;
693 hmi_ctrl->base_layer.width = screen_width;
694 hmi_ctrl->base_layer.height = screen_height;
695 hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
696
697 create_layer(iviscrn, &hmi_ctrl->base_layer);
698
699 panel_height = hmi_ctrl->hmi_setting->panel_height;
700
701 /* init application ivi_layer */
702 hmi_ctrl->application_layer.x = 0;
703 hmi_ctrl->application_layer.y = 0;
704 hmi_ctrl->application_layer.width = screen_width;
705 hmi_ctrl->application_layer.height = screen_height - panel_height;
706 hmi_ctrl->application_layer.id_layer =
707 hmi_ctrl->hmi_setting->application_layer_id;
708
709 create_layer(iviscrn, &hmi_ctrl->application_layer);
710
711 /* init workspace background ivi_layer */
712 hmi_ctrl->workspace_background_layer.x = 0;
713 hmi_ctrl->workspace_background_layer.y = 0;
714 hmi_ctrl->workspace_background_layer.width = screen_width;
715 hmi_ctrl->workspace_background_layer.height =
716 screen_height - panel_height;
717
718 hmi_ctrl->workspace_background_layer.id_layer =
719 hmi_ctrl->hmi_setting->workspace_background_layer_id;
720
721 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900722 ivi_controller_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900723 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900724 ivi_controller_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900725 hmi_ctrl->workspace_background_layer.ivilayer, false);
726
727 /* init workspace ivi_layer */
728 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
729 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
730 hmi_ctrl->workspace_layer.width =
731 hmi_ctrl->workspace_background_layer.width;
732 hmi_ctrl->workspace_layer.height =
733 hmi_ctrl->workspace_background_layer.height;
734 hmi_ctrl->workspace_layer.id_layer =
735 hmi_ctrl->hmi_setting->workspace_layer_id;
736
737 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900738 ivi_controller_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
739 ivi_controller_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900740 false);
741
742 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
743 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
744 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
745 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
746 &tmp_link_layer->link);
747 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
748 tmp_link_layer->layout_layer =
749 hmi_ctrl->workspace_background_layer.ivilayer;
750 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
751 &tmp_link_layer->link);
752
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900753 ivi_controller_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900754 set_notification_create_surface, hmi_ctrl);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900755 ivi_controller_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900756 set_notification_remove_surface, hmi_ctrl);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900757 ivi_controller_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900758 set_notification_configure_surface, hmi_ctrl);
759
760 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
761 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
762 &hmi_ctrl->destroy_listener);
763
764 free(pp_screen);
765 pp_screen = NULL;
766
767 return hmi_ctrl;
768}
769
770/**
771 * Implementations of ivi-hmi-controller.xml
772 */
773
774/**
775 * A ivi_surface drawing background is identified by id_surface.
776 * Properties of the ivi_surface is set by using ivi_layout APIs according to
777 * the scene graph of UI defined in hmi_controller_create.
778 *
779 * UI ivi_layer is used to add this ivi_surface.
780 */
781static void
782ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
783 uint32_t id_surface)
784{
785 struct ivi_layout_surface *ivisurf = NULL;
786 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
787 const int32_t dstx = hmi_ctrl->application_layer.x;
788 const int32_t dsty = hmi_ctrl->application_layer.y;
789 const int32_t width = hmi_ctrl->application_layer.width;
790 const int32_t height = hmi_ctrl->application_layer.height;
791 int32_t ret = 0;
792
793 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
794 sizeof(*add_surface_id));
795 *add_surface_id = id_surface;
796
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900797 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900798 assert(ivisurf != NULL);
799
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900800 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900801 assert(!ret);
802
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900803 ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900804 dstx, dsty, width, height);
805 assert(!ret);
806
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900807 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900808 assert(!ret);
809}
810
811/**
812 * A ivi_surface drawing panel is identified by id_surface.
813 * Properties of the ivi_surface is set by using ivi_layout APIs according to
814 * the scene graph of UI defined in hmi_controller_create.
815 *
816 * UI ivi_layer is used to add this ivi_surface.
817 */
818static void
819ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
820 uint32_t id_surface)
821{
822 struct ivi_layout_surface *ivisurf = NULL;
823 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
824 const int32_t width = hmi_ctrl->base_layer.width;
825 int32_t ret = 0;
826 int32_t panel_height = 0;
827 const int32_t dstx = 0;
828 int32_t dsty = 0;
829
830 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
831 sizeof(*add_surface_id));
832 *add_surface_id = id_surface;
833
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900834 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900835 assert(ivisurf != NULL);
836
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900837 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900838 assert(!ret);
839
840 panel_height = hmi_ctrl->hmi_setting->panel_height;
841
842 dsty = hmi_ctrl->base_layer.height - panel_height;
843
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900844 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900845 ivisurf, dstx, dsty, width, panel_height);
846 assert(!ret);
847
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900848 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900849 assert(!ret);
850}
851
852/**
853 * A ivi_surface drawing buttons in panel is identified by id_surface.
854 * It can set several buttons. Properties of the ivi_surface is set by
855 * using ivi_layout APIs according to the scene graph of UI defined in
856 * hmi_controller_create. Additionally, the position of it is shifted to
857 * right when new one is requested.
858 *
859 * UI ivi_layer is used to add these ivi_surfaces.
860 */
861static void
862ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
863 uint32_t id_surface, int32_t number)
864{
865 struct ivi_layout_surface *ivisurf = NULL;
866 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
867 const int32_t width = 48;
868 const int32_t height = 48;
869 int32_t ret = 0;
870 int32_t panel_height = 0;
871 int32_t dstx = 0;
872 int32_t dsty = 0;
873 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
874 sizeof(*add_surface_id));
875 *add_surface_id = id_surface;
876
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900877 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900878 assert(ivisurf != NULL);
879
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900880 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900881 assert(!ret);
882
883 panel_height = hmi_ctrl->hmi_setting->panel_height;
884
885 dstx = (60 * number) + 15;
886 dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
887
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900888 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900889 ivisurf,dstx, dsty, width, height);
890 assert(!ret);
891
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900892 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900893 assert(!ret);
894}
895
896/**
897 * A ivi_surface drawing home button in panel is identified by id_surface.
898 * Properties of the ivi_surface is set by using ivi_layout APIs according to
899 * the scene graph of UI defined in hmi_controller_create.
900 *
901 * UI ivi_layer is used to add these ivi_surfaces.
902 */
903static void
904ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
905 uint32_t id_surface)
906{
907 struct ivi_layout_surface *ivisurf = NULL;
908 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
909 int32_t ret = 0;
910 int32_t size = 48;
911 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
912 const int32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
913 const int32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
914
915 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
916 sizeof(*add_surface_id));
917 *add_surface_id = id_surface;
918
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900919 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900920 assert(ivisurf != NULL);
921
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900922 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900923 assert(!ret);
924
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900925 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900926 ivisurf, dstx, dsty, size, size);
927 assert(!ret);
928
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900929 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900930 assert(!ret);
931}
932
933/**
934 * A ivi_surface drawing background of workspace is identified by id_surface.
935 * Properties of the ivi_surface is set by using ivi_layout APIs according to
936 * the scene graph of UI defined in hmi_controller_create.
937 *
938 * A ivi_layer of workspace_background is used to add this ivi_surface.
939 */
940static void
941ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
942 uint32_t id_surface)
943{
944 struct ivi_layout_surface *ivisurf = NULL;
945 struct ivi_layout_layer *ivilayer = NULL;
946 const int32_t width = hmi_ctrl->workspace_background_layer.width;
947 const int32_t height = hmi_ctrl->workspace_background_layer.height;
948 int32_t ret = 0;
949
950 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
951 sizeof(*add_surface_id));
952 *add_surface_id = id_surface;
953 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
954
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900955 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900956 assert(ivisurf != NULL);
957
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900958 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900959 assert(!ret);
960
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900961 ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900962 0, 0, width, height);
963 assert(!ret);
964
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900965 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900966 assert(!ret);
967}
968
969/**
970 * A list of ivi_surfaces drawing launchers in workspace is identified by
971 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
972 * APIs according to the scene graph of UI defined in hmi_controller_create.
973 *
974 * The workspace can have several pages to group ivi_surfaces of launcher.
975 * Each call of this interface increments a number of page to add a group
976 * of ivi_surfaces
977 */
978static void
979ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
980 int32_t icon_size)
981{
982 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
983 int32_t minspace_x = 10;
984 int32_t minspace_y = minspace_x;
985
986 int32_t width = hmi_ctrl->workspace_layer.width;
987 int32_t height = hmi_ctrl->workspace_layer.height;
988
989 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
990 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
991 float fcell_size_x = icon_size + space_x;
992
993 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
994 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
995 float fcell_size_y = icon_size + space_y;
996
997 struct weston_config *config = NULL;
998 struct weston_config_section *section = NULL;
999 const char *name = NULL;
1000 int launcher_count = 0;
1001 struct wl_array launchers;
1002 int32_t nx = 0;
1003 int32_t ny = 0;
1004 int32_t prev = -1;
1005 struct launcher_info *data = NULL;
1006
1007 uint32_t surfaceid = 0;
1008 uint32_t workspaceid = 0;
1009 struct launcher_info *info = NULL;
1010
1011 int32_t x = 0;
1012 int32_t y = 0;
1013 int32_t ret = 0;
1014 struct ivi_layout_surface* layout_surface = NULL;
1015 uint32_t *add_surface_id = NULL;
1016
1017 if (0 == x_count)
1018 x_count = 1;
1019
1020 if (0 == y_count)
1021 y_count = 1;
1022
1023 config = hmi_ctrl->compositor->config;
1024 if (!config)
1025 return;
1026
1027 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1028 if (!section)
1029 return;
1030
1031 wl_array_init(&launchers);
1032
1033 while (weston_config_next_section(config, &section, &name)) {
1034 surfaceid = 0;
1035 workspaceid = 0;
1036 info = NULL;
1037 if (0 != strcmp(name, "ivi-launcher"))
1038 continue;
1039
1040 if (0 != weston_config_section_get_uint(section, "icon-id",
1041 &surfaceid, 0))
1042 continue;
1043
1044 if (0 != weston_config_section_get_uint(section,
1045 "workspace-id",
1046 &workspaceid, 0))
1047 continue;
1048
1049 info = wl_array_add(&launchers, sizeof(*info));
1050
1051 if (info) {
1052 info->surface_id = surfaceid;
1053 info->workspace_id = workspaceid;
1054 info->index = launcher_count;
1055 ++launcher_count;
1056 }
1057 }
1058
1059 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1060 compare_launcher_info);
1061
1062 wl_array_for_each(data, &launchers) {
1063 x = 0;
1064 y = 0;
1065 ret = 0;
1066 layout_surface = NULL;
1067 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1068 sizeof(*add_surface_id));
1069
1070 *add_surface_id = data->surface_id;
1071
1072 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1073 nx = 0;
1074 ny = 0;
1075 prev = data->workspace_id;
1076
1077 if (0 <= prev)
1078 hmi_ctrl->workspace_count++;
1079 }
1080
1081 if (y_count == ny) {
1082 ny = 0;
1083 hmi_ctrl->workspace_count++;
1084 }
1085
1086 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1087 y = ny * fcell_size_y + space_y;
1088
1089 layout_surface =
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001090 ivi_controller_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001091 assert(layout_surface);
1092
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001093 ret = ivi_controller_interface->layer_add_surface(layer, layout_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001094 assert(!ret);
1095
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001096 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001097 layout_surface, x, y, icon_size, icon_size);
1098 assert(!ret);
1099
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001100 ret = ivi_controller_interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001101 assert(!ret);
1102
1103 nx++;
1104
1105 if (x_count == nx) {
1106 ny++;
1107 nx = 0;
1108 }
1109 }
1110
1111 wl_array_release(&launchers);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001112 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001113}
1114
1115static void
1116ivi_hmi_controller_UI_ready(struct wl_client *client,
1117 struct wl_resource *resource)
1118{
1119 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1120
1121 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1122 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1123 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1124 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1125 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1126 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1127 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1128 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001129 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001130
1131 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1132 hmi_ctrl->is_initialized = 1;
1133}
1134
1135/**
1136 * Implementation of request and event of ivi_hmi_controller_workspace_control
1137 * and controlling workspace.
1138 *
1139 * When motion of input is detected in a ivi_surface of workspace background,
1140 * ivi_hmi_controller_workspace_control shall be invoked and to start
1141 * controlling of workspace. The workspace has several pages to show several
1142 * groups of applications.
1143 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1144 * according to motion. When motion finished, e.g. touch up detected, control is
1145 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1146 */
1147struct pointer_grab {
1148 struct weston_pointer_grab grab;
1149 struct ivi_layout_layer *layer;
1150 struct wl_resource *resource;
1151};
1152
1153struct touch_grab {
1154 struct weston_touch_grab grab;
1155 struct ivi_layout_layer *layer;
1156 struct wl_resource *resource;
1157};
1158
1159struct move_grab {
1160 wl_fixed_t dst[2];
1161 wl_fixed_t rgn[2][2];
1162 double v[2];
1163 struct timespec start_time;
1164 struct timespec pre_time;
1165 wl_fixed_t start_pos[2];
1166 wl_fixed_t pos[2];
1167 int32_t is_moved;
1168};
1169
1170struct pointer_move_grab {
1171 struct pointer_grab base;
1172 struct move_grab move;
1173};
1174
1175struct touch_move_grab {
1176 struct touch_grab base;
1177 struct move_grab move;
1178 int32_t is_active;
1179};
1180
1181static void
1182pointer_grab_start(struct pointer_grab *grab,
1183 struct ivi_layout_layer *layer,
1184 const struct weston_pointer_grab_interface *interface,
1185 struct weston_pointer *pointer)
1186{
1187 grab->grab.interface = interface;
1188 grab->layer = layer;
1189 weston_pointer_start_grab(pointer, &grab->grab);
1190}
1191
1192static void
1193touch_grab_start(struct touch_grab *grab,
1194 struct ivi_layout_layer *layer,
1195 const struct weston_touch_grab_interface *interface,
1196 struct weston_touch* touch)
1197{
1198 grab->grab.interface = interface;
1199 grab->layer = layer;
1200 weston_touch_start_grab(touch, &grab->grab);
1201}
1202
1203static int32_t
1204clamp(int32_t val, int32_t min, int32_t max)
1205{
1206 if (val < min)
1207 return min;
1208
1209 if (max < val)
1210 return max;
1211
1212 return val;
1213}
1214
1215static void
1216move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1217 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1218{
1219 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1220 int32_t width = hmi_ctrl->workspace_background_layer.width;
1221
1222 struct timespec time = {0};
1223 double grab_time = 0.0;
1224 double from_motion_time = 0.0;
1225 double pointer_v = 0.0;
1226 int32_t is_flick = 0;
1227 int32_t pos_x = 0;
1228 int32_t pos_y = 0;
1229 int page_no = 0;
1230 double end_pos = 0.0;
1231 uint32_t duration = 0;
1232
1233 clock_gettime(CLOCK_MONOTONIC, &time);
1234
1235 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1236 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1237
1238 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1239 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1240
1241 pointer_v = move->v[0];
1242
1243 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1244 if (200 < from_motion_time)
1245 pointer_v = 0.0;
1246
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001247 ivi_controller_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001248
1249
1250 if (is_flick) {
1251 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1252 page_no = (-orgx + width / 2) / width;
1253
1254 if (pointer_v < 0.0)
1255 page_no++;
1256 else
1257 page_no--;
1258 } else {
1259 page_no = (-pos_x + width / 2) / width;
1260 }
1261
1262 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1263 end_pos = -page_no * width;
1264
1265 duration = hmi_ctrl->hmi_setting->transition_duration;
1266 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001267 ivi_controller_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001268 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1269 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001270 ivi_controller_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001271 end_pos, pos_y,
1272 hmi_ctrl->workspace_background_layer.width,
1273 hmi_ctrl->workspace_background_layer.height);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001274 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001275}
1276
1277static void
1278pointer_move_workspace_grab_end(struct pointer_grab *grab)
1279{
1280 struct pointer_move_grab *pnt_move_grab =
1281 (struct pointer_move_grab *)grab;
1282 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1283
1284 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1285 grab->grab.pointer->grab_x, layer);
1286
1287 weston_pointer_end_grab(grab->grab.pointer);
1288}
1289
1290static void
1291touch_move_workspace_grab_end(struct touch_grab *grab)
1292{
1293 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1294 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1295
1296 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1297 grab->grab.touch->grab_x, layer);
1298
1299 weston_touch_end_grab(grab->grab.touch);
1300}
1301
1302static void
1303pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1304{
1305}
1306
1307static void
1308move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1309{
1310 struct timespec timestamp = {0};
1311 int32_t ii = 0;
1312 double dt = 0.0;
1313
1314 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1315 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1316 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1317
1318 if (dt < 1e-6)
1319 dt = 1e-6;
1320
1321 move->pre_time = timestamp;
1322
1323 for (ii = 0; ii < 2; ii++) {
1324 wl_fixed_t prepos = move->pos[ii];
1325 move->pos[ii] = pointer[ii] + move->dst[ii];
1326
1327 if (move->pos[ii] < move->rgn[0][ii]) {
1328 move->pos[ii] = move->rgn[0][ii];
1329 move->dst[ii] = move->pos[ii] - pointer[ii];
1330 } else if (move->rgn[1][ii] < move->pos[ii]) {
1331 move->pos[ii] = move->rgn[1][ii];
1332 move->dst[ii] = move->pos[ii] - pointer[ii];
1333 }
1334
1335 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1336
1337 if (!move->is_moved &&
1338 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1339 move->is_moved = 1;
1340 }
1341}
1342
1343static void
1344layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1345 wl_fixed_t pos_y)
1346{
1347 int32_t layout_pos_x = 0;
1348 int32_t layout_pos_y = 0;
1349
1350 layout_pos_x = wl_fixed_to_int(pos_x);
1351 layout_pos_y = wl_fixed_to_int(pos_y);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001352 ivi_controller_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1353 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001354}
1355
1356static void
1357pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1358 wl_fixed_t x, wl_fixed_t y)
1359{
1360 struct pointer_move_grab *pnt_move_grab =
1361 (struct pointer_move_grab *)grab;
1362 wl_fixed_t pointer_pos[2] = {x, y};
1363
1364 move_grab_update(&pnt_move_grab->move, pointer_pos);
1365 layer_set_pos(pnt_move_grab->base.layer,
1366 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
1367 weston_pointer_move(pnt_move_grab->base.grab.pointer, x, y);
1368}
1369
1370static void
1371touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1372 int touch_id, wl_fixed_t x, wl_fixed_t y)
1373{
1374 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1375
1376 if (!tch_move_grab->is_active)
1377 return;
1378
1379 wl_fixed_t pointer_pos[2] = {
1380 grab->touch->grab_x,
1381 grab->touch->grab_y
1382 };
1383
1384 move_grab_update(&tch_move_grab->move, pointer_pos);
1385 layer_set_pos(tch_move_grab->base.layer,
1386 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1387}
1388
1389static void
1390pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1391 uint32_t time, uint32_t button,
1392 uint32_t state_w)
1393{
1394 if (BTN_LEFT == button &&
1395 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1396 struct pointer_grab *pg = (struct pointer_grab *)grab;
1397
1398 pointer_move_workspace_grab_end(pg);
1399 free(grab);
1400 }
1401}
1402
1403static void
1404touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1405 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1406{
1407}
1408
1409static void
1410touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1411 int touch_id)
1412{
1413 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1414
1415 if (0 == touch_id)
1416 tch_move_grab->is_active = 0;
1417
1418 if (0 == grab->touch->num_tp) {
1419 touch_move_workspace_grab_end(&tch_move_grab->base);
1420 free(grab);
1421 }
1422}
1423
1424static void
1425pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1426{
1427 struct pointer_grab *pg = (struct pointer_grab *)grab;
1428
1429 pointer_move_workspace_grab_end(pg);
1430 free(grab);
1431}
1432
1433static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001434touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1435{
1436}
1437
1438static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001439touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1440{
1441 struct touch_grab *tg = (struct touch_grab *)grab;
1442
1443 touch_move_workspace_grab_end(tg);
1444 free(grab);
1445}
1446
1447static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1448 pointer_noop_grab_focus,
1449 pointer_move_grab_motion,
1450 pointer_move_workspace_grab_button,
1451 pointer_move_workspace_grab_cancel
1452};
1453
1454static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1455 touch_nope_grab_down,
1456 touch_move_workspace_grab_up,
1457 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001458 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001459 touch_move_workspace_grab_cancel
1460};
1461
1462enum HMI_GRAB_DEVICE {
1463 HMI_GRAB_DEVICE_NONE,
1464 HMI_GRAB_DEVICE_POINTER,
1465 HMI_GRAB_DEVICE_TOUCH
1466};
1467
1468static enum HMI_GRAB_DEVICE
1469get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1470{
1471 if (seat->pointer &&
1472 seat->pointer->focus &&
1473 seat->pointer->button_count &&
1474 seat->pointer->grab_serial == serial)
1475 return HMI_GRAB_DEVICE_POINTER;
1476
1477 if (seat->touch &&
1478 seat->touch->focus &&
1479 seat->touch->grab_serial == serial)
1480 return HMI_GRAB_DEVICE_TOUCH;
1481
1482 return HMI_GRAB_DEVICE_NONE;
1483}
1484
1485static void
1486move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1487 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1488 struct wl_resource* resource)
1489{
1490 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1491 move->pre_time = move->start_time;
1492 move->pos[0] = start_pos[0];
1493 move->pos[1] = start_pos[1];
1494 move->start_pos[0] = start_pos[0];
1495 move->start_pos[1] = start_pos[1];
1496 move->dst[0] = start_pos[0] - grab_pos[0];
1497 move->dst[1] = start_pos[1] - grab_pos[1];
1498 memcpy(move->rgn, rgn, sizeof(move->rgn));
1499}
1500
1501static void
1502move_grab_init_workspace(struct move_grab* move,
1503 wl_fixed_t grab_x, wl_fixed_t grab_y,
1504 struct wl_resource *resource)
1505{
1506 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1507 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1508 int32_t workspace_count = hmi_ctrl->workspace_count;
1509 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1510 int32_t layer_pos_x = 0;
1511 int32_t layer_pos_y = 0;
1512 wl_fixed_t start_pos[2] = {0};
1513 wl_fixed_t rgn[2][2] = {{0}};
1514 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1515
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001516 ivi_controller_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001517
1518 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1519 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1520
1521 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1522
1523 rgn[0][1] = wl_fixed_from_int(0);
1524 rgn[1][0] = wl_fixed_from_int(0);
1525 rgn[1][1] = wl_fixed_from_int(0);
1526
1527 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1528}
1529
1530static struct pointer_move_grab *
1531create_workspace_pointer_move(struct weston_pointer *pointer,
1532 struct wl_resource* resource)
1533{
1534 struct pointer_move_grab *pnt_move_grab =
1535 MEM_ALLOC(sizeof(*pnt_move_grab));
1536
1537 pnt_move_grab->base.resource = resource;
1538 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1539 pointer->grab_y, resource);
1540
1541 return pnt_move_grab;
1542}
1543
1544static struct touch_move_grab *
1545create_workspace_touch_move(struct weston_touch *touch,
1546 struct wl_resource* resource)
1547{
1548 struct touch_move_grab *tch_move_grab =
1549 MEM_ALLOC(sizeof(*tch_move_grab));
1550
1551 tch_move_grab->base.resource = resource;
1552 tch_move_grab->is_active = 1;
1553 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1554 touch->grab_y, resource);
1555
1556 return tch_move_grab;
1557}
1558
1559static void
1560ivi_hmi_controller_workspace_control(struct wl_client *client,
1561 struct wl_resource *resource,
1562 struct wl_resource *seat_resource,
1563 uint32_t serial)
1564{
1565 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1566 struct ivi_layout_layer *layer = NULL;
1567 struct pointer_move_grab *pnt_move_grab = NULL;
1568 struct touch_move_grab *tch_move_grab = NULL;
1569 struct weston_seat *seat = NULL;
1570 enum HMI_GRAB_DEVICE device;
1571
1572 if (hmi_ctrl->workspace_count < 2)
1573 return;
1574
1575 seat = wl_resource_get_user_data(seat_resource);
1576 device = get_hmi_grab_device(seat, serial);
1577
1578 if (HMI_GRAB_DEVICE_POINTER != device &&
1579 HMI_GRAB_DEVICE_TOUCH != device)
1580 return;
1581
1582 layer = hmi_ctrl->workspace_layer.ivilayer;
1583
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001584 ivi_controller_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001585
1586 switch (device) {
1587 case HMI_GRAB_DEVICE_POINTER:
1588 pnt_move_grab = create_workspace_pointer_move(seat->pointer,
1589 resource);
1590
1591 pointer_grab_start(&pnt_move_grab->base, layer,
1592 &pointer_move_grab_workspace_interface,
1593 seat->pointer);
1594 break;
1595
1596 case HMI_GRAB_DEVICE_TOUCH:
1597 tch_move_grab = create_workspace_touch_move(seat->touch,
1598 resource);
1599
1600 touch_grab_start(&tch_move_grab->base, layer,
1601 &touch_move_grab_workspace_interface,
1602 seat->touch);
1603 break;
1604
1605 default:
1606 break;
1607 }
1608}
1609
1610/**
1611 * Implementation of switch_mode
1612 */
1613static void
1614ivi_hmi_controller_switch_mode(struct wl_client *client,
1615 struct wl_resource *resource,
1616 uint32_t layout_mode)
1617{
1618 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1619
1620 switch_mode(hmi_ctrl, layout_mode);
1621}
1622
1623/**
1624 * Implementation of on/off displaying workspace and workspace background
1625 * ivi_layers.
1626 */
1627static void
1628ivi_hmi_controller_home(struct wl_client *client,
1629 struct wl_resource *resource,
1630 uint32_t home)
1631{
1632 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1633 uint32_t is_fade_in;
1634
1635 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1636 !hmi_ctrl->workspace_fade.is_fade_in) ||
1637 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1638 hmi_ctrl->workspace_fade.is_fade_in)) {
1639 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1640 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1641 &hmi_ctrl->workspace_fade);
1642 }
1643
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001644 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001645}
1646
1647/**
1648 * binding ivi-hmi-controller implementation
1649 */
1650static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1651 ivi_hmi_controller_UI_ready,
1652 ivi_hmi_controller_workspace_control,
1653 ivi_hmi_controller_switch_mode,
1654 ivi_hmi_controller_home
1655};
1656
1657static void
1658unbind_hmi_controller(struct wl_resource *resource)
1659{
1660}
1661
1662static void
1663bind_hmi_controller(struct wl_client *client,
1664 void *data, uint32_t version, uint32_t id)
1665{
1666 struct wl_resource *resource = NULL;
1667 struct hmi_controller *hmi_ctrl = data;
1668
1669 if (hmi_ctrl->user_interface != client) {
1670 struct wl_resource *res = wl_client_get_object(client, 1);
1671 wl_resource_post_error(res,
1672 WL_DISPLAY_ERROR_INVALID_OBJECT,
1673 "hmi-controller failed: permission denied");
1674 return;
1675 }
1676
1677 resource = wl_resource_create(
1678 client, &ivi_hmi_controller_interface, 1, id);
1679
1680 wl_resource_set_implementation(
1681 resource, &ivi_hmi_controller_implementation,
1682 hmi_ctrl, unbind_hmi_controller);
1683}
1684
1685static int32_t
1686initialize(struct hmi_controller *hmi_ctrl)
1687{
1688 struct config_command {
1689 char *key;
1690 uint32_t *dest;
1691 };
1692
1693 struct weston_config *config = hmi_ctrl->compositor->config;
1694 struct weston_config_section *section = NULL;
1695 int result = 0;
1696 int i = 0;
1697
1698 const struct config_command uint_commands[] = {
1699 { "background-id", &hmi_ctrl->ui_setting.background_id },
1700 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1701 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1702 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1703 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1704 { "random-id", &hmi_ctrl->ui_setting.random_id },
1705 { "home-id", &hmi_ctrl->ui_setting.home_id },
1706 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
1707 { NULL, NULL }
1708 };
1709
1710 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1711
1712 for (i = 0; -1 != result; ++i) {
1713 const struct config_command *command = &uint_commands[i];
1714
1715 if (!command->key)
1716 break;
1717
1718 if (weston_config_section_get_uint(
1719 section, command->key, command->dest, 0) != 0)
1720 result = -1;
1721 }
1722
1723 if (-1 == result) {
1724 weston_log("Failed to initialize hmi-controller\n");
1725 return 0;
1726 }
1727
1728 return 1;
1729}
1730
1731static void
1732launch_hmi_client_process(void *data)
1733{
1734 struct hmi_controller *hmi_ctrl =
1735 (struct hmi_controller *)data;
1736
1737 hmi_ctrl->user_interface =
1738 weston_client_start(hmi_ctrl->compositor,
1739 hmi_ctrl->hmi_setting->ivi_homescreen);
1740
1741 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1742}
1743
1744/*****************************************************************************
1745 * exported functions
1746 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001747WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001748controller_module_init(struct weston_compositor *ec,
1749 int *argc, char *argv[],
1750 const struct ivi_controller_interface *interface,
1751 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001752{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001753 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001754 struct wl_event_loop *loop = NULL;
1755
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001756 if (interface_version < sizeof(struct ivi_controller_interface)) {
1757 weston_log("ivi-shell: version mismatch of controller interface");
1758 return -1;
1759 }
1760
1761 ivi_controller_interface = interface;
1762
1763 hmi_ctrl = hmi_controller_create(ec);
1764
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001765 if (!initialize(hmi_ctrl)) {
1766 return -1;
1767 }
1768
1769 if (wl_global_create(ec->wl_display,
1770 &ivi_hmi_controller_interface, 1,
1771 hmi_ctrl, bind_hmi_controller) == NULL) {
1772 return -1;
1773 }
1774
1775 loop = wl_display_get_event_loop(ec->wl_display);
1776 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1777
1778 return 0;
1779}