blob: cd79c3867bfea8f6f98a6d0bd873d7d61c56ea27 [file] [log] [blame]
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001/*
2 * Copyright (C) 2014 DENSO CORPORATION
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23/**
24 * A reference implementation how to use ivi-layout APIs in order to manage
25 * layout of ivi_surfaces/ivi_layers. Layout change is triggered by
26 * ivi-hmi-controller protocol, ivi-hmi-controller.xml. A reference how to
27 * use the protocol, see hmi-controller-homescreen.
28 *
29 * In-Vehicle Infotainment system usually manage properties of
30 * ivi_surfaces/ivi_layers by only a central component which decide where
31 * ivi_surfaces/ivi_layers shall be. This reference show examples to
32 * implement the central component as a module of weston.
33 *
34 * Default Scene graph of UI is defined in hmi_controller_create. It
35 * consists of
36 * - In the bottom, a base ivi_layer to group ivi_surfaces of background,
37 * panel, and buttons
38 * - Next, a application ivi_layer to show application ivi_surfaces.
39 * - Workspace background ivi_layer to show a ivi_surface of background image.
40 * - Workspace ivi_layer to show launcher to launch application with icons.
41 * Paths to binary and icon are defined in weston.ini. The width of this
42 * ivi_layer is longer than the size of ivi_screen because a workspace has
43 * several pages and is controlled by motion of input.
44 *
45 * TODO: animation method shall be refined
46 * TODO: support fade-in when UI is ready
47 */
48
49#include <sys/wait.h>
50#include <unistd.h>
51#include <stdlib.h>
52#include <stdio.h>
53#include <string.h>
54#include <linux/input.h>
55#include <assert.h>
56#include <time.h>
57
58#include "ivi-layout-export.h"
59#include "ivi-hmi-controller-server-protocol.h"
60
61/*****************************************************************************
62 * structure, globals
63 ****************************************************************************/
64struct hmi_controller_layer {
65 struct ivi_layout_layer *ivilayer;
66 uint32_t id_layer;
67 int32_t x;
68 int32_t y;
69 int32_t width;
70 int32_t height;
71};
72
73struct link_layer {
74 struct ivi_layout_layer *layout_layer;
75 struct wl_list link;
76};
77
78struct hmi_controller_fade {
79 uint32_t is_fade_in;
80 struct wl_list layer_list;
81};
82
83struct hmi_server_setting {
84 uint32_t base_layer_id;
85 uint32_t application_layer_id;
86 uint32_t workspace_background_layer_id;
87 uint32_t workspace_layer_id;
88 int32_t panel_height;
89 uint32_t transition_duration;
90 char *ivi_homescreen;
91};
92
93struct ui_setting {
94 uint32_t background_id;
95 uint32_t panel_id;
96 uint32_t tiling_id;
97 uint32_t sidebyside_id;
98 uint32_t fullscreen_id;
99 uint32_t random_id;
100 uint32_t home_id;
101 uint32_t workspace_background_id;
102};
103
104struct hmi_controller {
105 struct hmi_server_setting *hmi_setting;
106 struct hmi_controller_layer base_layer;
107 struct hmi_controller_layer application_layer;
108 struct hmi_controller_layer workspace_background_layer;
109 struct hmi_controller_layer workspace_layer;
110 enum ivi_hmi_controller_layout_mode layout_mode;
111
112 struct hmi_controller_fade workspace_fade;
113
114 int32_t workspace_count;
115 struct wl_array ui_widgets;
116 int32_t is_initialized;
117
118 struct weston_compositor *compositor;
119 struct wl_listener destroy_listener;
120
121 struct wl_client *user_interface;
122 struct ui_setting ui_setting;
123};
124
125struct launcher_info {
126 uint32_t surface_id;
127 uint32_t workspace_id;
128 int32_t index;
129};
130
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900131const struct ivi_controller_interface *ivi_controller_interface;
132
133int
134controller_module_init(struct weston_compositor *ec,
135 int *argc, char *argv[],
136 const struct ivi_controller_interface *interface,
137 size_t interface_version);
138
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900139/*****************************************************************************
140 * local functions
141 ****************************************************************************/
142static void *
143fail_on_null(void *p, size_t size, char *file, int32_t line)
144{
145 if (size && !p) {
146 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
147 exit(EXIT_FAILURE);
148 }
149
150 return p;
151}
152
153static void *
154mem_alloc(size_t size, char *file, int32_t line)
155{
156 return fail_on_null(calloc(1, size), size, file, line);
157}
158
159#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
160
161static int32_t
162is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
163 struct ivi_layout_surface *ivisurf)
164{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900165 uint32_t id = ivi_controller_interface->get_id_of_surface(ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900166
167 uint32_t *ui_widget_id = NULL;
168 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
169 if (*ui_widget_id == id)
170 return 1;
171 }
172
173 return 0;
174}
175
176static int
177compare_launcher_info(const void *lhs, const void *rhs)
178{
179 const struct launcher_info *left = lhs;
180 const struct launcher_info *right = rhs;
181
182 if (left->workspace_id < right->workspace_id)
183 return -1;
184
185 if (left->workspace_id > right->workspace_id)
186 return 1;
187
188 if (left->index < right->index)
189 return -1;
190
191 if (left->index > right->index)
192 return 1;
193
194 return 0;
195}
196
197/**
198 * Internal methods called by mainly ivi_hmi_controller_switch_mode
199 * This reference shows 4 examples how to use ivi_layout APIs.
200 */
201static void
202mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
203 struct ivi_layout_surface **pp_surface,
204 int32_t surface_length,
205 struct hmi_controller_layer *layer)
206{
207 const float surface_width = (float)layer->width * 0.25;
208 const float surface_height = (float)layer->height * 0.5;
209 int32_t surface_x = 0;
210 int32_t surface_y = 0;
211 struct ivi_layout_surface *ivisurf = NULL;
212 struct ivi_layout_surface **surfaces;
213 struct ivi_layout_surface **new_order;
214 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
215
216 int32_t i = 0;
217 int32_t surf_num = 0;
218 uint32_t num = 1;
219
220 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
221 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
222
223 for (i = 0; i < surface_length; i++) {
224 ivisurf = pp_surface[i];
225
226 /* skip ui widgets */
227 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
228 continue;
229
230 surfaces[surf_num++] = ivisurf;
231 }
232
233 for (i = 0; i < surf_num; i++) {
234 ivisurf = surfaces[i];
235 new_order[i] = ivisurf;
236
237 if (num <= 8) {
238 if (num < 5) {
239 surface_x = (int32_t)((num - 1) * (surface_width));
240 surface_y = 0;
241 } else {
242 surface_x = (int32_t)((num - 5) * (surface_width));
243 surface_y = (int32_t)surface_height;
244 }
245
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900246 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900247 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
248 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900249 ivi_controller_interface->surface_set_visibility(ivisurf, true);
250 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900251 surface_x, surface_y,
252 (int32_t)surface_width,
253 (int32_t)surface_height);
254
255 num++;
256 continue;
257 }
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900258 ivi_controller_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900259 }
260
261 if (surf_num > 0) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900262 ivi_controller_interface->layer_set_transition(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900263 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
264 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900265 }
266
267 free(surfaces);
268 free(new_order);
269}
270
271static void
272mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
273 struct ivi_layout_surface **pp_surface,
274 int32_t surface_length,
275 struct hmi_controller_layer *layer)
276{
277 int32_t surface_width = layer->width / 2;
278 int32_t surface_height = layer->height;
279 struct ivi_layout_surface *ivisurf = NULL;
280
281 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
282 int32_t i = 0;
283 int32_t num = 1;
284
285 for (i = 0; i < surface_length; i++) {
286 ivisurf = pp_surface[i];
287
288 /* skip ui widgets */
289 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
290 continue;
291
292 if (num == 1) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900293 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900294 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
295 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900296 ivi_controller_interface->surface_set_visibility(ivisurf, true);
297 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900298 0, 0,
299 surface_width,
300 surface_height);
301
302 num++;
303 continue;
304 } else if (num == 2) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900305 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900306 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
307 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900308 ivi_controller_interface->surface_set_visibility(ivisurf, true);
309 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900310 surface_width, 0,
311 surface_width,
312 surface_height);
313
314 num++;
315 continue;
316 }
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900317 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900318 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
319 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900320 ivi_controller_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900321 }
322}
323
324static void
325mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
326 struct ivi_layout_surface **pp_surface,
327 int32_t surface_length,
328 struct hmi_controller_layer *layer)
329{
330 const int32_t surface_width = layer->width;
331 const int32_t surface_height = layer->height;
332 struct ivi_layout_surface *ivisurf = NULL;
333 int32_t i = 0;
334 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
335
336 for (i = 0; i < surface_length; i++) {
337 ivisurf = pp_surface[i];
338
339 /* skip ui widgets */
340 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
341 continue;
342
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900343 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900344 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
345 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900346 ivi_controller_interface->surface_set_visibility(ivisurf, true);
347 ivi_controller_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900348 surface_width,
349 surface_height);
350 }
351}
352
353static void
354mode_random_replace(struct hmi_controller *hmi_ctrl,
355 struct ivi_layout_surface **pp_surface,
356 int32_t surface_length,
357 struct hmi_controller_layer *layer)
358{
359 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
360 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
361 int32_t surface_x = 0;
362 int32_t surface_y = 0;
363 struct ivi_layout_surface *ivisurf = NULL;
364 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
365 int32_t i = 0;
366
367 for (i = 0; i < surface_length; i++) {
368 ivisurf = pp_surface[i];
369
370 /* skip ui widgets */
371 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
372 continue;
373
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900374 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900375 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
376 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900377 ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900378 surface_x = rand() % (layer->width - surface_width);
379 surface_y = rand() % (layer->height - surface_height);
380
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900381 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900382 surface_x,
383 surface_y,
384 surface_width,
385 surface_height);
386 }
387}
388
389static int32_t
390has_application_surface(struct hmi_controller *hmi_ctrl,
391 struct ivi_layout_surface **pp_surface,
392 int32_t surface_length)
393{
394 struct ivi_layout_surface *ivisurf = NULL;
395 int32_t i = 0;
396
397 for (i = 0; i < surface_length; i++) {
398 ivisurf = pp_surface[i];
399
400 /* skip ui widgets */
401 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
402 continue;
403
404 return 1;
405 }
406
407 return 0;
408}
409
410/**
411 * Supports 4 example to layout of application ivi_surfaces;
412 * tiling, side by side, fullscreen, and random.
413 */
414static void
415switch_mode(struct hmi_controller *hmi_ctrl,
416 enum ivi_hmi_controller_layout_mode layout_mode)
417{
418 struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
419 struct ivi_layout_surface **pp_surface = NULL;
420 int32_t surface_length = 0;
421 int32_t ret = 0;
422
423 if (!hmi_ctrl->is_initialized)
424 return;
425
426 hmi_ctrl->layout_mode = layout_mode;
427
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900428 ret = ivi_controller_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900429 assert(!ret);
430
431 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
432 free(pp_surface);
433 pp_surface = NULL;
434 return;
435 }
436
437 switch (layout_mode) {
438 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
439 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
440 layer);
441 break;
442 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
443 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
444 surface_length, layer);
445 break;
446 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
447 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
448 layer);
449 break;
450 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
451 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
452 layer);
453 break;
454 }
455
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900456 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900457 free(pp_surface);
458}
459
460/**
461 * Internal method for transition
462 */
463static void
464hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
465 struct hmi_controller_fade *fade)
466{
467 double tint = is_fade_in ? 1.0 : 0.0;
468 struct link_layer *linklayer = NULL;
469 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
470
471 fade->is_fade_in = is_fade_in;
472
473 wl_list_for_each(linklayer, &fade->layer_list, link) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900474 ivi_controller_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900475 IVI_LAYOUT_TRANSITION_LAYER_FADE,
476 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900477 ivi_controller_interface->layer_set_fade_info(linklayer->layout_layer,
478 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900479 }
480}
481
482/**
483 * Internal method to create ivi_layer with hmi_controller_layer and
484 * add to a ivi_screen
485 */
486static void
487create_layer(struct ivi_layout_screen *iviscrn,
488 struct hmi_controller_layer *layer)
489{
490 int32_t ret = 0;
491
492 layer->ivilayer =
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900493 ivi_controller_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900494 layer->width,
495 layer->height);
496 assert(layer->ivilayer != NULL);
497
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900498 ret = ivi_controller_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900499 assert(!ret);
500
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900501 ret = ivi_controller_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900502 layer->x, layer->y,
503 layer->width,
504 layer->height);
505 assert(!ret);
506
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900507 ret = ivi_controller_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900508 assert(!ret);
509}
510
511/**
512 * Internal set notification
513 */
514static void
515set_notification_create_surface(struct ivi_layout_surface *ivisurf,
516 void *userdata)
517{
518 struct hmi_controller *hmi_ctrl = userdata;
519 struct ivi_layout_layer *application_layer =
520 hmi_ctrl->application_layer.ivilayer;
521 int32_t ret = 0;
522
523 /* skip ui widgets */
524 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
525 return;
526
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900527 ret = ivi_controller_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900528 assert(!ret);
529}
530
531static void
532set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
533 void *userdata)
534{
535 struct hmi_controller *hmi_ctrl = userdata;
536
537 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
538}
539
540static void
541set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
542 void *userdata)
543{
544 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900545 struct ivi_layout_layer *application_layer =
546 hmi_ctrl->application_layer.ivilayer;
547 struct weston_surface *surface;
548 struct ivi_layout_surface **ivisurfs;
549 int32_t length = 0;
550 int32_t i;
551
552 /* return if the surface is not application content */
553 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
554 return;
555 }
556
557 /*
558 * if application changes size of wl_buffer. The source rectangle shall be
559 * fit to the size.
560 */
561 surface = ivi_controller_interface->surface_get_weston_surface(ivisurf);
562 if (surface) {
563 ivi_controller_interface->surface_set_source_rectangle(
564 ivisurf, 0, 0, surface->width,
565 surface->height);
566 }
567
568 /*
569 * search if the surface is already added to layer.
570 * If not yet, it is newly invoded application to go to switch_mode.
571 */
572 ivi_controller_interface->get_surfaces_on_layer(application_layer,
573 &length, &ivisurfs);
574 for (i = 0; i < length; i++) {
575 if (ivisurf == ivisurfs[i]) {
576 /*
577 * if it is non new invoked application, just call
578 * commit_changes to apply source_rectangle.
579 */
580 ivi_controller_interface->commit_changes();
581 return;
582 }
583 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900584
585 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
586}
587
588/**
589 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
590 * corresponding ivi_layer are defined in weston.ini. Default scene graph
591 * of ivi_layers are initialized in hmi_controller_create
592 */
593static struct hmi_server_setting *
594hmi_server_setting_create(struct weston_compositor *ec)
595{
596 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
597 struct weston_config *config = ec->config;
598 struct weston_config_section *shell_section = NULL;
599
600 shell_section = weston_config_get_section(config, "ivi-shell",
601 NULL, NULL);
602
603 weston_config_section_get_uint(shell_section, "base-layer-id",
604 &setting->base_layer_id, 1000);
605
606 weston_config_section_get_uint(shell_section,
607 "workspace-background-layer-id",
608 &setting->workspace_background_layer_id,
609 2000);
610
611 weston_config_section_get_uint(shell_section, "workspace-layer-id",
612 &setting->workspace_layer_id, 3000);
613
614 weston_config_section_get_uint(shell_section, "application-layer-id",
615 &setting->application_layer_id, 4000);
616
617 weston_config_section_get_uint(shell_section, "transition-duration",
618 &setting->transition_duration, 300);
619
620 setting->panel_height = 70;
621
622 weston_config_section_get_string(shell_section,
623 "ivi-shell-user-interface",
624 &setting->ivi_homescreen, NULL);
625
626 return setting;
627}
628
629static void
630hmi_controller_destroy(struct wl_listener *listener, void *data)
631{
632 struct link_layer *link = NULL;
633 struct link_layer *next = NULL;
634 struct hmi_controller *hmi_ctrl =
635 container_of(listener, struct hmi_controller, destroy_listener);
636
637 wl_list_for_each_safe(link, next,
638 &hmi_ctrl->workspace_fade.layer_list, link) {
639 wl_list_remove(&link->link);
640 free(link);
641 }
642
643 wl_array_release(&hmi_ctrl->ui_widgets);
644 free(hmi_ctrl->hmi_setting);
645 free(hmi_ctrl);
646}
647
648/**
649 * This is a starting method called from module_init.
650 * This sets up scene graph of ivi_layers; base, application, workspace
651 * background, and workspace. These ivi_layers are created/added to
652 * ivi_screen in create_layer
653 *
654 * base: to group ivi_surfaces of panel and background
655 * application: to group ivi_surfaces of ivi_applications
656 * workspace background: to group a ivi_surface of background in workspace
657 * workspace: to group ivi_surfaces for launching ivi_applications
658 *
659 * ivi_layers of workspace background and workspace is set to invisible at
660 * first. The properties of it is updated with animation when
661 * ivi_hmi_controller_home is requested.
662 */
663static struct hmi_controller *
664hmi_controller_create(struct weston_compositor *ec)
665{
666 struct ivi_layout_screen **pp_screen = NULL;
667 struct ivi_layout_screen *iviscrn = NULL;
668 int32_t screen_length = 0;
669 int32_t screen_width = 0;
670 int32_t screen_height = 0;
671 struct link_layer *tmp_link_layer = NULL;
672 int32_t panel_height = 0;
673 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
674
675 wl_array_init(&hmi_ctrl->ui_widgets);
676 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
677 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
678 hmi_ctrl->compositor = ec;
679
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900680 ivi_controller_interface->get_screens(&screen_length, &pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900681
682 iviscrn = pp_screen[0];
683
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900684 ivi_controller_interface->get_screen_resolution(iviscrn, &screen_width,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900685 &screen_height);
686
687 /* init base ivi_layer*/
688 hmi_ctrl->base_layer.x = 0;
689 hmi_ctrl->base_layer.y = 0;
690 hmi_ctrl->base_layer.width = screen_width;
691 hmi_ctrl->base_layer.height = screen_height;
692 hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
693
694 create_layer(iviscrn, &hmi_ctrl->base_layer);
695
696 panel_height = hmi_ctrl->hmi_setting->panel_height;
697
698 /* init application ivi_layer */
699 hmi_ctrl->application_layer.x = 0;
700 hmi_ctrl->application_layer.y = 0;
701 hmi_ctrl->application_layer.width = screen_width;
702 hmi_ctrl->application_layer.height = screen_height - panel_height;
703 hmi_ctrl->application_layer.id_layer =
704 hmi_ctrl->hmi_setting->application_layer_id;
705
706 create_layer(iviscrn, &hmi_ctrl->application_layer);
707
708 /* init workspace background ivi_layer */
709 hmi_ctrl->workspace_background_layer.x = 0;
710 hmi_ctrl->workspace_background_layer.y = 0;
711 hmi_ctrl->workspace_background_layer.width = screen_width;
712 hmi_ctrl->workspace_background_layer.height =
713 screen_height - panel_height;
714
715 hmi_ctrl->workspace_background_layer.id_layer =
716 hmi_ctrl->hmi_setting->workspace_background_layer_id;
717
718 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900719 ivi_controller_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900720 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900721 ivi_controller_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900722 hmi_ctrl->workspace_background_layer.ivilayer, false);
723
724 /* init workspace ivi_layer */
725 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
726 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
727 hmi_ctrl->workspace_layer.width =
728 hmi_ctrl->workspace_background_layer.width;
729 hmi_ctrl->workspace_layer.height =
730 hmi_ctrl->workspace_background_layer.height;
731 hmi_ctrl->workspace_layer.id_layer =
732 hmi_ctrl->hmi_setting->workspace_layer_id;
733
734 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900735 ivi_controller_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
736 ivi_controller_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900737 false);
738
739 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
740 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
741 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
742 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
743 &tmp_link_layer->link);
744 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
745 tmp_link_layer->layout_layer =
746 hmi_ctrl->workspace_background_layer.ivilayer;
747 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
748 &tmp_link_layer->link);
749
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900750 ivi_controller_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900751 set_notification_create_surface, hmi_ctrl);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900752 ivi_controller_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900753 set_notification_remove_surface, hmi_ctrl);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900754 ivi_controller_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900755 set_notification_configure_surface, hmi_ctrl);
756
757 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
758 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
759 &hmi_ctrl->destroy_listener);
760
761 free(pp_screen);
762 pp_screen = NULL;
763
764 return hmi_ctrl;
765}
766
767/**
768 * Implementations of ivi-hmi-controller.xml
769 */
770
771/**
772 * A ivi_surface drawing background is identified by id_surface.
773 * Properties of the ivi_surface is set by using ivi_layout APIs according to
774 * the scene graph of UI defined in hmi_controller_create.
775 *
776 * UI ivi_layer is used to add this ivi_surface.
777 */
778static void
779ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
780 uint32_t id_surface)
781{
782 struct ivi_layout_surface *ivisurf = NULL;
783 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
784 const int32_t dstx = hmi_ctrl->application_layer.x;
785 const int32_t dsty = hmi_ctrl->application_layer.y;
786 const int32_t width = hmi_ctrl->application_layer.width;
787 const int32_t height = hmi_ctrl->application_layer.height;
788 int32_t ret = 0;
789
790 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
791 sizeof(*add_surface_id));
792 *add_surface_id = id_surface;
793
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900794 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900795 assert(ivisurf != NULL);
796
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900797 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900798 assert(!ret);
799
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900800 ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900801 dstx, dsty, width, height);
802 assert(!ret);
803
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900804 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900805 assert(!ret);
806}
807
808/**
809 * A ivi_surface drawing panel is identified by id_surface.
810 * Properties of the ivi_surface is set by using ivi_layout APIs according to
811 * the scene graph of UI defined in hmi_controller_create.
812 *
813 * UI ivi_layer is used to add this ivi_surface.
814 */
815static void
816ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
817 uint32_t id_surface)
818{
819 struct ivi_layout_surface *ivisurf = NULL;
820 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
821 const int32_t width = hmi_ctrl->base_layer.width;
822 int32_t ret = 0;
823 int32_t panel_height = 0;
824 const int32_t dstx = 0;
825 int32_t dsty = 0;
826
827 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
828 sizeof(*add_surface_id));
829 *add_surface_id = id_surface;
830
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900831 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900832 assert(ivisurf != NULL);
833
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900834 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900835 assert(!ret);
836
837 panel_height = hmi_ctrl->hmi_setting->panel_height;
838
839 dsty = hmi_ctrl->base_layer.height - panel_height;
840
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900841 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900842 ivisurf, dstx, dsty, width, panel_height);
843 assert(!ret);
844
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900845 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900846 assert(!ret);
847}
848
849/**
850 * A ivi_surface drawing buttons in panel is identified by id_surface.
851 * It can set several buttons. Properties of the ivi_surface is set by
852 * using ivi_layout APIs according to the scene graph of UI defined in
853 * hmi_controller_create. Additionally, the position of it is shifted to
854 * right when new one is requested.
855 *
856 * UI ivi_layer is used to add these ivi_surfaces.
857 */
858static void
859ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
860 uint32_t id_surface, int32_t number)
861{
862 struct ivi_layout_surface *ivisurf = NULL;
863 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
864 const int32_t width = 48;
865 const int32_t height = 48;
866 int32_t ret = 0;
867 int32_t panel_height = 0;
868 int32_t dstx = 0;
869 int32_t dsty = 0;
870 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
871 sizeof(*add_surface_id));
872 *add_surface_id = id_surface;
873
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900874 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900875 assert(ivisurf != NULL);
876
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900877 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900878 assert(!ret);
879
880 panel_height = hmi_ctrl->hmi_setting->panel_height;
881
882 dstx = (60 * number) + 15;
883 dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
884
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900885 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900886 ivisurf,dstx, dsty, width, height);
887 assert(!ret);
888
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900889 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900890 assert(!ret);
891}
892
893/**
894 * A ivi_surface drawing home button in panel is identified by id_surface.
895 * Properties of the ivi_surface is set by using ivi_layout APIs according to
896 * the scene graph of UI defined in hmi_controller_create.
897 *
898 * UI ivi_layer is used to add these ivi_surfaces.
899 */
900static void
901ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
902 uint32_t id_surface)
903{
904 struct ivi_layout_surface *ivisurf = NULL;
905 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
906 int32_t ret = 0;
907 int32_t size = 48;
908 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
909 const int32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
910 const int32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
911
912 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
913 sizeof(*add_surface_id));
914 *add_surface_id = id_surface;
915
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900916 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900917 assert(ivisurf != NULL);
918
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900919 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900920 assert(!ret);
921
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900922 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900923 ivisurf, dstx, dsty, size, size);
924 assert(!ret);
925
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900926 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900927 assert(!ret);
928}
929
930/**
931 * A ivi_surface drawing background of workspace is identified by id_surface.
932 * Properties of the ivi_surface is set by using ivi_layout APIs according to
933 * the scene graph of UI defined in hmi_controller_create.
934 *
935 * A ivi_layer of workspace_background is used to add this ivi_surface.
936 */
937static void
938ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
939 uint32_t id_surface)
940{
941 struct ivi_layout_surface *ivisurf = NULL;
942 struct ivi_layout_layer *ivilayer = NULL;
943 const int32_t width = hmi_ctrl->workspace_background_layer.width;
944 const int32_t height = hmi_ctrl->workspace_background_layer.height;
945 int32_t ret = 0;
946
947 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
948 sizeof(*add_surface_id));
949 *add_surface_id = id_surface;
950 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
951
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900952 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900953 assert(ivisurf != NULL);
954
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900955 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900956 assert(!ret);
957
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900958 ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900959 0, 0, width, height);
960 assert(!ret);
961
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900962 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900963 assert(!ret);
964}
965
966/**
967 * A list of ivi_surfaces drawing launchers in workspace is identified by
968 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
969 * APIs according to the scene graph of UI defined in hmi_controller_create.
970 *
971 * The workspace can have several pages to group ivi_surfaces of launcher.
972 * Each call of this interface increments a number of page to add a group
973 * of ivi_surfaces
974 */
975static void
976ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
977 int32_t icon_size)
978{
979 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
980 int32_t minspace_x = 10;
981 int32_t minspace_y = minspace_x;
982
983 int32_t width = hmi_ctrl->workspace_layer.width;
984 int32_t height = hmi_ctrl->workspace_layer.height;
985
986 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
987 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
988 float fcell_size_x = icon_size + space_x;
989
990 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
991 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
992 float fcell_size_y = icon_size + space_y;
993
994 struct weston_config *config = NULL;
995 struct weston_config_section *section = NULL;
996 const char *name = NULL;
997 int launcher_count = 0;
998 struct wl_array launchers;
999 int32_t nx = 0;
1000 int32_t ny = 0;
1001 int32_t prev = -1;
1002 struct launcher_info *data = NULL;
1003
1004 uint32_t surfaceid = 0;
1005 uint32_t workspaceid = 0;
1006 struct launcher_info *info = NULL;
1007
1008 int32_t x = 0;
1009 int32_t y = 0;
1010 int32_t ret = 0;
1011 struct ivi_layout_surface* layout_surface = NULL;
1012 uint32_t *add_surface_id = NULL;
1013
1014 if (0 == x_count)
1015 x_count = 1;
1016
1017 if (0 == y_count)
1018 y_count = 1;
1019
1020 config = hmi_ctrl->compositor->config;
1021 if (!config)
1022 return;
1023
1024 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1025 if (!section)
1026 return;
1027
1028 wl_array_init(&launchers);
1029
1030 while (weston_config_next_section(config, &section, &name)) {
1031 surfaceid = 0;
1032 workspaceid = 0;
1033 info = NULL;
1034 if (0 != strcmp(name, "ivi-launcher"))
1035 continue;
1036
1037 if (0 != weston_config_section_get_uint(section, "icon-id",
1038 &surfaceid, 0))
1039 continue;
1040
1041 if (0 != weston_config_section_get_uint(section,
1042 "workspace-id",
1043 &workspaceid, 0))
1044 continue;
1045
1046 info = wl_array_add(&launchers, sizeof(*info));
1047
1048 if (info) {
1049 info->surface_id = surfaceid;
1050 info->workspace_id = workspaceid;
1051 info->index = launcher_count;
1052 ++launcher_count;
1053 }
1054 }
1055
1056 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1057 compare_launcher_info);
1058
1059 wl_array_for_each(data, &launchers) {
1060 x = 0;
1061 y = 0;
1062 ret = 0;
1063 layout_surface = NULL;
1064 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1065 sizeof(*add_surface_id));
1066
1067 *add_surface_id = data->surface_id;
1068
1069 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1070 nx = 0;
1071 ny = 0;
1072 prev = data->workspace_id;
1073
1074 if (0 <= prev)
1075 hmi_ctrl->workspace_count++;
1076 }
1077
1078 if (y_count == ny) {
1079 ny = 0;
1080 hmi_ctrl->workspace_count++;
1081 }
1082
1083 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1084 y = ny * fcell_size_y + space_y;
1085
1086 layout_surface =
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001087 ivi_controller_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001088 assert(layout_surface);
1089
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001090 ret = ivi_controller_interface->layer_add_surface(layer, layout_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001091 assert(!ret);
1092
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001093 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001094 layout_surface, x, y, icon_size, icon_size);
1095 assert(!ret);
1096
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001097 ret = ivi_controller_interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001098 assert(!ret);
1099
1100 nx++;
1101
1102 if (x_count == nx) {
1103 ny++;
1104 nx = 0;
1105 }
1106 }
1107
1108 wl_array_release(&launchers);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001109 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001110}
1111
1112static void
1113ivi_hmi_controller_UI_ready(struct wl_client *client,
1114 struct wl_resource *resource)
1115{
1116 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1117
1118 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1119 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1120 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1121 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1122 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1123 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1124 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1125 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001126 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001127
1128 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1129 hmi_ctrl->is_initialized = 1;
1130}
1131
1132/**
1133 * Implementation of request and event of ivi_hmi_controller_workspace_control
1134 * and controlling workspace.
1135 *
1136 * When motion of input is detected in a ivi_surface of workspace background,
1137 * ivi_hmi_controller_workspace_control shall be invoked and to start
1138 * controlling of workspace. The workspace has several pages to show several
1139 * groups of applications.
1140 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1141 * according to motion. When motion finished, e.g. touch up detected, control is
1142 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1143 */
1144struct pointer_grab {
1145 struct weston_pointer_grab grab;
1146 struct ivi_layout_layer *layer;
1147 struct wl_resource *resource;
1148};
1149
1150struct touch_grab {
1151 struct weston_touch_grab grab;
1152 struct ivi_layout_layer *layer;
1153 struct wl_resource *resource;
1154};
1155
1156struct move_grab {
1157 wl_fixed_t dst[2];
1158 wl_fixed_t rgn[2][2];
1159 double v[2];
1160 struct timespec start_time;
1161 struct timespec pre_time;
1162 wl_fixed_t start_pos[2];
1163 wl_fixed_t pos[2];
1164 int32_t is_moved;
1165};
1166
1167struct pointer_move_grab {
1168 struct pointer_grab base;
1169 struct move_grab move;
1170};
1171
1172struct touch_move_grab {
1173 struct touch_grab base;
1174 struct move_grab move;
1175 int32_t is_active;
1176};
1177
1178static void
1179pointer_grab_start(struct pointer_grab *grab,
1180 struct ivi_layout_layer *layer,
1181 const struct weston_pointer_grab_interface *interface,
1182 struct weston_pointer *pointer)
1183{
1184 grab->grab.interface = interface;
1185 grab->layer = layer;
1186 weston_pointer_start_grab(pointer, &grab->grab);
1187}
1188
1189static void
1190touch_grab_start(struct touch_grab *grab,
1191 struct ivi_layout_layer *layer,
1192 const struct weston_touch_grab_interface *interface,
1193 struct weston_touch* touch)
1194{
1195 grab->grab.interface = interface;
1196 grab->layer = layer;
1197 weston_touch_start_grab(touch, &grab->grab);
1198}
1199
1200static int32_t
1201clamp(int32_t val, int32_t min, int32_t max)
1202{
1203 if (val < min)
1204 return min;
1205
1206 if (max < val)
1207 return max;
1208
1209 return val;
1210}
1211
1212static void
1213move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1214 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1215{
1216 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1217 int32_t width = hmi_ctrl->workspace_background_layer.width;
1218
1219 struct timespec time = {0};
1220 double grab_time = 0.0;
1221 double from_motion_time = 0.0;
1222 double pointer_v = 0.0;
1223 int32_t is_flick = 0;
1224 int32_t pos_x = 0;
1225 int32_t pos_y = 0;
1226 int page_no = 0;
1227 double end_pos = 0.0;
1228 uint32_t duration = 0;
1229
1230 clock_gettime(CLOCK_MONOTONIC, &time);
1231
1232 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1233 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1234
1235 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1236 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1237
1238 pointer_v = move->v[0];
1239
1240 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1241 if (200 < from_motion_time)
1242 pointer_v = 0.0;
1243
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001244 ivi_controller_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001245
1246
1247 if (is_flick) {
1248 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1249 page_no = (-orgx + width / 2) / width;
1250
1251 if (pointer_v < 0.0)
1252 page_no++;
1253 else
1254 page_no--;
1255 } else {
1256 page_no = (-pos_x + width / 2) / width;
1257 }
1258
1259 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1260 end_pos = -page_no * width;
1261
1262 duration = hmi_ctrl->hmi_setting->transition_duration;
1263 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001264 ivi_controller_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001265 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1266 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001267 ivi_controller_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001268 end_pos, pos_y,
1269 hmi_ctrl->workspace_background_layer.width,
1270 hmi_ctrl->workspace_background_layer.height);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001271 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001272}
1273
1274static void
1275pointer_move_workspace_grab_end(struct pointer_grab *grab)
1276{
1277 struct pointer_move_grab *pnt_move_grab =
1278 (struct pointer_move_grab *)grab;
1279 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1280
1281 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1282 grab->grab.pointer->grab_x, layer);
1283
1284 weston_pointer_end_grab(grab->grab.pointer);
1285}
1286
1287static void
1288touch_move_workspace_grab_end(struct touch_grab *grab)
1289{
1290 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1291 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1292
1293 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1294 grab->grab.touch->grab_x, layer);
1295
1296 weston_touch_end_grab(grab->grab.touch);
1297}
1298
1299static void
1300pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1301{
1302}
1303
1304static void
1305move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1306{
1307 struct timespec timestamp = {0};
1308 int32_t ii = 0;
1309 double dt = 0.0;
1310
1311 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1312 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1313 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1314
1315 if (dt < 1e-6)
1316 dt = 1e-6;
1317
1318 move->pre_time = timestamp;
1319
1320 for (ii = 0; ii < 2; ii++) {
1321 wl_fixed_t prepos = move->pos[ii];
1322 move->pos[ii] = pointer[ii] + move->dst[ii];
1323
1324 if (move->pos[ii] < move->rgn[0][ii]) {
1325 move->pos[ii] = move->rgn[0][ii];
1326 move->dst[ii] = move->pos[ii] - pointer[ii];
1327 } else if (move->rgn[1][ii] < move->pos[ii]) {
1328 move->pos[ii] = move->rgn[1][ii];
1329 move->dst[ii] = move->pos[ii] - pointer[ii];
1330 }
1331
1332 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1333
1334 if (!move->is_moved &&
1335 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1336 move->is_moved = 1;
1337 }
1338}
1339
1340static void
1341layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1342 wl_fixed_t pos_y)
1343{
1344 int32_t layout_pos_x = 0;
1345 int32_t layout_pos_y = 0;
1346
1347 layout_pos_x = wl_fixed_to_int(pos_x);
1348 layout_pos_y = wl_fixed_to_int(pos_y);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001349 ivi_controller_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1350 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001351}
1352
1353static void
1354pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1355 wl_fixed_t x, wl_fixed_t y)
1356{
1357 struct pointer_move_grab *pnt_move_grab =
1358 (struct pointer_move_grab *)grab;
1359 wl_fixed_t pointer_pos[2] = {x, y};
1360
1361 move_grab_update(&pnt_move_grab->move, pointer_pos);
1362 layer_set_pos(pnt_move_grab->base.layer,
1363 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
1364 weston_pointer_move(pnt_move_grab->base.grab.pointer, x, y);
1365}
1366
1367static void
1368touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1369 int touch_id, wl_fixed_t x, wl_fixed_t y)
1370{
1371 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1372
1373 if (!tch_move_grab->is_active)
1374 return;
1375
1376 wl_fixed_t pointer_pos[2] = {
1377 grab->touch->grab_x,
1378 grab->touch->grab_y
1379 };
1380
1381 move_grab_update(&tch_move_grab->move, pointer_pos);
1382 layer_set_pos(tch_move_grab->base.layer,
1383 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1384}
1385
1386static void
1387pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1388 uint32_t time, uint32_t button,
1389 uint32_t state_w)
1390{
1391 if (BTN_LEFT == button &&
1392 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1393 struct pointer_grab *pg = (struct pointer_grab *)grab;
1394
1395 pointer_move_workspace_grab_end(pg);
1396 free(grab);
1397 }
1398}
1399
1400static void
1401touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1402 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1403{
1404}
1405
1406static void
1407touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1408 int touch_id)
1409{
1410 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1411
1412 if (0 == touch_id)
1413 tch_move_grab->is_active = 0;
1414
1415 if (0 == grab->touch->num_tp) {
1416 touch_move_workspace_grab_end(&tch_move_grab->base);
1417 free(grab);
1418 }
1419}
1420
1421static void
1422pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1423{
1424 struct pointer_grab *pg = (struct pointer_grab *)grab;
1425
1426 pointer_move_workspace_grab_end(pg);
1427 free(grab);
1428}
1429
1430static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001431touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1432{
1433}
1434
1435static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001436touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1437{
1438 struct touch_grab *tg = (struct touch_grab *)grab;
1439
1440 touch_move_workspace_grab_end(tg);
1441 free(grab);
1442}
1443
1444static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1445 pointer_noop_grab_focus,
1446 pointer_move_grab_motion,
1447 pointer_move_workspace_grab_button,
1448 pointer_move_workspace_grab_cancel
1449};
1450
1451static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1452 touch_nope_grab_down,
1453 touch_move_workspace_grab_up,
1454 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001455 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001456 touch_move_workspace_grab_cancel
1457};
1458
1459enum HMI_GRAB_DEVICE {
1460 HMI_GRAB_DEVICE_NONE,
1461 HMI_GRAB_DEVICE_POINTER,
1462 HMI_GRAB_DEVICE_TOUCH
1463};
1464
1465static enum HMI_GRAB_DEVICE
1466get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1467{
1468 if (seat->pointer &&
1469 seat->pointer->focus &&
1470 seat->pointer->button_count &&
1471 seat->pointer->grab_serial == serial)
1472 return HMI_GRAB_DEVICE_POINTER;
1473
1474 if (seat->touch &&
1475 seat->touch->focus &&
1476 seat->touch->grab_serial == serial)
1477 return HMI_GRAB_DEVICE_TOUCH;
1478
1479 return HMI_GRAB_DEVICE_NONE;
1480}
1481
1482static void
1483move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1484 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1485 struct wl_resource* resource)
1486{
1487 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1488 move->pre_time = move->start_time;
1489 move->pos[0] = start_pos[0];
1490 move->pos[1] = start_pos[1];
1491 move->start_pos[0] = start_pos[0];
1492 move->start_pos[1] = start_pos[1];
1493 move->dst[0] = start_pos[0] - grab_pos[0];
1494 move->dst[1] = start_pos[1] - grab_pos[1];
1495 memcpy(move->rgn, rgn, sizeof(move->rgn));
1496}
1497
1498static void
1499move_grab_init_workspace(struct move_grab* move,
1500 wl_fixed_t grab_x, wl_fixed_t grab_y,
1501 struct wl_resource *resource)
1502{
1503 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1504 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1505 int32_t workspace_count = hmi_ctrl->workspace_count;
1506 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1507 int32_t layer_pos_x = 0;
1508 int32_t layer_pos_y = 0;
1509 wl_fixed_t start_pos[2] = {0};
1510 wl_fixed_t rgn[2][2] = {{0}};
1511 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1512
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001513 ivi_controller_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001514
1515 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1516 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1517
1518 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1519
1520 rgn[0][1] = wl_fixed_from_int(0);
1521 rgn[1][0] = wl_fixed_from_int(0);
1522 rgn[1][1] = wl_fixed_from_int(0);
1523
1524 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1525}
1526
1527static struct pointer_move_grab *
1528create_workspace_pointer_move(struct weston_pointer *pointer,
1529 struct wl_resource* resource)
1530{
1531 struct pointer_move_grab *pnt_move_grab =
1532 MEM_ALLOC(sizeof(*pnt_move_grab));
1533
1534 pnt_move_grab->base.resource = resource;
1535 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1536 pointer->grab_y, resource);
1537
1538 return pnt_move_grab;
1539}
1540
1541static struct touch_move_grab *
1542create_workspace_touch_move(struct weston_touch *touch,
1543 struct wl_resource* resource)
1544{
1545 struct touch_move_grab *tch_move_grab =
1546 MEM_ALLOC(sizeof(*tch_move_grab));
1547
1548 tch_move_grab->base.resource = resource;
1549 tch_move_grab->is_active = 1;
1550 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1551 touch->grab_y, resource);
1552
1553 return tch_move_grab;
1554}
1555
1556static void
1557ivi_hmi_controller_workspace_control(struct wl_client *client,
1558 struct wl_resource *resource,
1559 struct wl_resource *seat_resource,
1560 uint32_t serial)
1561{
1562 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1563 struct ivi_layout_layer *layer = NULL;
1564 struct pointer_move_grab *pnt_move_grab = NULL;
1565 struct touch_move_grab *tch_move_grab = NULL;
1566 struct weston_seat *seat = NULL;
1567 enum HMI_GRAB_DEVICE device;
1568
1569 if (hmi_ctrl->workspace_count < 2)
1570 return;
1571
1572 seat = wl_resource_get_user_data(seat_resource);
1573 device = get_hmi_grab_device(seat, serial);
1574
1575 if (HMI_GRAB_DEVICE_POINTER != device &&
1576 HMI_GRAB_DEVICE_TOUCH != device)
1577 return;
1578
1579 layer = hmi_ctrl->workspace_layer.ivilayer;
1580
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001581 ivi_controller_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001582
1583 switch (device) {
1584 case HMI_GRAB_DEVICE_POINTER:
1585 pnt_move_grab = create_workspace_pointer_move(seat->pointer,
1586 resource);
1587
1588 pointer_grab_start(&pnt_move_grab->base, layer,
1589 &pointer_move_grab_workspace_interface,
1590 seat->pointer);
1591 break;
1592
1593 case HMI_GRAB_DEVICE_TOUCH:
1594 tch_move_grab = create_workspace_touch_move(seat->touch,
1595 resource);
1596
1597 touch_grab_start(&tch_move_grab->base, layer,
1598 &touch_move_grab_workspace_interface,
1599 seat->touch);
1600 break;
1601
1602 default:
1603 break;
1604 }
1605}
1606
1607/**
1608 * Implementation of switch_mode
1609 */
1610static void
1611ivi_hmi_controller_switch_mode(struct wl_client *client,
1612 struct wl_resource *resource,
1613 uint32_t layout_mode)
1614{
1615 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1616
1617 switch_mode(hmi_ctrl, layout_mode);
1618}
1619
1620/**
1621 * Implementation of on/off displaying workspace and workspace background
1622 * ivi_layers.
1623 */
1624static void
1625ivi_hmi_controller_home(struct wl_client *client,
1626 struct wl_resource *resource,
1627 uint32_t home)
1628{
1629 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1630 uint32_t is_fade_in;
1631
1632 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1633 !hmi_ctrl->workspace_fade.is_fade_in) ||
1634 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1635 hmi_ctrl->workspace_fade.is_fade_in)) {
1636 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1637 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1638 &hmi_ctrl->workspace_fade);
1639 }
1640
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001641 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001642}
1643
1644/**
1645 * binding ivi-hmi-controller implementation
1646 */
1647static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1648 ivi_hmi_controller_UI_ready,
1649 ivi_hmi_controller_workspace_control,
1650 ivi_hmi_controller_switch_mode,
1651 ivi_hmi_controller_home
1652};
1653
1654static void
1655unbind_hmi_controller(struct wl_resource *resource)
1656{
1657}
1658
1659static void
1660bind_hmi_controller(struct wl_client *client,
1661 void *data, uint32_t version, uint32_t id)
1662{
1663 struct wl_resource *resource = NULL;
1664 struct hmi_controller *hmi_ctrl = data;
1665
1666 if (hmi_ctrl->user_interface != client) {
1667 struct wl_resource *res = wl_client_get_object(client, 1);
1668 wl_resource_post_error(res,
1669 WL_DISPLAY_ERROR_INVALID_OBJECT,
1670 "hmi-controller failed: permission denied");
1671 return;
1672 }
1673
1674 resource = wl_resource_create(
1675 client, &ivi_hmi_controller_interface, 1, id);
1676
1677 wl_resource_set_implementation(
1678 resource, &ivi_hmi_controller_implementation,
1679 hmi_ctrl, unbind_hmi_controller);
1680}
1681
1682static int32_t
1683initialize(struct hmi_controller *hmi_ctrl)
1684{
1685 struct config_command {
1686 char *key;
1687 uint32_t *dest;
1688 };
1689
1690 struct weston_config *config = hmi_ctrl->compositor->config;
1691 struct weston_config_section *section = NULL;
1692 int result = 0;
1693 int i = 0;
1694
1695 const struct config_command uint_commands[] = {
1696 { "background-id", &hmi_ctrl->ui_setting.background_id },
1697 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1698 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1699 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1700 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1701 { "random-id", &hmi_ctrl->ui_setting.random_id },
1702 { "home-id", &hmi_ctrl->ui_setting.home_id },
1703 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
1704 { NULL, NULL }
1705 };
1706
1707 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1708
1709 for (i = 0; -1 != result; ++i) {
1710 const struct config_command *command = &uint_commands[i];
1711
1712 if (!command->key)
1713 break;
1714
1715 if (weston_config_section_get_uint(
1716 section, command->key, command->dest, 0) != 0)
1717 result = -1;
1718 }
1719
1720 if (-1 == result) {
1721 weston_log("Failed to initialize hmi-controller\n");
1722 return 0;
1723 }
1724
1725 return 1;
1726}
1727
1728static void
1729launch_hmi_client_process(void *data)
1730{
1731 struct hmi_controller *hmi_ctrl =
1732 (struct hmi_controller *)data;
1733
1734 hmi_ctrl->user_interface =
1735 weston_client_start(hmi_ctrl->compositor,
1736 hmi_ctrl->hmi_setting->ivi_homescreen);
1737
1738 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1739}
1740
1741/*****************************************************************************
1742 * exported functions
1743 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001744WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001745controller_module_init(struct weston_compositor *ec,
1746 int *argc, char *argv[],
1747 const struct ivi_controller_interface *interface,
1748 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001749{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001750 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001751 struct wl_event_loop *loop = NULL;
1752
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001753 if (interface_version < sizeof(struct ivi_controller_interface)) {
1754 weston_log("ivi-shell: version mismatch of controller interface");
1755 return -1;
1756 }
1757
1758 ivi_controller_interface = interface;
1759
1760 hmi_ctrl = hmi_controller_create(ec);
1761
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001762 if (!initialize(hmi_ctrl)) {
1763 return -1;
1764 }
1765
1766 if (wl_global_create(ec->wl_display,
1767 &ivi_hmi_controller_interface, 1,
1768 hmi_ctrl, bind_hmi_controller) == NULL) {
1769 return -1;
1770 }
1771
1772 loop = wl_display_get_event_loop(ec->wl_display);
1773 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1774
1775 return 0;
1776}