blob: c38816478fb03863c251b723311658a6a152a1d7 [file] [log] [blame]
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001/*
2 * Copyright (C) 2014 DENSO CORPORATION
3 *
Bryce Harringtonaf637c22015-06-11 12:55:55 -07004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090011 *
Bryce Harringtonaf637c22015-06-11 12:55:55 -070012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090024 */
25
26/**
27 * A reference implementation how to use ivi-layout APIs in order to manage
28 * layout of ivi_surfaces/ivi_layers. Layout change is triggered by
29 * ivi-hmi-controller protocol, ivi-hmi-controller.xml. A reference how to
30 * use the protocol, see hmi-controller-homescreen.
31 *
32 * In-Vehicle Infotainment system usually manage properties of
33 * ivi_surfaces/ivi_layers by only a central component which decide where
34 * ivi_surfaces/ivi_layers shall be. This reference show examples to
35 * implement the central component as a module of weston.
36 *
37 * Default Scene graph of UI is defined in hmi_controller_create. It
38 * consists of
39 * - In the bottom, a base ivi_layer to group ivi_surfaces of background,
40 * panel, and buttons
41 * - Next, a application ivi_layer to show application ivi_surfaces.
42 * - Workspace background ivi_layer to show a ivi_surface of background image.
43 * - Workspace ivi_layer to show launcher to launch application with icons.
44 * Paths to binary and icon are defined in weston.ini. The width of this
45 * ivi_layer is longer than the size of ivi_screen because a workspace has
46 * several pages and is controlled by motion of input.
47 *
48 * TODO: animation method shall be refined
49 * TODO: support fade-in when UI is ready
50 */
51
52#include <sys/wait.h>
53#include <unistd.h>
54#include <stdlib.h>
55#include <stdio.h>
56#include <string.h>
57#include <linux/input.h>
58#include <assert.h>
59#include <time.h>
60
61#include "ivi-layout-export.h"
62#include "ivi-hmi-controller-server-protocol.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070063#include "shared/helpers.h"
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090064
65/*****************************************************************************
66 * structure, globals
67 ****************************************************************************/
68struct hmi_controller_layer {
69 struct ivi_layout_layer *ivilayer;
70 uint32_t id_layer;
71 int32_t x;
72 int32_t y;
73 int32_t width;
74 int32_t height;
75};
76
77struct link_layer {
78 struct ivi_layout_layer *layout_layer;
79 struct wl_list link;
80};
81
82struct hmi_controller_fade {
83 uint32_t is_fade_in;
84 struct wl_list layer_list;
85};
86
87struct hmi_server_setting {
88 uint32_t base_layer_id;
89 uint32_t application_layer_id;
90 uint32_t workspace_background_layer_id;
91 uint32_t workspace_layer_id;
92 int32_t panel_height;
93 uint32_t transition_duration;
94 char *ivi_homescreen;
95};
96
97struct ui_setting {
98 uint32_t background_id;
99 uint32_t panel_id;
100 uint32_t tiling_id;
101 uint32_t sidebyside_id;
102 uint32_t fullscreen_id;
103 uint32_t random_id;
104 uint32_t home_id;
105 uint32_t workspace_background_id;
106};
107
108struct hmi_controller {
109 struct hmi_server_setting *hmi_setting;
110 struct hmi_controller_layer base_layer;
111 struct hmi_controller_layer application_layer;
112 struct hmi_controller_layer workspace_background_layer;
113 struct hmi_controller_layer workspace_layer;
114 enum ivi_hmi_controller_layout_mode layout_mode;
115
116 struct hmi_controller_fade workspace_fade;
117
118 int32_t workspace_count;
119 struct wl_array ui_widgets;
120 int32_t is_initialized;
121
122 struct weston_compositor *compositor;
123 struct wl_listener destroy_listener;
124
125 struct wl_client *user_interface;
126 struct ui_setting ui_setting;
127};
128
129struct launcher_info {
130 uint32_t surface_id;
131 uint32_t workspace_id;
132 int32_t index;
133};
134
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900135const struct ivi_controller_interface *ivi_controller_interface;
136
137int
138controller_module_init(struct weston_compositor *ec,
139 int *argc, char *argv[],
140 const struct ivi_controller_interface *interface,
141 size_t interface_version);
142
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900143/*****************************************************************************
144 * local functions
145 ****************************************************************************/
146static void *
147fail_on_null(void *p, size_t size, char *file, int32_t line)
148{
149 if (size && !p) {
150 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
151 exit(EXIT_FAILURE);
152 }
153
154 return p;
155}
156
157static void *
158mem_alloc(size_t size, char *file, int32_t line)
159{
160 return fail_on_null(calloc(1, size), size, file, line);
161}
162
163#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
164
165static int32_t
166is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
167 struct ivi_layout_surface *ivisurf)
168{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900169 uint32_t id = ivi_controller_interface->get_id_of_surface(ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900170
171 uint32_t *ui_widget_id = NULL;
172 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
173 if (*ui_widget_id == id)
174 return 1;
175 }
176
177 return 0;
178}
179
180static int
181compare_launcher_info(const void *lhs, const void *rhs)
182{
183 const struct launcher_info *left = lhs;
184 const struct launcher_info *right = rhs;
185
186 if (left->workspace_id < right->workspace_id)
187 return -1;
188
189 if (left->workspace_id > right->workspace_id)
190 return 1;
191
192 if (left->index < right->index)
193 return -1;
194
195 if (left->index > right->index)
196 return 1;
197
198 return 0;
199}
200
201/**
202 * Internal methods called by mainly ivi_hmi_controller_switch_mode
203 * This reference shows 4 examples how to use ivi_layout APIs.
204 */
205static void
206mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
207 struct ivi_layout_surface **pp_surface,
208 int32_t surface_length,
209 struct hmi_controller_layer *layer)
210{
211 const float surface_width = (float)layer->width * 0.25;
212 const float surface_height = (float)layer->height * 0.5;
213 int32_t surface_x = 0;
214 int32_t surface_y = 0;
215 struct ivi_layout_surface *ivisurf = NULL;
216 struct ivi_layout_surface **surfaces;
217 struct ivi_layout_surface **new_order;
218 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
219
220 int32_t i = 0;
221 int32_t surf_num = 0;
222 uint32_t num = 1;
223
224 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
225 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
226
227 for (i = 0; i < surface_length; i++) {
228 ivisurf = pp_surface[i];
229
230 /* skip ui widgets */
231 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
232 continue;
233
234 surfaces[surf_num++] = ivisurf;
235 }
236
237 for (i = 0; i < surf_num; i++) {
238 ivisurf = surfaces[i];
239 new_order[i] = ivisurf;
240
241 if (num <= 8) {
242 if (num < 5) {
243 surface_x = (int32_t)((num - 1) * (surface_width));
244 surface_y = 0;
245 } else {
246 surface_x = (int32_t)((num - 5) * (surface_width));
247 surface_y = (int32_t)surface_height;
248 }
249
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900250 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900251 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
252 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900253 ivi_controller_interface->surface_set_visibility(ivisurf, true);
254 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900255 surface_x, surface_y,
256 (int32_t)surface_width,
257 (int32_t)surface_height);
258
259 num++;
260 continue;
261 }
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900262 ivi_controller_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900263 }
264
265 if (surf_num > 0) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900266 ivi_controller_interface->layer_set_transition(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900267 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
268 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900269 }
270
271 free(surfaces);
272 free(new_order);
273}
274
275static void
276mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
277 struct ivi_layout_surface **pp_surface,
278 int32_t surface_length,
279 struct hmi_controller_layer *layer)
280{
281 int32_t surface_width = layer->width / 2;
282 int32_t surface_height = layer->height;
283 struct ivi_layout_surface *ivisurf = NULL;
284
285 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
286 int32_t i = 0;
287 int32_t num = 1;
288
289 for (i = 0; i < surface_length; i++) {
290 ivisurf = pp_surface[i];
291
292 /* skip ui widgets */
293 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
294 continue;
295
296 if (num == 1) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900297 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900298 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
299 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900300 ivi_controller_interface->surface_set_visibility(ivisurf, true);
301 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900302 0, 0,
303 surface_width,
304 surface_height);
305
306 num++;
307 continue;
308 } else if (num == 2) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900309 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900310 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
311 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900312 ivi_controller_interface->surface_set_visibility(ivisurf, true);
313 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900314 surface_width, 0,
315 surface_width,
316 surface_height);
317
318 num++;
319 continue;
320 }
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900321 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900322 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
323 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900324 ivi_controller_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900325 }
326}
327
328static void
329mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
330 struct ivi_layout_surface **pp_surface,
331 int32_t surface_length,
332 struct hmi_controller_layer *layer)
333{
334 const int32_t surface_width = layer->width;
335 const int32_t surface_height = layer->height;
336 struct ivi_layout_surface *ivisurf = NULL;
337 int32_t i = 0;
338 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
339
340 for (i = 0; i < surface_length; i++) {
341 ivisurf = pp_surface[i];
342
343 /* skip ui widgets */
344 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
345 continue;
346
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900347 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900348 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
349 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900350 ivi_controller_interface->surface_set_visibility(ivisurf, true);
351 ivi_controller_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900352 surface_width,
353 surface_height);
354 }
355}
356
357static void
358mode_random_replace(struct hmi_controller *hmi_ctrl,
359 struct ivi_layout_surface **pp_surface,
360 int32_t surface_length,
361 struct hmi_controller_layer *layer)
362{
363 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
364 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
365 int32_t surface_x = 0;
366 int32_t surface_y = 0;
367 struct ivi_layout_surface *ivisurf = NULL;
368 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
369 int32_t i = 0;
370
371 for (i = 0; i < surface_length; i++) {
372 ivisurf = pp_surface[i];
373
374 /* skip ui widgets */
375 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
376 continue;
377
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900378 ivi_controller_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900379 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
380 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900381 ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900382 surface_x = rand() % (layer->width - surface_width);
383 surface_y = rand() % (layer->height - surface_height);
384
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900385 ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900386 surface_x,
387 surface_y,
388 surface_width,
389 surface_height);
390 }
391}
392
393static int32_t
394has_application_surface(struct hmi_controller *hmi_ctrl,
395 struct ivi_layout_surface **pp_surface,
396 int32_t surface_length)
397{
398 struct ivi_layout_surface *ivisurf = NULL;
399 int32_t i = 0;
400
401 for (i = 0; i < surface_length; i++) {
402 ivisurf = pp_surface[i];
403
404 /* skip ui widgets */
405 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
406 continue;
407
408 return 1;
409 }
410
411 return 0;
412}
413
414/**
415 * Supports 4 example to layout of application ivi_surfaces;
416 * tiling, side by side, fullscreen, and random.
417 */
418static void
419switch_mode(struct hmi_controller *hmi_ctrl,
420 enum ivi_hmi_controller_layout_mode layout_mode)
421{
422 struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
423 struct ivi_layout_surface **pp_surface = NULL;
424 int32_t surface_length = 0;
425 int32_t ret = 0;
426
427 if (!hmi_ctrl->is_initialized)
428 return;
429
430 hmi_ctrl->layout_mode = layout_mode;
431
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900432 ret = ivi_controller_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900433 assert(!ret);
434
435 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
436 free(pp_surface);
437 pp_surface = NULL;
438 return;
439 }
440
441 switch (layout_mode) {
442 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
443 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
444 layer);
445 break;
446 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
447 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
448 surface_length, layer);
449 break;
450 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
451 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
452 layer);
453 break;
454 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
455 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
456 layer);
457 break;
458 }
459
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900460 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900461 free(pp_surface);
462}
463
464/**
465 * Internal method for transition
466 */
467static void
468hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
469 struct hmi_controller_fade *fade)
470{
471 double tint = is_fade_in ? 1.0 : 0.0;
472 struct link_layer *linklayer = NULL;
473 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
474
475 fade->is_fade_in = is_fade_in;
476
477 wl_list_for_each(linklayer, &fade->layer_list, link) {
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900478 ivi_controller_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900479 IVI_LAYOUT_TRANSITION_LAYER_FADE,
480 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900481 ivi_controller_interface->layer_set_fade_info(linklayer->layout_layer,
482 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900483 }
484}
485
486/**
487 * Internal method to create ivi_layer with hmi_controller_layer and
488 * add to a ivi_screen
489 */
490static void
491create_layer(struct ivi_layout_screen *iviscrn,
492 struct hmi_controller_layer *layer)
493{
494 int32_t ret = 0;
495
496 layer->ivilayer =
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900497 ivi_controller_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900498 layer->width,
499 layer->height);
500 assert(layer->ivilayer != NULL);
501
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900502 ret = ivi_controller_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900503 assert(!ret);
504
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900505 ret = ivi_controller_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900506 layer->x, layer->y,
507 layer->width,
508 layer->height);
509 assert(!ret);
510
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900511 ret = ivi_controller_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900512 assert(!ret);
513}
514
515/**
516 * Internal set notification
517 */
518static void
519set_notification_create_surface(struct ivi_layout_surface *ivisurf,
520 void *userdata)
521{
522 struct hmi_controller *hmi_ctrl = userdata;
523 struct ivi_layout_layer *application_layer =
524 hmi_ctrl->application_layer.ivilayer;
525 int32_t ret = 0;
526
527 /* skip ui widgets */
528 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
529 return;
530
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900531 ret = ivi_controller_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900532 assert(!ret);
533}
534
535static void
536set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
537 void *userdata)
538{
539 struct hmi_controller *hmi_ctrl = userdata;
540
541 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
542}
543
544static void
545set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
546 void *userdata)
547{
548 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900549 struct ivi_layout_layer *application_layer =
550 hmi_ctrl->application_layer.ivilayer;
551 struct weston_surface *surface;
552 struct ivi_layout_surface **ivisurfs;
553 int32_t length = 0;
554 int32_t i;
555
556 /* return if the surface is not application content */
557 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
558 return;
559 }
560
561 /*
562 * if application changes size of wl_buffer. The source rectangle shall be
563 * fit to the size.
564 */
565 surface = ivi_controller_interface->surface_get_weston_surface(ivisurf);
566 if (surface) {
567 ivi_controller_interface->surface_set_source_rectangle(
568 ivisurf, 0, 0, surface->width,
569 surface->height);
570 }
571
572 /*
573 * search if the surface is already added to layer.
574 * If not yet, it is newly invoded application to go to switch_mode.
575 */
576 ivi_controller_interface->get_surfaces_on_layer(application_layer,
577 &length, &ivisurfs);
578 for (i = 0; i < length; i++) {
579 if (ivisurf == ivisurfs[i]) {
Michael Vetter2a18a522015-05-15 17:17:47 +0200580 /*
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900581 * if it is non new invoked application, just call
582 * commit_changes to apply source_rectangle.
583 */
584 ivi_controller_interface->commit_changes();
585 return;
586 }
587 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900588
589 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
590}
591
592/**
593 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
594 * corresponding ivi_layer are defined in weston.ini. Default scene graph
595 * of ivi_layers are initialized in hmi_controller_create
596 */
597static struct hmi_server_setting *
598hmi_server_setting_create(struct weston_compositor *ec)
599{
600 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
601 struct weston_config *config = ec->config;
602 struct weston_config_section *shell_section = NULL;
603
604 shell_section = weston_config_get_section(config, "ivi-shell",
605 NULL, NULL);
606
607 weston_config_section_get_uint(shell_section, "base-layer-id",
608 &setting->base_layer_id, 1000);
609
610 weston_config_section_get_uint(shell_section,
611 "workspace-background-layer-id",
612 &setting->workspace_background_layer_id,
613 2000);
614
615 weston_config_section_get_uint(shell_section, "workspace-layer-id",
616 &setting->workspace_layer_id, 3000);
617
618 weston_config_section_get_uint(shell_section, "application-layer-id",
619 &setting->application_layer_id, 4000);
620
621 weston_config_section_get_uint(shell_section, "transition-duration",
622 &setting->transition_duration, 300);
623
624 setting->panel_height = 70;
625
626 weston_config_section_get_string(shell_section,
627 "ivi-shell-user-interface",
628 &setting->ivi_homescreen, NULL);
629
630 return setting;
631}
632
633static void
634hmi_controller_destroy(struct wl_listener *listener, void *data)
635{
636 struct link_layer *link = NULL;
637 struct link_layer *next = NULL;
638 struct hmi_controller *hmi_ctrl =
639 container_of(listener, struct hmi_controller, destroy_listener);
640
641 wl_list_for_each_safe(link, next,
642 &hmi_ctrl->workspace_fade.layer_list, link) {
643 wl_list_remove(&link->link);
644 free(link);
645 }
646
647 wl_array_release(&hmi_ctrl->ui_widgets);
648 free(hmi_ctrl->hmi_setting);
649 free(hmi_ctrl);
650}
651
652/**
653 * This is a starting method called from module_init.
654 * This sets up scene graph of ivi_layers; base, application, workspace
655 * background, and workspace. These ivi_layers are created/added to
656 * ivi_screen in create_layer
657 *
658 * base: to group ivi_surfaces of panel and background
659 * application: to group ivi_surfaces of ivi_applications
660 * workspace background: to group a ivi_surface of background in workspace
661 * workspace: to group ivi_surfaces for launching ivi_applications
662 *
663 * ivi_layers of workspace background and workspace is set to invisible at
664 * first. The properties of it is updated with animation when
665 * ivi_hmi_controller_home is requested.
666 */
667static struct hmi_controller *
668hmi_controller_create(struct weston_compositor *ec)
669{
670 struct ivi_layout_screen **pp_screen = NULL;
671 struct ivi_layout_screen *iviscrn = NULL;
672 int32_t screen_length = 0;
673 int32_t screen_width = 0;
674 int32_t screen_height = 0;
675 struct link_layer *tmp_link_layer = NULL;
676 int32_t panel_height = 0;
677 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
678
679 wl_array_init(&hmi_ctrl->ui_widgets);
680 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
681 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
682 hmi_ctrl->compositor = ec;
683
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900684 ivi_controller_interface->get_screens(&screen_length, &pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900685
686 iviscrn = pp_screen[0];
687
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900688 ivi_controller_interface->get_screen_resolution(iviscrn, &screen_width,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900689 &screen_height);
690
691 /* init base ivi_layer*/
692 hmi_ctrl->base_layer.x = 0;
693 hmi_ctrl->base_layer.y = 0;
694 hmi_ctrl->base_layer.width = screen_width;
695 hmi_ctrl->base_layer.height = screen_height;
696 hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
697
698 create_layer(iviscrn, &hmi_ctrl->base_layer);
699
700 panel_height = hmi_ctrl->hmi_setting->panel_height;
701
702 /* init application ivi_layer */
703 hmi_ctrl->application_layer.x = 0;
704 hmi_ctrl->application_layer.y = 0;
705 hmi_ctrl->application_layer.width = screen_width;
706 hmi_ctrl->application_layer.height = screen_height - panel_height;
707 hmi_ctrl->application_layer.id_layer =
708 hmi_ctrl->hmi_setting->application_layer_id;
709
710 create_layer(iviscrn, &hmi_ctrl->application_layer);
711
712 /* init workspace background ivi_layer */
713 hmi_ctrl->workspace_background_layer.x = 0;
714 hmi_ctrl->workspace_background_layer.y = 0;
715 hmi_ctrl->workspace_background_layer.width = screen_width;
716 hmi_ctrl->workspace_background_layer.height =
717 screen_height - panel_height;
718
719 hmi_ctrl->workspace_background_layer.id_layer =
720 hmi_ctrl->hmi_setting->workspace_background_layer_id;
721
722 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900723 ivi_controller_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900724 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900725 ivi_controller_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900726 hmi_ctrl->workspace_background_layer.ivilayer, false);
727
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900728
729 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
730 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900731 tmp_link_layer->layout_layer =
732 hmi_ctrl->workspace_background_layer.ivilayer;
733 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
734 &tmp_link_layer->link);
735
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900736 ivi_controller_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900737 set_notification_create_surface, hmi_ctrl);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900738 ivi_controller_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900739 set_notification_remove_surface, hmi_ctrl);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900740 ivi_controller_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900741 set_notification_configure_surface, hmi_ctrl);
742
743 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
744 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
745 &hmi_ctrl->destroy_listener);
746
747 free(pp_screen);
748 pp_screen = NULL;
749
750 return hmi_ctrl;
751}
752
753/**
754 * Implementations of ivi-hmi-controller.xml
755 */
756
757/**
758 * A ivi_surface drawing background is identified by id_surface.
759 * Properties of the ivi_surface is set by using ivi_layout APIs according to
760 * the scene graph of UI defined in hmi_controller_create.
761 *
762 * UI ivi_layer is used to add this ivi_surface.
763 */
764static void
765ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
766 uint32_t id_surface)
767{
768 struct ivi_layout_surface *ivisurf = NULL;
769 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
770 const int32_t dstx = hmi_ctrl->application_layer.x;
771 const int32_t dsty = hmi_ctrl->application_layer.y;
772 const int32_t width = hmi_ctrl->application_layer.width;
773 const int32_t height = hmi_ctrl->application_layer.height;
774 int32_t ret = 0;
775
776 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
777 sizeof(*add_surface_id));
778 *add_surface_id = id_surface;
779
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900780 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900781 assert(ivisurf != NULL);
782
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900783 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900784 assert(!ret);
785
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900786 ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900787 dstx, dsty, width, height);
788 assert(!ret);
789
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900790 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900791 assert(!ret);
792}
793
794/**
795 * A ivi_surface drawing panel is identified by id_surface.
796 * Properties of the ivi_surface is set by using ivi_layout APIs according to
797 * the scene graph of UI defined in hmi_controller_create.
798 *
799 * UI ivi_layer is used to add this ivi_surface.
800 */
801static void
802ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
803 uint32_t id_surface)
804{
805 struct ivi_layout_surface *ivisurf = NULL;
806 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
807 const int32_t width = hmi_ctrl->base_layer.width;
808 int32_t ret = 0;
809 int32_t panel_height = 0;
810 const int32_t dstx = 0;
811 int32_t dsty = 0;
812
813 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
814 sizeof(*add_surface_id));
815 *add_surface_id = id_surface;
816
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900817 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900818 assert(ivisurf != NULL);
819
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900820 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900821 assert(!ret);
822
823 panel_height = hmi_ctrl->hmi_setting->panel_height;
824
825 dsty = hmi_ctrl->base_layer.height - panel_height;
826
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900827 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900828 ivisurf, dstx, dsty, width, panel_height);
829 assert(!ret);
830
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900831 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900832 assert(!ret);
833}
834
835/**
836 * A ivi_surface drawing buttons in panel is identified by id_surface.
837 * It can set several buttons. Properties of the ivi_surface is set by
838 * using ivi_layout APIs according to the scene graph of UI defined in
839 * hmi_controller_create. Additionally, the position of it is shifted to
840 * right when new one is requested.
841 *
842 * UI ivi_layer is used to add these ivi_surfaces.
843 */
844static void
845ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
846 uint32_t id_surface, int32_t number)
847{
848 struct ivi_layout_surface *ivisurf = NULL;
849 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
850 const int32_t width = 48;
851 const int32_t height = 48;
852 int32_t ret = 0;
853 int32_t panel_height = 0;
854 int32_t dstx = 0;
855 int32_t dsty = 0;
856 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
857 sizeof(*add_surface_id));
858 *add_surface_id = id_surface;
859
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900860 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900861 assert(ivisurf != NULL);
862
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900863 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900864 assert(!ret);
865
866 panel_height = hmi_ctrl->hmi_setting->panel_height;
867
868 dstx = (60 * number) + 15;
869 dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
870
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900871 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900872 ivisurf,dstx, dsty, width, height);
873 assert(!ret);
874
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900875 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900876 assert(!ret);
877}
878
879/**
880 * A ivi_surface drawing home button in panel is identified by id_surface.
881 * Properties of the ivi_surface is set by using ivi_layout APIs according to
882 * the scene graph of UI defined in hmi_controller_create.
883 *
884 * UI ivi_layer is used to add these ivi_surfaces.
885 */
886static void
887ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
888 uint32_t id_surface)
889{
890 struct ivi_layout_surface *ivisurf = NULL;
891 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
892 int32_t ret = 0;
893 int32_t size = 48;
894 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
895 const int32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
896 const int32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
897
898 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
899 sizeof(*add_surface_id));
900 *add_surface_id = id_surface;
901
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900902 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900903 assert(ivisurf != NULL);
904
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900905 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900906 assert(!ret);
907
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900908 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900909 ivisurf, dstx, dsty, size, size);
910 assert(!ret);
911
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900912 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900913 assert(!ret);
914}
915
916/**
917 * A ivi_surface drawing background of workspace is identified by id_surface.
918 * Properties of the ivi_surface is set by using ivi_layout APIs according to
919 * the scene graph of UI defined in hmi_controller_create.
920 *
921 * A ivi_layer of workspace_background is used to add this ivi_surface.
922 */
923static void
924ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
925 uint32_t id_surface)
926{
927 struct ivi_layout_surface *ivisurf = NULL;
928 struct ivi_layout_layer *ivilayer = NULL;
929 const int32_t width = hmi_ctrl->workspace_background_layer.width;
930 const int32_t height = hmi_ctrl->workspace_background_layer.height;
931 int32_t ret = 0;
932
933 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
934 sizeof(*add_surface_id));
935 *add_surface_id = id_surface;
936 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
937
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900938 ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900939 assert(ivisurf != NULL);
940
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900941 ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900942 assert(!ret);
943
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900944 ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900945 0, 0, width, height);
946 assert(!ret);
947
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900948 ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900949 assert(!ret);
950}
951
952/**
953 * A list of ivi_surfaces drawing launchers in workspace is identified by
954 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
955 * APIs according to the scene graph of UI defined in hmi_controller_create.
956 *
957 * The workspace can have several pages to group ivi_surfaces of launcher.
958 * Each call of this interface increments a number of page to add a group
959 * of ivi_surfaces
960 */
961static void
962ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
963 int32_t icon_size)
964{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900965 int32_t minspace_x = 10;
966 int32_t minspace_y = minspace_x;
967
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +0900968 int32_t width = hmi_ctrl->workspace_background_layer.width;
969 int32_t height = hmi_ctrl->workspace_background_layer.height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900970
971 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
972 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
973 float fcell_size_x = icon_size + space_x;
974
975 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
976 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
977 float fcell_size_y = icon_size + space_y;
978
979 struct weston_config *config = NULL;
980 struct weston_config_section *section = NULL;
981 const char *name = NULL;
982 int launcher_count = 0;
983 struct wl_array launchers;
984 int32_t nx = 0;
985 int32_t ny = 0;
986 int32_t prev = -1;
987 struct launcher_info *data = NULL;
988
989 uint32_t surfaceid = 0;
990 uint32_t workspaceid = 0;
991 struct launcher_info *info = NULL;
992
993 int32_t x = 0;
994 int32_t y = 0;
995 int32_t ret = 0;
996 struct ivi_layout_surface* layout_surface = NULL;
997 uint32_t *add_surface_id = NULL;
998
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +0900999 struct ivi_layout_screen *iviscrn = NULL;
1000 struct link_layer *tmp_link_layer = NULL;
1001 struct ivi_layout_screen **pp_screen = NULL;
1002 int32_t screen_length = 0;
1003
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001004 if (0 == x_count)
1005 x_count = 1;
1006
1007 if (0 == y_count)
1008 y_count = 1;
1009
1010 config = hmi_ctrl->compositor->config;
1011 if (!config)
1012 return;
1013
1014 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1015 if (!section)
1016 return;
1017
1018 wl_array_init(&launchers);
1019
1020 while (weston_config_next_section(config, &section, &name)) {
1021 surfaceid = 0;
1022 workspaceid = 0;
1023 info = NULL;
1024 if (0 != strcmp(name, "ivi-launcher"))
1025 continue;
1026
1027 if (0 != weston_config_section_get_uint(section, "icon-id",
1028 &surfaceid, 0))
1029 continue;
1030
1031 if (0 != weston_config_section_get_uint(section,
1032 "workspace-id",
1033 &workspaceid, 0))
1034 continue;
1035
1036 info = wl_array_add(&launchers, sizeof(*info));
1037
1038 if (info) {
1039 info->surface_id = surfaceid;
1040 info->workspace_id = workspaceid;
1041 info->index = launcher_count;
1042 ++launcher_count;
1043 }
1044 }
1045
1046 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1047 compare_launcher_info);
1048
1049 wl_array_for_each(data, &launchers) {
1050 x = 0;
1051 y = 0;
1052 ret = 0;
1053 layout_surface = NULL;
1054 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1055 sizeof(*add_surface_id));
1056
1057 *add_surface_id = data->surface_id;
1058
1059 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1060 nx = 0;
1061 ny = 0;
1062 prev = data->workspace_id;
1063
1064 if (0 <= prev)
1065 hmi_ctrl->workspace_count++;
1066 }
1067
1068 if (y_count == ny) {
1069 ny = 0;
1070 hmi_ctrl->workspace_count++;
1071 }
1072
1073 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1074 y = ny * fcell_size_y + space_y;
1075
1076 layout_surface =
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001077 ivi_controller_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001078 assert(layout_surface);
1079
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001080 ret = ivi_controller_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001081 layout_surface, x, y, icon_size, icon_size);
1082 assert(!ret);
1083
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001084 nx++;
1085
1086 if (x_count == nx) {
1087 ny++;
1088 nx = 0;
1089 }
1090 }
1091
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001092 /* init workspace ivi_layer */
1093 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1094 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1095 hmi_ctrl->workspace_layer.width =
1096 hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1097 hmi_ctrl->workspace_layer.height =
1098 hmi_ctrl->workspace_background_layer.height;
1099 hmi_ctrl->workspace_layer.id_layer =
1100 hmi_ctrl->hmi_setting->workspace_layer_id;
1101
1102 ivi_controller_interface->get_screens(&screen_length, &pp_screen);
1103 iviscrn = pp_screen[0];
1104 free(pp_screen);
1105 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
1106 ivi_controller_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1107 ivi_controller_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
1108 false);
1109
1110 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1111 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1112 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1113 &tmp_link_layer->link);
1114
1115 /* Add surface to layer */
1116 wl_array_for_each(data, &launchers) {
1117 layout_surface =
1118 ivi_controller_interface->get_surface_from_id(data->surface_id);
1119 assert(layout_surface);
1120
1121 ret = ivi_controller_interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
1122 layout_surface);
1123 assert(!ret);
1124
1125 ret = ivi_controller_interface->surface_set_visibility(layout_surface, true);
1126 assert(!ret);
1127 }
1128
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001129 wl_array_release(&launchers);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001130 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001131}
1132
1133static void
1134ivi_hmi_controller_UI_ready(struct wl_client *client,
1135 struct wl_resource *resource)
1136{
1137 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1138
1139 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1140 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1141 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1142 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1143 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1144 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1145 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1146 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001147 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001148
1149 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1150 hmi_ctrl->is_initialized = 1;
1151}
1152
1153/**
1154 * Implementation of request and event of ivi_hmi_controller_workspace_control
1155 * and controlling workspace.
1156 *
1157 * When motion of input is detected in a ivi_surface of workspace background,
1158 * ivi_hmi_controller_workspace_control shall be invoked and to start
1159 * controlling of workspace. The workspace has several pages to show several
1160 * groups of applications.
1161 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1162 * according to motion. When motion finished, e.g. touch up detected, control is
1163 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1164 */
1165struct pointer_grab {
1166 struct weston_pointer_grab grab;
1167 struct ivi_layout_layer *layer;
1168 struct wl_resource *resource;
1169};
1170
1171struct touch_grab {
1172 struct weston_touch_grab grab;
1173 struct ivi_layout_layer *layer;
1174 struct wl_resource *resource;
1175};
1176
1177struct move_grab {
1178 wl_fixed_t dst[2];
1179 wl_fixed_t rgn[2][2];
1180 double v[2];
1181 struct timespec start_time;
1182 struct timespec pre_time;
1183 wl_fixed_t start_pos[2];
1184 wl_fixed_t pos[2];
1185 int32_t is_moved;
1186};
1187
1188struct pointer_move_grab {
1189 struct pointer_grab base;
1190 struct move_grab move;
1191};
1192
1193struct touch_move_grab {
1194 struct touch_grab base;
1195 struct move_grab move;
1196 int32_t is_active;
1197};
1198
1199static void
1200pointer_grab_start(struct pointer_grab *grab,
1201 struct ivi_layout_layer *layer,
1202 const struct weston_pointer_grab_interface *interface,
1203 struct weston_pointer *pointer)
1204{
1205 grab->grab.interface = interface;
1206 grab->layer = layer;
1207 weston_pointer_start_grab(pointer, &grab->grab);
1208}
1209
1210static void
1211touch_grab_start(struct touch_grab *grab,
1212 struct ivi_layout_layer *layer,
1213 const struct weston_touch_grab_interface *interface,
1214 struct weston_touch* touch)
1215{
1216 grab->grab.interface = interface;
1217 grab->layer = layer;
1218 weston_touch_start_grab(touch, &grab->grab);
1219}
1220
1221static int32_t
1222clamp(int32_t val, int32_t min, int32_t max)
1223{
1224 if (val < min)
1225 return min;
1226
1227 if (max < val)
1228 return max;
1229
1230 return val;
1231}
1232
1233static void
1234move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1235 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1236{
1237 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1238 int32_t width = hmi_ctrl->workspace_background_layer.width;
1239
1240 struct timespec time = {0};
1241 double grab_time = 0.0;
1242 double from_motion_time = 0.0;
1243 double pointer_v = 0.0;
1244 int32_t is_flick = 0;
1245 int32_t pos_x = 0;
1246 int32_t pos_y = 0;
1247 int page_no = 0;
1248 double end_pos = 0.0;
1249 uint32_t duration = 0;
1250
1251 clock_gettime(CLOCK_MONOTONIC, &time);
1252
1253 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1254 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1255
1256 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1257 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1258
1259 pointer_v = move->v[0];
1260
1261 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1262 if (200 < from_motion_time)
1263 pointer_v = 0.0;
1264
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001265 ivi_controller_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001266
1267
1268 if (is_flick) {
1269 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1270 page_no = (-orgx + width / 2) / width;
1271
1272 if (pointer_v < 0.0)
1273 page_no++;
1274 else
1275 page_no--;
1276 } else {
1277 page_no = (-pos_x + width / 2) / width;
1278 }
1279
1280 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1281 end_pos = -page_no * width;
1282
1283 duration = hmi_ctrl->hmi_setting->transition_duration;
1284 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001285 ivi_controller_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001286 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1287 duration);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001288 ivi_controller_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001289 end_pos, pos_y,
Nobuhiko Tanibata4412cd12015-08-24 09:12:37 +09001290 hmi_ctrl->workspace_layer.width,
1291 hmi_ctrl->workspace_layer.height);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001292 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001293}
1294
1295static void
1296pointer_move_workspace_grab_end(struct pointer_grab *grab)
1297{
1298 struct pointer_move_grab *pnt_move_grab =
1299 (struct pointer_move_grab *)grab;
1300 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1301
1302 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1303 grab->grab.pointer->grab_x, layer);
1304
1305 weston_pointer_end_grab(grab->grab.pointer);
1306}
1307
1308static void
1309touch_move_workspace_grab_end(struct touch_grab *grab)
1310{
1311 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1312 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1313
1314 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1315 grab->grab.touch->grab_x, layer);
1316
1317 weston_touch_end_grab(grab->grab.touch);
1318}
1319
1320static void
1321pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1322{
1323}
1324
1325static void
1326move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1327{
1328 struct timespec timestamp = {0};
1329 int32_t ii = 0;
1330 double dt = 0.0;
1331
1332 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1333 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1334 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1335
1336 if (dt < 1e-6)
1337 dt = 1e-6;
1338
1339 move->pre_time = timestamp;
1340
1341 for (ii = 0; ii < 2; ii++) {
1342 wl_fixed_t prepos = move->pos[ii];
1343 move->pos[ii] = pointer[ii] + move->dst[ii];
1344
1345 if (move->pos[ii] < move->rgn[0][ii]) {
1346 move->pos[ii] = move->rgn[0][ii];
1347 move->dst[ii] = move->pos[ii] - pointer[ii];
1348 } else if (move->rgn[1][ii] < move->pos[ii]) {
1349 move->pos[ii] = move->rgn[1][ii];
1350 move->dst[ii] = move->pos[ii] - pointer[ii];
1351 }
1352
1353 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1354
1355 if (!move->is_moved &&
1356 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1357 move->is_moved = 1;
1358 }
1359}
1360
1361static void
1362layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1363 wl_fixed_t pos_y)
1364{
1365 int32_t layout_pos_x = 0;
1366 int32_t layout_pos_y = 0;
1367
1368 layout_pos_x = wl_fixed_to_int(pos_x);
1369 layout_pos_y = wl_fixed_to_int(pos_y);
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001370 ivi_controller_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1371 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001372}
1373
1374static void
1375pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1376 wl_fixed_t x, wl_fixed_t y)
1377{
1378 struct pointer_move_grab *pnt_move_grab =
1379 (struct pointer_move_grab *)grab;
1380 wl_fixed_t pointer_pos[2] = {x, y};
1381
1382 move_grab_update(&pnt_move_grab->move, pointer_pos);
1383 layer_set_pos(pnt_move_grab->base.layer,
1384 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
1385 weston_pointer_move(pnt_move_grab->base.grab.pointer, x, y);
1386}
1387
1388static void
1389touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1390 int touch_id, wl_fixed_t x, wl_fixed_t y)
1391{
1392 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1393
1394 if (!tch_move_grab->is_active)
1395 return;
1396
1397 wl_fixed_t pointer_pos[2] = {
1398 grab->touch->grab_x,
1399 grab->touch->grab_y
1400 };
1401
1402 move_grab_update(&tch_move_grab->move, pointer_pos);
1403 layer_set_pos(tch_move_grab->base.layer,
1404 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1405}
1406
1407static void
1408pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1409 uint32_t time, uint32_t button,
1410 uint32_t state_w)
1411{
1412 if (BTN_LEFT == button &&
1413 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1414 struct pointer_grab *pg = (struct pointer_grab *)grab;
1415
1416 pointer_move_workspace_grab_end(pg);
1417 free(grab);
1418 }
1419}
1420
1421static void
1422touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1423 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1424{
1425}
1426
1427static void
1428touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1429 int touch_id)
1430{
1431 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1432
1433 if (0 == touch_id)
1434 tch_move_grab->is_active = 0;
1435
1436 if (0 == grab->touch->num_tp) {
1437 touch_move_workspace_grab_end(&tch_move_grab->base);
1438 free(grab);
1439 }
1440}
1441
1442static void
1443pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1444{
1445 struct pointer_grab *pg = (struct pointer_grab *)grab;
1446
1447 pointer_move_workspace_grab_end(pg);
1448 free(grab);
1449}
1450
1451static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001452touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1453{
1454}
1455
1456static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001457touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1458{
1459 struct touch_grab *tg = (struct touch_grab *)grab;
1460
1461 touch_move_workspace_grab_end(tg);
1462 free(grab);
1463}
1464
1465static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1466 pointer_noop_grab_focus,
1467 pointer_move_grab_motion,
1468 pointer_move_workspace_grab_button,
1469 pointer_move_workspace_grab_cancel
1470};
1471
1472static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1473 touch_nope_grab_down,
1474 touch_move_workspace_grab_up,
1475 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001476 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001477 touch_move_workspace_grab_cancel
1478};
1479
1480enum HMI_GRAB_DEVICE {
1481 HMI_GRAB_DEVICE_NONE,
1482 HMI_GRAB_DEVICE_POINTER,
1483 HMI_GRAB_DEVICE_TOUCH
1484};
1485
1486static enum HMI_GRAB_DEVICE
1487get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1488{
Derek Foreman1281a362015-07-31 16:55:32 -05001489 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1490 struct weston_touch *touch = weston_seat_get_touch(seat);
1491
1492 if (pointer &&
1493 pointer->focus &&
1494 pointer->button_count &&
1495 pointer->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001496 return HMI_GRAB_DEVICE_POINTER;
1497
Derek Foreman1281a362015-07-31 16:55:32 -05001498 if (touch &&
1499 touch->focus &&
1500 touch->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001501 return HMI_GRAB_DEVICE_TOUCH;
1502
1503 return HMI_GRAB_DEVICE_NONE;
1504}
1505
1506static void
1507move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1508 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1509 struct wl_resource* resource)
1510{
1511 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1512 move->pre_time = move->start_time;
1513 move->pos[0] = start_pos[0];
1514 move->pos[1] = start_pos[1];
1515 move->start_pos[0] = start_pos[0];
1516 move->start_pos[1] = start_pos[1];
1517 move->dst[0] = start_pos[0] - grab_pos[0];
1518 move->dst[1] = start_pos[1] - grab_pos[1];
1519 memcpy(move->rgn, rgn, sizeof(move->rgn));
1520}
1521
1522static void
1523move_grab_init_workspace(struct move_grab* move,
1524 wl_fixed_t grab_x, wl_fixed_t grab_y,
1525 struct wl_resource *resource)
1526{
1527 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1528 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1529 int32_t workspace_count = hmi_ctrl->workspace_count;
1530 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1531 int32_t layer_pos_x = 0;
1532 int32_t layer_pos_y = 0;
1533 wl_fixed_t start_pos[2] = {0};
1534 wl_fixed_t rgn[2][2] = {{0}};
1535 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1536
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001537 ivi_controller_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001538
1539 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1540 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1541
1542 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1543
1544 rgn[0][1] = wl_fixed_from_int(0);
1545 rgn[1][0] = wl_fixed_from_int(0);
1546 rgn[1][1] = wl_fixed_from_int(0);
1547
1548 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1549}
1550
1551static struct pointer_move_grab *
1552create_workspace_pointer_move(struct weston_pointer *pointer,
1553 struct wl_resource* resource)
1554{
1555 struct pointer_move_grab *pnt_move_grab =
1556 MEM_ALLOC(sizeof(*pnt_move_grab));
1557
1558 pnt_move_grab->base.resource = resource;
1559 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1560 pointer->grab_y, resource);
1561
1562 return pnt_move_grab;
1563}
1564
1565static struct touch_move_grab *
1566create_workspace_touch_move(struct weston_touch *touch,
1567 struct wl_resource* resource)
1568{
1569 struct touch_move_grab *tch_move_grab =
1570 MEM_ALLOC(sizeof(*tch_move_grab));
1571
1572 tch_move_grab->base.resource = resource;
1573 tch_move_grab->is_active = 1;
1574 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1575 touch->grab_y, resource);
1576
1577 return tch_move_grab;
1578}
1579
1580static void
1581ivi_hmi_controller_workspace_control(struct wl_client *client,
1582 struct wl_resource *resource,
1583 struct wl_resource *seat_resource,
1584 uint32_t serial)
1585{
1586 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1587 struct ivi_layout_layer *layer = NULL;
1588 struct pointer_move_grab *pnt_move_grab = NULL;
1589 struct touch_move_grab *tch_move_grab = NULL;
1590 struct weston_seat *seat = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001591 struct weston_pointer *pointer;
1592 struct weston_touch *touch;
1593
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001594 enum HMI_GRAB_DEVICE device;
1595
1596 if (hmi_ctrl->workspace_count < 2)
1597 return;
1598
1599 seat = wl_resource_get_user_data(seat_resource);
1600 device = get_hmi_grab_device(seat, serial);
1601
1602 if (HMI_GRAB_DEVICE_POINTER != device &&
1603 HMI_GRAB_DEVICE_TOUCH != device)
1604 return;
1605
1606 layer = hmi_ctrl->workspace_layer.ivilayer;
1607
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001608 ivi_controller_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001609
1610 switch (device) {
1611 case HMI_GRAB_DEVICE_POINTER:
Derek Foreman1281a362015-07-31 16:55:32 -05001612 pointer = weston_seat_get_pointer(seat);
1613 pnt_move_grab = create_workspace_pointer_move(pointer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001614 resource);
1615
1616 pointer_grab_start(&pnt_move_grab->base, layer,
1617 &pointer_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001618 pointer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001619 break;
1620
1621 case HMI_GRAB_DEVICE_TOUCH:
Derek Foreman1281a362015-07-31 16:55:32 -05001622 touch = weston_seat_get_touch(seat);
1623 tch_move_grab = create_workspace_touch_move(touch,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001624 resource);
1625
1626 touch_grab_start(&tch_move_grab->base, layer,
1627 &touch_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001628 touch);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001629 break;
1630
1631 default:
1632 break;
1633 }
1634}
1635
1636/**
1637 * Implementation of switch_mode
1638 */
1639static void
1640ivi_hmi_controller_switch_mode(struct wl_client *client,
1641 struct wl_resource *resource,
1642 uint32_t layout_mode)
1643{
1644 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1645
1646 switch_mode(hmi_ctrl, layout_mode);
1647}
1648
1649/**
1650 * Implementation of on/off displaying workspace and workspace background
1651 * ivi_layers.
1652 */
1653static void
1654ivi_hmi_controller_home(struct wl_client *client,
1655 struct wl_resource *resource,
1656 uint32_t home)
1657{
1658 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1659 uint32_t is_fade_in;
1660
1661 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1662 !hmi_ctrl->workspace_fade.is_fade_in) ||
1663 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1664 hmi_ctrl->workspace_fade.is_fade_in)) {
1665 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1666 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1667 &hmi_ctrl->workspace_fade);
1668 }
1669
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001670 ivi_controller_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001671}
1672
1673/**
1674 * binding ivi-hmi-controller implementation
1675 */
1676static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1677 ivi_hmi_controller_UI_ready,
1678 ivi_hmi_controller_workspace_control,
1679 ivi_hmi_controller_switch_mode,
1680 ivi_hmi_controller_home
1681};
1682
1683static void
1684unbind_hmi_controller(struct wl_resource *resource)
1685{
1686}
1687
1688static void
1689bind_hmi_controller(struct wl_client *client,
1690 void *data, uint32_t version, uint32_t id)
1691{
1692 struct wl_resource *resource = NULL;
1693 struct hmi_controller *hmi_ctrl = data;
1694
1695 if (hmi_ctrl->user_interface != client) {
1696 struct wl_resource *res = wl_client_get_object(client, 1);
1697 wl_resource_post_error(res,
1698 WL_DISPLAY_ERROR_INVALID_OBJECT,
1699 "hmi-controller failed: permission denied");
1700 return;
1701 }
1702
1703 resource = wl_resource_create(
1704 client, &ivi_hmi_controller_interface, 1, id);
1705
1706 wl_resource_set_implementation(
1707 resource, &ivi_hmi_controller_implementation,
1708 hmi_ctrl, unbind_hmi_controller);
1709}
1710
1711static int32_t
1712initialize(struct hmi_controller *hmi_ctrl)
1713{
1714 struct config_command {
1715 char *key;
1716 uint32_t *dest;
1717 };
1718
1719 struct weston_config *config = hmi_ctrl->compositor->config;
1720 struct weston_config_section *section = NULL;
1721 int result = 0;
1722 int i = 0;
1723
1724 const struct config_command uint_commands[] = {
1725 { "background-id", &hmi_ctrl->ui_setting.background_id },
1726 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1727 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1728 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1729 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1730 { "random-id", &hmi_ctrl->ui_setting.random_id },
1731 { "home-id", &hmi_ctrl->ui_setting.home_id },
1732 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
1733 { NULL, NULL }
1734 };
1735
1736 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1737
1738 for (i = 0; -1 != result; ++i) {
1739 const struct config_command *command = &uint_commands[i];
1740
1741 if (!command->key)
1742 break;
1743
1744 if (weston_config_section_get_uint(
1745 section, command->key, command->dest, 0) != 0)
1746 result = -1;
1747 }
1748
1749 if (-1 == result) {
1750 weston_log("Failed to initialize hmi-controller\n");
1751 return 0;
1752 }
1753
1754 return 1;
1755}
1756
1757static void
1758launch_hmi_client_process(void *data)
1759{
1760 struct hmi_controller *hmi_ctrl =
1761 (struct hmi_controller *)data;
1762
1763 hmi_ctrl->user_interface =
1764 weston_client_start(hmi_ctrl->compositor,
1765 hmi_ctrl->hmi_setting->ivi_homescreen);
1766
1767 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1768}
1769
1770/*****************************************************************************
1771 * exported functions
1772 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001773WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001774controller_module_init(struct weston_compositor *ec,
1775 int *argc, char *argv[],
1776 const struct ivi_controller_interface *interface,
1777 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001778{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001779 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001780 struct wl_event_loop *loop = NULL;
1781
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001782 if (interface_version < sizeof(struct ivi_controller_interface)) {
1783 weston_log("ivi-shell: version mismatch of controller interface");
1784 return -1;
1785 }
1786
1787 ivi_controller_interface = interface;
1788
1789 hmi_ctrl = hmi_controller_create(ec);
1790
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001791 if (!initialize(hmi_ctrl)) {
1792 return -1;
1793 }
1794
1795 if (wl_global_create(ec->wl_display,
1796 &ivi_hmi_controller_interface, 1,
1797 hmi_ctrl, bind_hmi_controller) == NULL) {
1798 return -1;
1799 }
1800
1801 loop = wl_display_get_event_loop(ec->wl_display);
1802 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1803
1804 return 0;
1805}