blob: 3a07a70dd6b59400ec8b0303a389e25257833b89 [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
131/*****************************************************************************
132 * local functions
133 ****************************************************************************/
134static void *
135fail_on_null(void *p, size_t size, char *file, int32_t line)
136{
137 if (size && !p) {
138 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
139 exit(EXIT_FAILURE);
140 }
141
142 return p;
143}
144
145static void *
146mem_alloc(size_t size, char *file, int32_t line)
147{
148 return fail_on_null(calloc(1, size), size, file, line);
149}
150
151#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
152
153static int32_t
154is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
155 struct ivi_layout_surface *ivisurf)
156{
157 uint32_t id = ivi_layout_get_id_of_surface(ivisurf);
158
159 uint32_t *ui_widget_id = NULL;
160 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
161 if (*ui_widget_id == id)
162 return 1;
163 }
164
165 return 0;
166}
167
168static int
169compare_launcher_info(const void *lhs, const void *rhs)
170{
171 const struct launcher_info *left = lhs;
172 const struct launcher_info *right = rhs;
173
174 if (left->workspace_id < right->workspace_id)
175 return -1;
176
177 if (left->workspace_id > right->workspace_id)
178 return 1;
179
180 if (left->index < right->index)
181 return -1;
182
183 if (left->index > right->index)
184 return 1;
185
186 return 0;
187}
188
189/**
190 * Internal methods called by mainly ivi_hmi_controller_switch_mode
191 * This reference shows 4 examples how to use ivi_layout APIs.
192 */
193static void
194mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
195 struct ivi_layout_surface **pp_surface,
196 int32_t surface_length,
197 struct hmi_controller_layer *layer)
198{
199 const float surface_width = (float)layer->width * 0.25;
200 const float surface_height = (float)layer->height * 0.5;
201 int32_t surface_x = 0;
202 int32_t surface_y = 0;
203 struct ivi_layout_surface *ivisurf = NULL;
204 struct ivi_layout_surface **surfaces;
205 struct ivi_layout_surface **new_order;
206 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
207
208 int32_t i = 0;
209 int32_t surf_num = 0;
210 uint32_t num = 1;
211
212 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
213 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
214
215 for (i = 0; i < surface_length; i++) {
216 ivisurf = pp_surface[i];
217
218 /* skip ui widgets */
219 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
220 continue;
221
222 surfaces[surf_num++] = ivisurf;
223 }
224
225 for (i = 0; i < surf_num; i++) {
226 ivisurf = surfaces[i];
227 new_order[i] = ivisurf;
228
229 if (num <= 8) {
230 if (num < 5) {
231 surface_x = (int32_t)((num - 1) * (surface_width));
232 surface_y = 0;
233 } else {
234 surface_x = (int32_t)((num - 5) * (surface_width));
235 surface_y = (int32_t)surface_height;
236 }
237
238 ivi_layout_surface_set_transition(ivisurf,
239 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
240 duration);
241 ivi_layout_surface_set_visibility(ivisurf, true);
242 ivi_layout_surface_set_destination_rectangle(ivisurf,
243 surface_x, surface_y,
244 (int32_t)surface_width,
245 (int32_t)surface_height);
246
247 num++;
248 continue;
249 }
250 ivi_layout_surface_set_visibility(ivisurf, false);
251 }
252
253 if (surf_num > 0) {
254 ivi_layout_layer_set_transition(layer->ivilayer,
255 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
256 duration);
257 //TODO: implement IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER later.
258 ivi_layout_transition_layer_render_order(layer->ivilayer,
259 new_order,
260 surf_num,
261 duration);
262 }
263
264 free(surfaces);
265 free(new_order);
266}
267
268static void
269mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
270 struct ivi_layout_surface **pp_surface,
271 int32_t surface_length,
272 struct hmi_controller_layer *layer)
273{
274 int32_t surface_width = layer->width / 2;
275 int32_t surface_height = layer->height;
276 struct ivi_layout_surface *ivisurf = NULL;
277
278 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
279 int32_t i = 0;
280 int32_t num = 1;
281
282 for (i = 0; i < surface_length; i++) {
283 ivisurf = pp_surface[i];
284
285 /* skip ui widgets */
286 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
287 continue;
288
289 if (num == 1) {
290 ivi_layout_surface_set_transition(ivisurf,
291 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
292 duration);
293 ivi_layout_surface_set_visibility(ivisurf, true);
294 ivi_layout_surface_set_destination_rectangle(ivisurf,
295 0, 0,
296 surface_width,
297 surface_height);
298
299 num++;
300 continue;
301 } else if (num == 2) {
302 ivi_layout_surface_set_transition(ivisurf,
303 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
304 duration);
305 ivi_layout_surface_set_visibility(ivisurf, true);
306 ivi_layout_surface_set_destination_rectangle(ivisurf,
307 surface_width, 0,
308 surface_width,
309 surface_height);
310
311 num++;
312 continue;
313 }
314 ivi_layout_surface_set_transition(ivisurf,
315 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
316 duration);
317 ivi_layout_surface_set_visibility(ivisurf, false);
318 }
319}
320
321static void
322mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
323 struct ivi_layout_surface **pp_surface,
324 int32_t surface_length,
325 struct hmi_controller_layer *layer)
326{
327 const int32_t surface_width = layer->width;
328 const int32_t surface_height = layer->height;
329 struct ivi_layout_surface *ivisurf = NULL;
330 int32_t i = 0;
331 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
332
333 for (i = 0; i < surface_length; i++) {
334 ivisurf = pp_surface[i];
335
336 /* skip ui widgets */
337 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
338 continue;
339
340 ivi_layout_surface_set_transition(ivisurf,
341 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
342 duration);
343 ivi_layout_surface_set_visibility(ivisurf, true);
344 ivi_layout_surface_set_destination_rectangle(ivisurf, 0, 0,
345 surface_width,
346 surface_height);
347 }
348}
349
350static void
351mode_random_replace(struct hmi_controller *hmi_ctrl,
352 struct ivi_layout_surface **pp_surface,
353 int32_t surface_length,
354 struct hmi_controller_layer *layer)
355{
356 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
357 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
358 int32_t surface_x = 0;
359 int32_t surface_y = 0;
360 struct ivi_layout_surface *ivisurf = NULL;
361 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
362 int32_t i = 0;
363
364 for (i = 0; i < surface_length; i++) {
365 ivisurf = pp_surface[i];
366
367 /* skip ui widgets */
368 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
369 continue;
370
371 ivi_layout_surface_set_transition(ivisurf,
372 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
373 duration);
374 ivi_layout_surface_set_visibility(ivisurf, true);
375 surface_x = rand() % (layer->width - surface_width);
376 surface_y = rand() % (layer->height - surface_height);
377
378 ivi_layout_surface_set_destination_rectangle(ivisurf,
379 surface_x,
380 surface_y,
381 surface_width,
382 surface_height);
383 }
384}
385
386static int32_t
387has_application_surface(struct hmi_controller *hmi_ctrl,
388 struct ivi_layout_surface **pp_surface,
389 int32_t surface_length)
390{
391 struct ivi_layout_surface *ivisurf = NULL;
392 int32_t i = 0;
393
394 for (i = 0; i < surface_length; i++) {
395 ivisurf = pp_surface[i];
396
397 /* skip ui widgets */
398 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
399 continue;
400
401 return 1;
402 }
403
404 return 0;
405}
406
407/**
408 * Supports 4 example to layout of application ivi_surfaces;
409 * tiling, side by side, fullscreen, and random.
410 */
411static void
412switch_mode(struct hmi_controller *hmi_ctrl,
413 enum ivi_hmi_controller_layout_mode layout_mode)
414{
415 struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
416 struct ivi_layout_surface **pp_surface = NULL;
417 int32_t surface_length = 0;
418 int32_t ret = 0;
419
420 if (!hmi_ctrl->is_initialized)
421 return;
422
423 hmi_ctrl->layout_mode = layout_mode;
424
425 ret = ivi_layout_get_surfaces(&surface_length, &pp_surface);
426 assert(!ret);
427
428 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
429 free(pp_surface);
430 pp_surface = NULL;
431 return;
432 }
433
434 switch (layout_mode) {
435 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
436 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
437 layer);
438 break;
439 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
440 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
441 surface_length, layer);
442 break;
443 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
444 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
445 layer);
446 break;
447 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
448 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
449 layer);
450 break;
451 }
452
453 ivi_layout_commit_changes();
454 free(pp_surface);
455}
456
457/**
458 * Internal method for transition
459 */
460static void
461hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
462 struct hmi_controller_fade *fade)
463{
464 double tint = is_fade_in ? 1.0 : 0.0;
465 struct link_layer *linklayer = NULL;
466 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
467
468 fade->is_fade_in = is_fade_in;
469
470 wl_list_for_each(linklayer, &fade->layer_list, link) {
471 ivi_layout_layer_set_transition(linklayer->layout_layer,
472 IVI_LAYOUT_TRANSITION_LAYER_FADE,
473 duration);
474 ivi_layout_layer_set_fade_info(linklayer->layout_layer,
475 is_fade_in, 1.0 - tint, tint);
476 }
477}
478
479/**
480 * Internal method to create ivi_layer with hmi_controller_layer and
481 * add to a ivi_screen
482 */
483static void
484create_layer(struct ivi_layout_screen *iviscrn,
485 struct hmi_controller_layer *layer)
486{
487 int32_t ret = 0;
488
489 layer->ivilayer =
490 ivi_layout_layer_create_with_dimension(layer->id_layer,
491 layer->width,
492 layer->height);
493 assert(layer->ivilayer != NULL);
494
495 ret = ivi_layout_screen_add_layer(iviscrn, layer->ivilayer);
496 assert(!ret);
497
498 ret = ivi_layout_layer_set_destination_rectangle(layer->ivilayer,
499 layer->x, layer->y,
500 layer->width,
501 layer->height);
502 assert(!ret);
503
504 ret = ivi_layout_layer_set_visibility(layer->ivilayer, true);
505 assert(!ret);
506}
507
508/**
509 * Internal set notification
510 */
511static void
512set_notification_create_surface(struct ivi_layout_surface *ivisurf,
513 void *userdata)
514{
515 struct hmi_controller *hmi_ctrl = userdata;
516 struct ivi_layout_layer *application_layer =
517 hmi_ctrl->application_layer.ivilayer;
518 int32_t ret = 0;
519
520 /* skip ui widgets */
521 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
522 return;
523
524 ret = ivi_layout_layer_add_surface(application_layer, ivisurf);
525 assert(!ret);
526}
527
528static void
529set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
530 void *userdata)
531{
532 struct hmi_controller *hmi_ctrl = userdata;
533
534 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
535}
536
537static void
538set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
539 void *userdata)
540{
541 struct hmi_controller *hmi_ctrl = userdata;
542
543 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
544}
545
546/**
547 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
548 * corresponding ivi_layer are defined in weston.ini. Default scene graph
549 * of ivi_layers are initialized in hmi_controller_create
550 */
551static struct hmi_server_setting *
552hmi_server_setting_create(struct weston_compositor *ec)
553{
554 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
555 struct weston_config *config = ec->config;
556 struct weston_config_section *shell_section = NULL;
557
558 shell_section = weston_config_get_section(config, "ivi-shell",
559 NULL, NULL);
560
561 weston_config_section_get_uint(shell_section, "base-layer-id",
562 &setting->base_layer_id, 1000);
563
564 weston_config_section_get_uint(shell_section,
565 "workspace-background-layer-id",
566 &setting->workspace_background_layer_id,
567 2000);
568
569 weston_config_section_get_uint(shell_section, "workspace-layer-id",
570 &setting->workspace_layer_id, 3000);
571
572 weston_config_section_get_uint(shell_section, "application-layer-id",
573 &setting->application_layer_id, 4000);
574
575 weston_config_section_get_uint(shell_section, "transition-duration",
576 &setting->transition_duration, 300);
577
578 setting->panel_height = 70;
579
580 weston_config_section_get_string(shell_section,
581 "ivi-shell-user-interface",
582 &setting->ivi_homescreen, NULL);
583
584 return setting;
585}
586
587static void
588hmi_controller_destroy(struct wl_listener *listener, void *data)
589{
590 struct link_layer *link = NULL;
591 struct link_layer *next = NULL;
592 struct hmi_controller *hmi_ctrl =
593 container_of(listener, struct hmi_controller, destroy_listener);
594
595 wl_list_for_each_safe(link, next,
596 &hmi_ctrl->workspace_fade.layer_list, link) {
597 wl_list_remove(&link->link);
598 free(link);
599 }
600
601 wl_array_release(&hmi_ctrl->ui_widgets);
602 free(hmi_ctrl->hmi_setting);
603 free(hmi_ctrl);
604}
605
606/**
607 * This is a starting method called from module_init.
608 * This sets up scene graph of ivi_layers; base, application, workspace
609 * background, and workspace. These ivi_layers are created/added to
610 * ivi_screen in create_layer
611 *
612 * base: to group ivi_surfaces of panel and background
613 * application: to group ivi_surfaces of ivi_applications
614 * workspace background: to group a ivi_surface of background in workspace
615 * workspace: to group ivi_surfaces for launching ivi_applications
616 *
617 * ivi_layers of workspace background and workspace is set to invisible at
618 * first. The properties of it is updated with animation when
619 * ivi_hmi_controller_home is requested.
620 */
621static struct hmi_controller *
622hmi_controller_create(struct weston_compositor *ec)
623{
624 struct ivi_layout_screen **pp_screen = NULL;
625 struct ivi_layout_screen *iviscrn = NULL;
626 int32_t screen_length = 0;
627 int32_t screen_width = 0;
628 int32_t screen_height = 0;
629 struct link_layer *tmp_link_layer = NULL;
630 int32_t panel_height = 0;
631 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
632
633 wl_array_init(&hmi_ctrl->ui_widgets);
634 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
635 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
636 hmi_ctrl->compositor = ec;
637
638 ivi_layout_get_screens(&screen_length, &pp_screen);
639
640 iviscrn = pp_screen[0];
641
642 ivi_layout_get_screen_resolution(iviscrn, &screen_width,
643 &screen_height);
644
645 /* init base ivi_layer*/
646 hmi_ctrl->base_layer.x = 0;
647 hmi_ctrl->base_layer.y = 0;
648 hmi_ctrl->base_layer.width = screen_width;
649 hmi_ctrl->base_layer.height = screen_height;
650 hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
651
652 create_layer(iviscrn, &hmi_ctrl->base_layer);
653
654 panel_height = hmi_ctrl->hmi_setting->panel_height;
655
656 /* init application ivi_layer */
657 hmi_ctrl->application_layer.x = 0;
658 hmi_ctrl->application_layer.y = 0;
659 hmi_ctrl->application_layer.width = screen_width;
660 hmi_ctrl->application_layer.height = screen_height - panel_height;
661 hmi_ctrl->application_layer.id_layer =
662 hmi_ctrl->hmi_setting->application_layer_id;
663
664 create_layer(iviscrn, &hmi_ctrl->application_layer);
665
666 /* init workspace background ivi_layer */
667 hmi_ctrl->workspace_background_layer.x = 0;
668 hmi_ctrl->workspace_background_layer.y = 0;
669 hmi_ctrl->workspace_background_layer.width = screen_width;
670 hmi_ctrl->workspace_background_layer.height =
671 screen_height - panel_height;
672
673 hmi_ctrl->workspace_background_layer.id_layer =
674 hmi_ctrl->hmi_setting->workspace_background_layer_id;
675
676 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
677 ivi_layout_layer_set_opacity(
678 hmi_ctrl->workspace_background_layer.ivilayer, 0);
679 ivi_layout_layer_set_visibility(
680 hmi_ctrl->workspace_background_layer.ivilayer, false);
681
682 /* init workspace ivi_layer */
683 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
684 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
685 hmi_ctrl->workspace_layer.width =
686 hmi_ctrl->workspace_background_layer.width;
687 hmi_ctrl->workspace_layer.height =
688 hmi_ctrl->workspace_background_layer.height;
689 hmi_ctrl->workspace_layer.id_layer =
690 hmi_ctrl->hmi_setting->workspace_layer_id;
691
692 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
693 ivi_layout_layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
694 ivi_layout_layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
695 false);
696
697 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
698 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
699 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
700 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
701 &tmp_link_layer->link);
702 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
703 tmp_link_layer->layout_layer =
704 hmi_ctrl->workspace_background_layer.ivilayer;
705 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
706 &tmp_link_layer->link);
707
708 ivi_layout_add_notification_create_surface(
709 set_notification_create_surface, hmi_ctrl);
710 ivi_layout_add_notification_remove_surface(
711 set_notification_remove_surface, hmi_ctrl);
712 ivi_layout_add_notification_configure_surface(
713 set_notification_configure_surface, hmi_ctrl);
714
715 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
716 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
717 &hmi_ctrl->destroy_listener);
718
719 free(pp_screen);
720 pp_screen = NULL;
721
722 return hmi_ctrl;
723}
724
725/**
726 * Implementations of ivi-hmi-controller.xml
727 */
728
729/**
730 * A ivi_surface drawing background is identified by id_surface.
731 * Properties of the ivi_surface is set by using ivi_layout APIs according to
732 * the scene graph of UI defined in hmi_controller_create.
733 *
734 * UI ivi_layer is used to add this ivi_surface.
735 */
736static void
737ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
738 uint32_t id_surface)
739{
740 struct ivi_layout_surface *ivisurf = NULL;
741 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
742 const int32_t dstx = hmi_ctrl->application_layer.x;
743 const int32_t dsty = hmi_ctrl->application_layer.y;
744 const int32_t width = hmi_ctrl->application_layer.width;
745 const int32_t height = hmi_ctrl->application_layer.height;
746 int32_t ret = 0;
747
748 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
749 sizeof(*add_surface_id));
750 *add_surface_id = id_surface;
751
752 ivisurf = ivi_layout_get_surface_from_id(id_surface);
753 assert(ivisurf != NULL);
754
755 ret = ivi_layout_layer_add_surface(ivilayer, ivisurf);
756 assert(!ret);
757
758 ret = ivi_layout_surface_set_destination_rectangle(ivisurf,
759 dstx, dsty, width, height);
760 assert(!ret);
761
762 ret = ivi_layout_surface_set_visibility(ivisurf, true);
763 assert(!ret);
764}
765
766/**
767 * A ivi_surface drawing panel is identified by id_surface.
768 * Properties of the ivi_surface is set by using ivi_layout APIs according to
769 * the scene graph of UI defined in hmi_controller_create.
770 *
771 * UI ivi_layer is used to add this ivi_surface.
772 */
773static void
774ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
775 uint32_t id_surface)
776{
777 struct ivi_layout_surface *ivisurf = NULL;
778 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
779 const int32_t width = hmi_ctrl->base_layer.width;
780 int32_t ret = 0;
781 int32_t panel_height = 0;
782 const int32_t dstx = 0;
783 int32_t dsty = 0;
784
785 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
786 sizeof(*add_surface_id));
787 *add_surface_id = id_surface;
788
789 ivisurf = ivi_layout_get_surface_from_id(id_surface);
790 assert(ivisurf != NULL);
791
792 ret = ivi_layout_layer_add_surface(ivilayer, ivisurf);
793 assert(!ret);
794
795 panel_height = hmi_ctrl->hmi_setting->panel_height;
796
797 dsty = hmi_ctrl->base_layer.height - panel_height;
798
799 ret = ivi_layout_surface_set_destination_rectangle(
800 ivisurf, dstx, dsty, width, panel_height);
801 assert(!ret);
802
803 ret = ivi_layout_surface_set_visibility(ivisurf, true);
804 assert(!ret);
805}
806
807/**
808 * A ivi_surface drawing buttons in panel is identified by id_surface.
809 * It can set several buttons. Properties of the ivi_surface is set by
810 * using ivi_layout APIs according to the scene graph of UI defined in
811 * hmi_controller_create. Additionally, the position of it is shifted to
812 * right when new one is requested.
813 *
814 * UI ivi_layer is used to add these ivi_surfaces.
815 */
816static void
817ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
818 uint32_t id_surface, int32_t number)
819{
820 struct ivi_layout_surface *ivisurf = NULL;
821 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
822 const int32_t width = 48;
823 const int32_t height = 48;
824 int32_t ret = 0;
825 int32_t panel_height = 0;
826 int32_t dstx = 0;
827 int32_t dsty = 0;
828 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
829 sizeof(*add_surface_id));
830 *add_surface_id = id_surface;
831
832 ivisurf = ivi_layout_get_surface_from_id(id_surface);
833 assert(ivisurf != NULL);
834
835 ret = ivi_layout_layer_add_surface(ivilayer, ivisurf);
836 assert(!ret);
837
838 panel_height = hmi_ctrl->hmi_setting->panel_height;
839
840 dstx = (60 * number) + 15;
841 dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
842
843 ret = ivi_layout_surface_set_destination_rectangle(
844 ivisurf,dstx, dsty, width, height);
845 assert(!ret);
846
847 ret = ivi_layout_surface_set_visibility(ivisurf, true);
848 assert(!ret);
849}
850
851/**
852 * A ivi_surface drawing home button in panel is identified by id_surface.
853 * Properties of the ivi_surface is set by using ivi_layout APIs according to
854 * the scene graph of UI defined in hmi_controller_create.
855 *
856 * UI ivi_layer is used to add these ivi_surfaces.
857 */
858static void
859ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
860 uint32_t id_surface)
861{
862 struct ivi_layout_surface *ivisurf = NULL;
863 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
864 int32_t ret = 0;
865 int32_t size = 48;
866 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
867 const int32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
868 const int32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
869
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
874 ivisurf = ivi_layout_get_surface_from_id(id_surface);
875 assert(ivisurf != NULL);
876
877 ret = ivi_layout_layer_add_surface(ivilayer, ivisurf);
878 assert(!ret);
879
880 ret = ivi_layout_surface_set_destination_rectangle(
881 ivisurf, dstx, dsty, size, size);
882 assert(!ret);
883
884 ret = ivi_layout_surface_set_visibility(ivisurf, true);
885 assert(!ret);
886}
887
888/**
889 * A ivi_surface drawing background of workspace is identified by id_surface.
890 * Properties of the ivi_surface is set by using ivi_layout APIs according to
891 * the scene graph of UI defined in hmi_controller_create.
892 *
893 * A ivi_layer of workspace_background is used to add this ivi_surface.
894 */
895static void
896ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
897 uint32_t id_surface)
898{
899 struct ivi_layout_surface *ivisurf = NULL;
900 struct ivi_layout_layer *ivilayer = NULL;
901 const int32_t width = hmi_ctrl->workspace_background_layer.width;
902 const int32_t height = hmi_ctrl->workspace_background_layer.height;
903 int32_t ret = 0;
904
905 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
906 sizeof(*add_surface_id));
907 *add_surface_id = id_surface;
908 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
909
910 ivisurf = ivi_layout_get_surface_from_id(id_surface);
911 assert(ivisurf != NULL);
912
913 ret = ivi_layout_layer_add_surface(ivilayer, ivisurf);
914 assert(!ret);
915
916 ret = ivi_layout_surface_set_destination_rectangle(ivisurf,
917 0, 0, width, height);
918 assert(!ret);
919
920 ret = ivi_layout_surface_set_visibility(ivisurf, true);
921 assert(!ret);
922}
923
924/**
925 * A list of ivi_surfaces drawing launchers in workspace is identified by
926 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
927 * APIs according to the scene graph of UI defined in hmi_controller_create.
928 *
929 * The workspace can have several pages to group ivi_surfaces of launcher.
930 * Each call of this interface increments a number of page to add a group
931 * of ivi_surfaces
932 */
933static void
934ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
935 int32_t icon_size)
936{
937 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
938 int32_t minspace_x = 10;
939 int32_t minspace_y = minspace_x;
940
941 int32_t width = hmi_ctrl->workspace_layer.width;
942 int32_t height = hmi_ctrl->workspace_layer.height;
943
944 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
945 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
946 float fcell_size_x = icon_size + space_x;
947
948 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
949 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
950 float fcell_size_y = icon_size + space_y;
951
952 struct weston_config *config = NULL;
953 struct weston_config_section *section = NULL;
954 const char *name = NULL;
955 int launcher_count = 0;
956 struct wl_array launchers;
957 int32_t nx = 0;
958 int32_t ny = 0;
959 int32_t prev = -1;
960 struct launcher_info *data = NULL;
961
962 uint32_t surfaceid = 0;
963 uint32_t workspaceid = 0;
964 struct launcher_info *info = NULL;
965
966 int32_t x = 0;
967 int32_t y = 0;
968 int32_t ret = 0;
969 struct ivi_layout_surface* layout_surface = NULL;
970 uint32_t *add_surface_id = NULL;
971
972 if (0 == x_count)
973 x_count = 1;
974
975 if (0 == y_count)
976 y_count = 1;
977
978 config = hmi_ctrl->compositor->config;
979 if (!config)
980 return;
981
982 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
983 if (!section)
984 return;
985
986 wl_array_init(&launchers);
987
988 while (weston_config_next_section(config, &section, &name)) {
989 surfaceid = 0;
990 workspaceid = 0;
991 info = NULL;
992 if (0 != strcmp(name, "ivi-launcher"))
993 continue;
994
995 if (0 != weston_config_section_get_uint(section, "icon-id",
996 &surfaceid, 0))
997 continue;
998
999 if (0 != weston_config_section_get_uint(section,
1000 "workspace-id",
1001 &workspaceid, 0))
1002 continue;
1003
1004 info = wl_array_add(&launchers, sizeof(*info));
1005
1006 if (info) {
1007 info->surface_id = surfaceid;
1008 info->workspace_id = workspaceid;
1009 info->index = launcher_count;
1010 ++launcher_count;
1011 }
1012 }
1013
1014 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1015 compare_launcher_info);
1016
1017 wl_array_for_each(data, &launchers) {
1018 x = 0;
1019 y = 0;
1020 ret = 0;
1021 layout_surface = NULL;
1022 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1023 sizeof(*add_surface_id));
1024
1025 *add_surface_id = data->surface_id;
1026
1027 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1028 nx = 0;
1029 ny = 0;
1030 prev = data->workspace_id;
1031
1032 if (0 <= prev)
1033 hmi_ctrl->workspace_count++;
1034 }
1035
1036 if (y_count == ny) {
1037 ny = 0;
1038 hmi_ctrl->workspace_count++;
1039 }
1040
1041 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1042 y = ny * fcell_size_y + space_y;
1043
1044 layout_surface =
1045 ivi_layout_get_surface_from_id(data->surface_id);
1046 assert(layout_surface);
1047
1048 ret = ivi_layout_layer_add_surface(layer, layout_surface);
1049 assert(!ret);
1050
1051 ret = ivi_layout_surface_set_destination_rectangle(
1052 layout_surface, x, y, icon_size, icon_size);
1053 assert(!ret);
1054
1055 ret = ivi_layout_surface_set_visibility(layout_surface, true);
1056 assert(!ret);
1057
1058 nx++;
1059
1060 if (x_count == nx) {
1061 ny++;
1062 nx = 0;
1063 }
1064 }
1065
1066 wl_array_release(&launchers);
1067 ivi_layout_commit_changes();
1068}
1069
1070static void
1071ivi_hmi_controller_UI_ready(struct wl_client *client,
1072 struct wl_resource *resource)
1073{
1074 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1075
1076 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1077 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1078 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1079 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1080 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1081 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1082 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1083 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
1084 ivi_layout_commit_changes();
1085
1086 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1087 hmi_ctrl->is_initialized = 1;
1088}
1089
1090/**
1091 * Implementation of request and event of ivi_hmi_controller_workspace_control
1092 * and controlling workspace.
1093 *
1094 * When motion of input is detected in a ivi_surface of workspace background,
1095 * ivi_hmi_controller_workspace_control shall be invoked and to start
1096 * controlling of workspace. The workspace has several pages to show several
1097 * groups of applications.
1098 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1099 * according to motion. When motion finished, e.g. touch up detected, control is
1100 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1101 */
1102struct pointer_grab {
1103 struct weston_pointer_grab grab;
1104 struct ivi_layout_layer *layer;
1105 struct wl_resource *resource;
1106};
1107
1108struct touch_grab {
1109 struct weston_touch_grab grab;
1110 struct ivi_layout_layer *layer;
1111 struct wl_resource *resource;
1112};
1113
1114struct move_grab {
1115 wl_fixed_t dst[2];
1116 wl_fixed_t rgn[2][2];
1117 double v[2];
1118 struct timespec start_time;
1119 struct timespec pre_time;
1120 wl_fixed_t start_pos[2];
1121 wl_fixed_t pos[2];
1122 int32_t is_moved;
1123};
1124
1125struct pointer_move_grab {
1126 struct pointer_grab base;
1127 struct move_grab move;
1128};
1129
1130struct touch_move_grab {
1131 struct touch_grab base;
1132 struct move_grab move;
1133 int32_t is_active;
1134};
1135
1136static void
1137pointer_grab_start(struct pointer_grab *grab,
1138 struct ivi_layout_layer *layer,
1139 const struct weston_pointer_grab_interface *interface,
1140 struct weston_pointer *pointer)
1141{
1142 grab->grab.interface = interface;
1143 grab->layer = layer;
1144 weston_pointer_start_grab(pointer, &grab->grab);
1145}
1146
1147static void
1148touch_grab_start(struct touch_grab *grab,
1149 struct ivi_layout_layer *layer,
1150 const struct weston_touch_grab_interface *interface,
1151 struct weston_touch* touch)
1152{
1153 grab->grab.interface = interface;
1154 grab->layer = layer;
1155 weston_touch_start_grab(touch, &grab->grab);
1156}
1157
1158static int32_t
1159clamp(int32_t val, int32_t min, int32_t max)
1160{
1161 if (val < min)
1162 return min;
1163
1164 if (max < val)
1165 return max;
1166
1167 return val;
1168}
1169
1170static void
1171move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1172 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1173{
1174 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1175 int32_t width = hmi_ctrl->workspace_background_layer.width;
1176
1177 struct timespec time = {0};
1178 double grab_time = 0.0;
1179 double from_motion_time = 0.0;
1180 double pointer_v = 0.0;
1181 int32_t is_flick = 0;
1182 int32_t pos_x = 0;
1183 int32_t pos_y = 0;
1184 int page_no = 0;
1185 double end_pos = 0.0;
1186 uint32_t duration = 0;
1187
1188 clock_gettime(CLOCK_MONOTONIC, &time);
1189
1190 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1191 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1192
1193 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1194 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1195
1196 pointer_v = move->v[0];
1197
1198 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1199 if (200 < from_motion_time)
1200 pointer_v = 0.0;
1201
1202 ivi_layout_layer_get_position(layer, &pos_x, &pos_y);
1203
1204
1205 if (is_flick) {
1206 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1207 page_no = (-orgx + width / 2) / width;
1208
1209 if (pointer_v < 0.0)
1210 page_no++;
1211 else
1212 page_no--;
1213 } else {
1214 page_no = (-pos_x + width / 2) / width;
1215 }
1216
1217 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1218 end_pos = -page_no * width;
1219
1220 duration = hmi_ctrl->hmi_setting->transition_duration;
1221 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
1222 ivi_layout_layer_set_transition(layer,
1223 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1224 duration);
1225 ivi_layout_layer_set_destination_rectangle(layer,
1226 end_pos, pos_y,
1227 hmi_ctrl->workspace_background_layer.width,
1228 hmi_ctrl->workspace_background_layer.height);
1229 ivi_layout_commit_changes();
1230}
1231
1232static void
1233pointer_move_workspace_grab_end(struct pointer_grab *grab)
1234{
1235 struct pointer_move_grab *pnt_move_grab =
1236 (struct pointer_move_grab *)grab;
1237 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1238
1239 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1240 grab->grab.pointer->grab_x, layer);
1241
1242 weston_pointer_end_grab(grab->grab.pointer);
1243}
1244
1245static void
1246touch_move_workspace_grab_end(struct touch_grab *grab)
1247{
1248 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1249 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1250
1251 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1252 grab->grab.touch->grab_x, layer);
1253
1254 weston_touch_end_grab(grab->grab.touch);
1255}
1256
1257static void
1258pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1259{
1260}
1261
1262static void
1263move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1264{
1265 struct timespec timestamp = {0};
1266 int32_t ii = 0;
1267 double dt = 0.0;
1268
1269 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1270 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1271 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1272
1273 if (dt < 1e-6)
1274 dt = 1e-6;
1275
1276 move->pre_time = timestamp;
1277
1278 for (ii = 0; ii < 2; ii++) {
1279 wl_fixed_t prepos = move->pos[ii];
1280 move->pos[ii] = pointer[ii] + move->dst[ii];
1281
1282 if (move->pos[ii] < move->rgn[0][ii]) {
1283 move->pos[ii] = move->rgn[0][ii];
1284 move->dst[ii] = move->pos[ii] - pointer[ii];
1285 } else if (move->rgn[1][ii] < move->pos[ii]) {
1286 move->pos[ii] = move->rgn[1][ii];
1287 move->dst[ii] = move->pos[ii] - pointer[ii];
1288 }
1289
1290 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1291
1292 if (!move->is_moved &&
1293 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1294 move->is_moved = 1;
1295 }
1296}
1297
1298static void
1299layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1300 wl_fixed_t pos_y)
1301{
1302 int32_t layout_pos_x = 0;
1303 int32_t layout_pos_y = 0;
1304
1305 layout_pos_x = wl_fixed_to_int(pos_x);
1306 layout_pos_y = wl_fixed_to_int(pos_y);
1307 ivi_layout_layer_set_position(layer, layout_pos_x, layout_pos_y);
1308 ivi_layout_commit_changes();
1309}
1310
1311static void
1312pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1313 wl_fixed_t x, wl_fixed_t y)
1314{
1315 struct pointer_move_grab *pnt_move_grab =
1316 (struct pointer_move_grab *)grab;
1317 wl_fixed_t pointer_pos[2] = {x, y};
1318
1319 move_grab_update(&pnt_move_grab->move, pointer_pos);
1320 layer_set_pos(pnt_move_grab->base.layer,
1321 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
1322 weston_pointer_move(pnt_move_grab->base.grab.pointer, x, y);
1323}
1324
1325static void
1326touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1327 int touch_id, wl_fixed_t x, wl_fixed_t y)
1328{
1329 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1330
1331 if (!tch_move_grab->is_active)
1332 return;
1333
1334 wl_fixed_t pointer_pos[2] = {
1335 grab->touch->grab_x,
1336 grab->touch->grab_y
1337 };
1338
1339 move_grab_update(&tch_move_grab->move, pointer_pos);
1340 layer_set_pos(tch_move_grab->base.layer,
1341 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1342}
1343
1344static void
1345pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1346 uint32_t time, uint32_t button,
1347 uint32_t state_w)
1348{
1349 if (BTN_LEFT == button &&
1350 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1351 struct pointer_grab *pg = (struct pointer_grab *)grab;
1352
1353 pointer_move_workspace_grab_end(pg);
1354 free(grab);
1355 }
1356}
1357
1358static void
1359touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1360 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1361{
1362}
1363
1364static void
1365touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1366 int touch_id)
1367{
1368 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1369
1370 if (0 == touch_id)
1371 tch_move_grab->is_active = 0;
1372
1373 if (0 == grab->touch->num_tp) {
1374 touch_move_workspace_grab_end(&tch_move_grab->base);
1375 free(grab);
1376 }
1377}
1378
1379static void
1380pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1381{
1382 struct pointer_grab *pg = (struct pointer_grab *)grab;
1383
1384 pointer_move_workspace_grab_end(pg);
1385 free(grab);
1386}
1387
1388static void
1389touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1390{
1391 struct touch_grab *tg = (struct touch_grab *)grab;
1392
1393 touch_move_workspace_grab_end(tg);
1394 free(grab);
1395}
1396
1397static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1398 pointer_noop_grab_focus,
1399 pointer_move_grab_motion,
1400 pointer_move_workspace_grab_button,
1401 pointer_move_workspace_grab_cancel
1402};
1403
1404static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1405 touch_nope_grab_down,
1406 touch_move_workspace_grab_up,
1407 touch_move_grab_motion,
1408 touch_move_workspace_grab_cancel
1409};
1410
1411enum HMI_GRAB_DEVICE {
1412 HMI_GRAB_DEVICE_NONE,
1413 HMI_GRAB_DEVICE_POINTER,
1414 HMI_GRAB_DEVICE_TOUCH
1415};
1416
1417static enum HMI_GRAB_DEVICE
1418get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1419{
1420 if (seat->pointer &&
1421 seat->pointer->focus &&
1422 seat->pointer->button_count &&
1423 seat->pointer->grab_serial == serial)
1424 return HMI_GRAB_DEVICE_POINTER;
1425
1426 if (seat->touch &&
1427 seat->touch->focus &&
1428 seat->touch->grab_serial == serial)
1429 return HMI_GRAB_DEVICE_TOUCH;
1430
1431 return HMI_GRAB_DEVICE_NONE;
1432}
1433
1434static void
1435move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1436 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1437 struct wl_resource* resource)
1438{
1439 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1440 move->pre_time = move->start_time;
1441 move->pos[0] = start_pos[0];
1442 move->pos[1] = start_pos[1];
1443 move->start_pos[0] = start_pos[0];
1444 move->start_pos[1] = start_pos[1];
1445 move->dst[0] = start_pos[0] - grab_pos[0];
1446 move->dst[1] = start_pos[1] - grab_pos[1];
1447 memcpy(move->rgn, rgn, sizeof(move->rgn));
1448}
1449
1450static void
1451move_grab_init_workspace(struct move_grab* move,
1452 wl_fixed_t grab_x, wl_fixed_t grab_y,
1453 struct wl_resource *resource)
1454{
1455 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1456 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1457 int32_t workspace_count = hmi_ctrl->workspace_count;
1458 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1459 int32_t layer_pos_x = 0;
1460 int32_t layer_pos_y = 0;
1461 wl_fixed_t start_pos[2] = {0};
1462 wl_fixed_t rgn[2][2] = {{0}};
1463 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1464
1465 ivi_layout_layer_get_position(layer, &layer_pos_x, &layer_pos_y);
1466
1467 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1468 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1469
1470 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1471
1472 rgn[0][1] = wl_fixed_from_int(0);
1473 rgn[1][0] = wl_fixed_from_int(0);
1474 rgn[1][1] = wl_fixed_from_int(0);
1475
1476 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1477}
1478
1479static struct pointer_move_grab *
1480create_workspace_pointer_move(struct weston_pointer *pointer,
1481 struct wl_resource* resource)
1482{
1483 struct pointer_move_grab *pnt_move_grab =
1484 MEM_ALLOC(sizeof(*pnt_move_grab));
1485
1486 pnt_move_grab->base.resource = resource;
1487 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1488 pointer->grab_y, resource);
1489
1490 return pnt_move_grab;
1491}
1492
1493static struct touch_move_grab *
1494create_workspace_touch_move(struct weston_touch *touch,
1495 struct wl_resource* resource)
1496{
1497 struct touch_move_grab *tch_move_grab =
1498 MEM_ALLOC(sizeof(*tch_move_grab));
1499
1500 tch_move_grab->base.resource = resource;
1501 tch_move_grab->is_active = 1;
1502 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1503 touch->grab_y, resource);
1504
1505 return tch_move_grab;
1506}
1507
1508static void
1509ivi_hmi_controller_workspace_control(struct wl_client *client,
1510 struct wl_resource *resource,
1511 struct wl_resource *seat_resource,
1512 uint32_t serial)
1513{
1514 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1515 struct ivi_layout_layer *layer = NULL;
1516 struct pointer_move_grab *pnt_move_grab = NULL;
1517 struct touch_move_grab *tch_move_grab = NULL;
1518 struct weston_seat *seat = NULL;
1519 enum HMI_GRAB_DEVICE device;
1520
1521 if (hmi_ctrl->workspace_count < 2)
1522 return;
1523
1524 seat = wl_resource_get_user_data(seat_resource);
1525 device = get_hmi_grab_device(seat, serial);
1526
1527 if (HMI_GRAB_DEVICE_POINTER != device &&
1528 HMI_GRAB_DEVICE_TOUCH != device)
1529 return;
1530
1531 layer = hmi_ctrl->workspace_layer.ivilayer;
1532
1533 ivi_layout_transition_move_layer_cancel(layer);
1534
1535 switch (device) {
1536 case HMI_GRAB_DEVICE_POINTER:
1537 pnt_move_grab = create_workspace_pointer_move(seat->pointer,
1538 resource);
1539
1540 pointer_grab_start(&pnt_move_grab->base, layer,
1541 &pointer_move_grab_workspace_interface,
1542 seat->pointer);
1543 break;
1544
1545 case HMI_GRAB_DEVICE_TOUCH:
1546 tch_move_grab = create_workspace_touch_move(seat->touch,
1547 resource);
1548
1549 touch_grab_start(&tch_move_grab->base, layer,
1550 &touch_move_grab_workspace_interface,
1551 seat->touch);
1552 break;
1553
1554 default:
1555 break;
1556 }
1557}
1558
1559/**
1560 * Implementation of switch_mode
1561 */
1562static void
1563ivi_hmi_controller_switch_mode(struct wl_client *client,
1564 struct wl_resource *resource,
1565 uint32_t layout_mode)
1566{
1567 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1568
1569 switch_mode(hmi_ctrl, layout_mode);
1570}
1571
1572/**
1573 * Implementation of on/off displaying workspace and workspace background
1574 * ivi_layers.
1575 */
1576static void
1577ivi_hmi_controller_home(struct wl_client *client,
1578 struct wl_resource *resource,
1579 uint32_t home)
1580{
1581 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1582 uint32_t is_fade_in;
1583
1584 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1585 !hmi_ctrl->workspace_fade.is_fade_in) ||
1586 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1587 hmi_ctrl->workspace_fade.is_fade_in)) {
1588 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1589 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1590 &hmi_ctrl->workspace_fade);
1591 }
1592
1593 ivi_layout_commit_changes();
1594}
1595
1596/**
1597 * binding ivi-hmi-controller implementation
1598 */
1599static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1600 ivi_hmi_controller_UI_ready,
1601 ivi_hmi_controller_workspace_control,
1602 ivi_hmi_controller_switch_mode,
1603 ivi_hmi_controller_home
1604};
1605
1606static void
1607unbind_hmi_controller(struct wl_resource *resource)
1608{
1609}
1610
1611static void
1612bind_hmi_controller(struct wl_client *client,
1613 void *data, uint32_t version, uint32_t id)
1614{
1615 struct wl_resource *resource = NULL;
1616 struct hmi_controller *hmi_ctrl = data;
1617
1618 if (hmi_ctrl->user_interface != client) {
1619 struct wl_resource *res = wl_client_get_object(client, 1);
1620 wl_resource_post_error(res,
1621 WL_DISPLAY_ERROR_INVALID_OBJECT,
1622 "hmi-controller failed: permission denied");
1623 return;
1624 }
1625
1626 resource = wl_resource_create(
1627 client, &ivi_hmi_controller_interface, 1, id);
1628
1629 wl_resource_set_implementation(
1630 resource, &ivi_hmi_controller_implementation,
1631 hmi_ctrl, unbind_hmi_controller);
1632}
1633
1634static int32_t
1635initialize(struct hmi_controller *hmi_ctrl)
1636{
1637 struct config_command {
1638 char *key;
1639 uint32_t *dest;
1640 };
1641
1642 struct weston_config *config = hmi_ctrl->compositor->config;
1643 struct weston_config_section *section = NULL;
1644 int result = 0;
1645 int i = 0;
1646
1647 const struct config_command uint_commands[] = {
1648 { "background-id", &hmi_ctrl->ui_setting.background_id },
1649 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1650 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1651 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1652 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1653 { "random-id", &hmi_ctrl->ui_setting.random_id },
1654 { "home-id", &hmi_ctrl->ui_setting.home_id },
1655 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
1656 { NULL, NULL }
1657 };
1658
1659 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1660
1661 for (i = 0; -1 != result; ++i) {
1662 const struct config_command *command = &uint_commands[i];
1663
1664 if (!command->key)
1665 break;
1666
1667 if (weston_config_section_get_uint(
1668 section, command->key, command->dest, 0) != 0)
1669 result = -1;
1670 }
1671
1672 if (-1 == result) {
1673 weston_log("Failed to initialize hmi-controller\n");
1674 return 0;
1675 }
1676
1677 return 1;
1678}
1679
1680static void
1681launch_hmi_client_process(void *data)
1682{
1683 struct hmi_controller *hmi_ctrl =
1684 (struct hmi_controller *)data;
1685
1686 hmi_ctrl->user_interface =
1687 weston_client_start(hmi_ctrl->compositor,
1688 hmi_ctrl->hmi_setting->ivi_homescreen);
1689
1690 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1691}
1692
1693/*****************************************************************************
1694 * exported functions
1695 ****************************************************************************/
1696
1697WL_EXPORT int
1698module_init(struct weston_compositor *ec,
1699 int *argc, char *argv[])
1700{
1701 struct hmi_controller *hmi_ctrl = hmi_controller_create(ec);
1702 struct wl_event_loop *loop = NULL;
1703
1704 if (!initialize(hmi_ctrl)) {
1705 return -1;
1706 }
1707
1708 if (wl_global_create(ec->wl_display,
1709 &ivi_hmi_controller_interface, 1,
1710 hmi_ctrl, bind_hmi_controller) == NULL) {
1711 return -1;
1712 }
1713
1714 loop = wl_display_get_event_loop(ec->wl_display);
1715 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1716
1717 return 0;
1718}