blob: 66dde79cd862aa3207eb36d50d4d44a5e2d03e31 [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;
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900127
128 int32_t screen_num;
129 struct ivi_layout_screen **pp_screen;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900130};
131
132struct launcher_info {
133 uint32_t surface_id;
134 uint32_t workspace_id;
135 int32_t index;
136};
137
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000138const struct ivi_layout_interface *ivi_layout_interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900139
140int
141controller_module_init(struct weston_compositor *ec,
142 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000143 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900144 size_t interface_version);
145
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900146/*****************************************************************************
147 * local functions
148 ****************************************************************************/
149static void *
150fail_on_null(void *p, size_t size, char *file, int32_t line)
151{
152 if (size && !p) {
153 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
154 exit(EXIT_FAILURE);
155 }
156
157 return p;
158}
159
160static void *
161mem_alloc(size_t size, char *file, int32_t line)
162{
163 return fail_on_null(calloc(1, size), size, file, line);
164}
165
166#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
167
168static int32_t
169is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
170 struct ivi_layout_surface *ivisurf)
171{
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000172 uint32_t id = ivi_layout_interface->get_id_of_surface(ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900173
174 uint32_t *ui_widget_id = NULL;
175 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
176 if (*ui_widget_id == id)
177 return 1;
178 }
179
180 return 0;
181}
182
183static int
184compare_launcher_info(const void *lhs, const void *rhs)
185{
186 const struct launcher_info *left = lhs;
187 const struct launcher_info *right = rhs;
188
189 if (left->workspace_id < right->workspace_id)
190 return -1;
191
192 if (left->workspace_id > right->workspace_id)
193 return 1;
194
195 if (left->index < right->index)
196 return -1;
197
198 if (left->index > right->index)
199 return 1;
200
201 return 0;
202}
203
204/**
205 * Internal methods called by mainly ivi_hmi_controller_switch_mode
206 * This reference shows 4 examples how to use ivi_layout APIs.
207 */
208static void
209mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
210 struct ivi_layout_surface **pp_surface,
211 int32_t surface_length,
212 struct hmi_controller_layer *layer)
213{
214 const float surface_width = (float)layer->width * 0.25;
215 const float surface_height = (float)layer->height * 0.5;
216 int32_t surface_x = 0;
217 int32_t surface_y = 0;
218 struct ivi_layout_surface *ivisurf = NULL;
219 struct ivi_layout_surface **surfaces;
220 struct ivi_layout_surface **new_order;
221 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
222
223 int32_t i = 0;
224 int32_t surf_num = 0;
225 uint32_t num = 1;
226
227 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
228 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
229
230 for (i = 0; i < surface_length; i++) {
231 ivisurf = pp_surface[i];
232
233 /* skip ui widgets */
234 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
235 continue;
236
237 surfaces[surf_num++] = ivisurf;
238 }
239
240 for (i = 0; i < surf_num; i++) {
241 ivisurf = surfaces[i];
242 new_order[i] = ivisurf;
243
244 if (num <= 8) {
245 if (num < 5) {
246 surface_x = (int32_t)((num - 1) * (surface_width));
247 surface_y = 0;
248 } else {
249 surface_x = (int32_t)((num - 5) * (surface_width));
250 surface_y = (int32_t)surface_height;
251 }
252
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000253 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900254 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
255 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000256 ivi_layout_interface->surface_set_visibility(ivisurf, true);
257 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900258 surface_x, surface_y,
259 (int32_t)surface_width,
260 (int32_t)surface_height);
261
262 num++;
263 continue;
264 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000265 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900266 }
267
268 if (surf_num > 0) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000269 ivi_layout_interface->layer_set_transition(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900270 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
271 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900272 }
273
274 free(surfaces);
275 free(new_order);
276}
277
278static void
279mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
280 struct ivi_layout_surface **pp_surface,
281 int32_t surface_length,
282 struct hmi_controller_layer *layer)
283{
284 int32_t surface_width = layer->width / 2;
285 int32_t surface_height = layer->height;
286 struct ivi_layout_surface *ivisurf = NULL;
287
288 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
289 int32_t i = 0;
290 int32_t num = 1;
291
292 for (i = 0; i < surface_length; i++) {
293 ivisurf = pp_surface[i];
294
295 /* skip ui widgets */
296 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
297 continue;
298
299 if (num == 1) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000300 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900301 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
302 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000303 ivi_layout_interface->surface_set_visibility(ivisurf, true);
304 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900305 0, 0,
306 surface_width,
307 surface_height);
308
309 num++;
310 continue;
311 } else if (num == 2) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000312 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900313 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
314 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000315 ivi_layout_interface->surface_set_visibility(ivisurf, true);
316 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900317 surface_width, 0,
318 surface_width,
319 surface_height);
320
321 num++;
322 continue;
323 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000324 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900325 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
326 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000327 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900328 }
329}
330
331static void
332mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
333 struct ivi_layout_surface **pp_surface,
334 int32_t surface_length,
335 struct hmi_controller_layer *layer)
336{
337 const int32_t surface_width = layer->width;
338 const int32_t surface_height = layer->height;
339 struct ivi_layout_surface *ivisurf = NULL;
340 int32_t i = 0;
341 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
342
343 for (i = 0; i < surface_length; i++) {
344 ivisurf = pp_surface[i];
345
346 /* skip ui widgets */
347 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
348 continue;
349
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000350 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900351 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
352 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000353 ivi_layout_interface->surface_set_visibility(ivisurf, true);
354 ivi_layout_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900355 surface_width,
356 surface_height);
357 }
358}
359
360static void
361mode_random_replace(struct hmi_controller *hmi_ctrl,
362 struct ivi_layout_surface **pp_surface,
363 int32_t surface_length,
364 struct hmi_controller_layer *layer)
365{
366 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
367 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
368 int32_t surface_x = 0;
369 int32_t surface_y = 0;
370 struct ivi_layout_surface *ivisurf = NULL;
371 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
372 int32_t i = 0;
373
374 for (i = 0; i < surface_length; i++) {
375 ivisurf = pp_surface[i];
376
377 /* skip ui widgets */
378 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
379 continue;
380
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000381 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900382 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
383 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000384 ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900385 surface_x = rand() % (layer->width - surface_width);
386 surface_y = rand() % (layer->height - surface_height);
387
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000388 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900389 surface_x,
390 surface_y,
391 surface_width,
392 surface_height);
393 }
394}
395
396static int32_t
397has_application_surface(struct hmi_controller *hmi_ctrl,
398 struct ivi_layout_surface **pp_surface,
399 int32_t surface_length)
400{
401 struct ivi_layout_surface *ivisurf = NULL;
402 int32_t i = 0;
403
404 for (i = 0; i < surface_length; i++) {
405 ivisurf = pp_surface[i];
406
407 /* skip ui widgets */
408 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
409 continue;
410
411 return 1;
412 }
413
414 return 0;
415}
416
417/**
418 * Supports 4 example to layout of application ivi_surfaces;
419 * tiling, side by side, fullscreen, and random.
420 */
421static void
422switch_mode(struct hmi_controller *hmi_ctrl,
423 enum ivi_hmi_controller_layout_mode layout_mode)
424{
425 struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
426 struct ivi_layout_surface **pp_surface = NULL;
427 int32_t surface_length = 0;
428 int32_t ret = 0;
429
430 if (!hmi_ctrl->is_initialized)
431 return;
432
433 hmi_ctrl->layout_mode = layout_mode;
434
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000435 ret = ivi_layout_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900436 assert(!ret);
437
438 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
439 free(pp_surface);
440 pp_surface = NULL;
441 return;
442 }
443
444 switch (layout_mode) {
445 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
446 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
447 layer);
448 break;
449 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
450 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
451 surface_length, layer);
452 break;
453 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
454 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
455 layer);
456 break;
457 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
458 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
459 layer);
460 break;
461 }
462
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000463 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900464 free(pp_surface);
465}
466
467/**
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900468 * Internal method to get screens from weston core
469 * TODO: shall support hotplug of screens
470 */
471static int32_t
472get_screens(struct hmi_controller *hmi_ctrl)
473{
474 hmi_ctrl->pp_screen = NULL;
475 hmi_ctrl->screen_num = 0;
476 ivi_layout_interface->get_screens(&hmi_ctrl->screen_num, &hmi_ctrl->pp_screen);
477
478 if (hmi_ctrl->pp_screen == NULL)
479 return -1;
480 else
481 return 0;
482}
483
484/**
485 * Internal method to get ivi_layout_screen
486 */
487static struct ivi_layout_screen *
488get_screen(int32_t screen_idx, struct hmi_controller *hmi_ctrl)
489{
490 struct ivi_layout_screen *iviscrn = NULL;
491
492 if (screen_idx > hmi_ctrl->screen_num - 1)
493 weston_log("Invalid index. Return NULL\n");
494 else
495 iviscrn = hmi_ctrl->pp_screen[screen_idx];
496
497 return iviscrn;
498}
499
500/**
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900501 * Internal method for transition
502 */
503static void
504hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
505 struct hmi_controller_fade *fade)
506{
507 double tint = is_fade_in ? 1.0 : 0.0;
508 struct link_layer *linklayer = NULL;
509 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
510
511 fade->is_fade_in = is_fade_in;
512
513 wl_list_for_each(linklayer, &fade->layer_list, link) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000514 ivi_layout_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900515 IVI_LAYOUT_TRANSITION_LAYER_FADE,
516 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000517 ivi_layout_interface->layer_set_fade_info(linklayer->layout_layer,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900518 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900519 }
520}
521
522/**
523 * Internal method to create ivi_layer with hmi_controller_layer and
524 * add to a ivi_screen
525 */
526static void
527create_layer(struct ivi_layout_screen *iviscrn,
528 struct hmi_controller_layer *layer)
529{
530 int32_t ret = 0;
531
532 layer->ivilayer =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000533 ivi_layout_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900534 layer->width,
535 layer->height);
536 assert(layer->ivilayer != NULL);
537
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000538 ret = ivi_layout_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900539 assert(!ret);
540
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000541 ret = ivi_layout_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900542 layer->x, layer->y,
543 layer->width,
544 layer->height);
545 assert(!ret);
546
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000547 ret = ivi_layout_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900548 assert(!ret);
549}
550
551/**
552 * Internal set notification
553 */
554static void
555set_notification_create_surface(struct ivi_layout_surface *ivisurf,
556 void *userdata)
557{
558 struct hmi_controller *hmi_ctrl = userdata;
559 struct ivi_layout_layer *application_layer =
560 hmi_ctrl->application_layer.ivilayer;
561 int32_t ret = 0;
562
563 /* skip ui widgets */
564 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
565 return;
566
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000567 ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900568 assert(!ret);
569}
570
571static void
572set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
573 void *userdata)
574{
575 struct hmi_controller *hmi_ctrl = userdata;
576
577 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
578}
579
580static void
581set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
582 void *userdata)
583{
584 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900585 struct ivi_layout_layer *application_layer =
586 hmi_ctrl->application_layer.ivilayer;
587 struct weston_surface *surface;
588 struct ivi_layout_surface **ivisurfs;
589 int32_t length = 0;
590 int32_t i;
591
592 /* return if the surface is not application content */
593 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
594 return;
595 }
596
597 /*
598 * if application changes size of wl_buffer. The source rectangle shall be
599 * fit to the size.
600 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000601 surface = ivi_layout_interface->surface_get_weston_surface(ivisurf);
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900602 if (surface) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000603 ivi_layout_interface->surface_set_source_rectangle(
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900604 ivisurf, 0, 0, surface->width,
605 surface->height);
606 }
607
608 /*
609 * search if the surface is already added to layer.
610 * If not yet, it is newly invoded application to go to switch_mode.
611 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000612 ivi_layout_interface->get_surfaces_on_layer(application_layer,
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900613 &length, &ivisurfs);
614 for (i = 0; i < length; i++) {
615 if (ivisurf == ivisurfs[i]) {
Michael Vetter2a18a522015-05-15 17:17:47 +0200616 /*
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900617 * if it is non new invoked application, just call
618 * commit_changes to apply source_rectangle.
619 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000620 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900621 return;
622 }
623 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900624
625 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
626}
627
628/**
629 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
630 * corresponding ivi_layer are defined in weston.ini. Default scene graph
631 * of ivi_layers are initialized in hmi_controller_create
632 */
633static struct hmi_server_setting *
634hmi_server_setting_create(struct weston_compositor *ec)
635{
636 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
637 struct weston_config *config = ec->config;
638 struct weston_config_section *shell_section = NULL;
639
640 shell_section = weston_config_get_section(config, "ivi-shell",
641 NULL, NULL);
642
643 weston_config_section_get_uint(shell_section, "base-layer-id",
644 &setting->base_layer_id, 1000);
645
646 weston_config_section_get_uint(shell_section,
647 "workspace-background-layer-id",
648 &setting->workspace_background_layer_id,
649 2000);
650
651 weston_config_section_get_uint(shell_section, "workspace-layer-id",
652 &setting->workspace_layer_id, 3000);
653
654 weston_config_section_get_uint(shell_section, "application-layer-id",
655 &setting->application_layer_id, 4000);
656
657 weston_config_section_get_uint(shell_section, "transition-duration",
658 &setting->transition_duration, 300);
659
660 setting->panel_height = 70;
661
662 weston_config_section_get_string(shell_section,
663 "ivi-shell-user-interface",
664 &setting->ivi_homescreen, NULL);
665
666 return setting;
667}
668
669static void
670hmi_controller_destroy(struct wl_listener *listener, void *data)
671{
672 struct link_layer *link = NULL;
673 struct link_layer *next = NULL;
674 struct hmi_controller *hmi_ctrl =
675 container_of(listener, struct hmi_controller, destroy_listener);
676
677 wl_list_for_each_safe(link, next,
678 &hmi_ctrl->workspace_fade.layer_list, link) {
679 wl_list_remove(&link->link);
680 free(link);
681 }
682
683 wl_array_release(&hmi_ctrl->ui_widgets);
684 free(hmi_ctrl->hmi_setting);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900685 free(hmi_ctrl->pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900686 free(hmi_ctrl);
687}
688
689/**
690 * This is a starting method called from module_init.
691 * This sets up scene graph of ivi_layers; base, application, workspace
692 * background, and workspace. These ivi_layers are created/added to
693 * ivi_screen in create_layer
694 *
695 * base: to group ivi_surfaces of panel and background
696 * application: to group ivi_surfaces of ivi_applications
697 * workspace background: to group a ivi_surface of background in workspace
698 * workspace: to group ivi_surfaces for launching ivi_applications
699 *
700 * ivi_layers of workspace background and workspace is set to invisible at
701 * first. The properties of it is updated with animation when
702 * ivi_hmi_controller_home is requested.
703 */
704static struct hmi_controller *
705hmi_controller_create(struct weston_compositor *ec)
706{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900707 struct ivi_layout_screen *iviscrn = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900708 int32_t screen_width = 0;
709 int32_t screen_height = 0;
710 struct link_layer *tmp_link_layer = NULL;
711 int32_t panel_height = 0;
712 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
713
714 wl_array_init(&hmi_ctrl->ui_widgets);
715 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
716 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
717 hmi_ctrl->compositor = ec;
718
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900719 /* TODO: shall support hotplug of screens */
720 if (get_screens(hmi_ctrl) < 0) {
721 weston_log("ivi-shell: Failed to get screens\n");
722 hmi_ctrl = NULL;
723 return hmi_ctrl;
724 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900725
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900726 iviscrn = get_screen(0, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000727 ivi_layout_interface->get_screen_resolution(iviscrn, &screen_width,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900728 &screen_height);
729
730 /* init base ivi_layer*/
731 hmi_ctrl->base_layer.x = 0;
732 hmi_ctrl->base_layer.y = 0;
733 hmi_ctrl->base_layer.width = screen_width;
734 hmi_ctrl->base_layer.height = screen_height;
735 hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
736
737 create_layer(iviscrn, &hmi_ctrl->base_layer);
738
739 panel_height = hmi_ctrl->hmi_setting->panel_height;
740
741 /* init application ivi_layer */
742 hmi_ctrl->application_layer.x = 0;
743 hmi_ctrl->application_layer.y = 0;
744 hmi_ctrl->application_layer.width = screen_width;
745 hmi_ctrl->application_layer.height = screen_height - panel_height;
746 hmi_ctrl->application_layer.id_layer =
747 hmi_ctrl->hmi_setting->application_layer_id;
748
749 create_layer(iviscrn, &hmi_ctrl->application_layer);
750
751 /* init workspace background ivi_layer */
752 hmi_ctrl->workspace_background_layer.x = 0;
753 hmi_ctrl->workspace_background_layer.y = 0;
754 hmi_ctrl->workspace_background_layer.width = screen_width;
755 hmi_ctrl->workspace_background_layer.height =
756 screen_height - panel_height;
757
758 hmi_ctrl->workspace_background_layer.id_layer =
759 hmi_ctrl->hmi_setting->workspace_background_layer_id;
760
761 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000762 ivi_layout_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900763 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000764 ivi_layout_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900765 hmi_ctrl->workspace_background_layer.ivilayer, false);
766
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900767
768 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
769 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900770 tmp_link_layer->layout_layer =
771 hmi_ctrl->workspace_background_layer.ivilayer;
772 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
773 &tmp_link_layer->link);
774
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000775 ivi_layout_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900776 set_notification_create_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000777 ivi_layout_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900778 set_notification_remove_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000779 ivi_layout_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900780 set_notification_configure_surface, hmi_ctrl);
781
782 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
783 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
784 &hmi_ctrl->destroy_listener);
785
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900786 return hmi_ctrl;
787}
788
789/**
790 * Implementations of ivi-hmi-controller.xml
791 */
792
793/**
794 * A ivi_surface drawing background is identified by id_surface.
795 * Properties of the ivi_surface is set by using ivi_layout APIs according to
796 * the scene graph of UI defined in hmi_controller_create.
797 *
798 * UI ivi_layer is used to add this ivi_surface.
799 */
800static void
801ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
802 uint32_t id_surface)
803{
804 struct ivi_layout_surface *ivisurf = NULL;
805 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
806 const int32_t dstx = hmi_ctrl->application_layer.x;
807 const int32_t dsty = hmi_ctrl->application_layer.y;
808 const int32_t width = hmi_ctrl->application_layer.width;
809 const int32_t height = hmi_ctrl->application_layer.height;
810 int32_t ret = 0;
811
812 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
813 sizeof(*add_surface_id));
814 *add_surface_id = id_surface;
815
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000816 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900817 assert(ivisurf != NULL);
818
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000819 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900820 assert(!ret);
821
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000822 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900823 dstx, dsty, width, height);
824 assert(!ret);
825
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000826 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900827 assert(!ret);
828}
829
830/**
831 * A ivi_surface drawing panel is identified by id_surface.
832 * Properties of the ivi_surface is set by using ivi_layout APIs according to
833 * the scene graph of UI defined in hmi_controller_create.
834 *
835 * UI ivi_layer is used to add this ivi_surface.
836 */
837static void
838ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
839 uint32_t id_surface)
840{
841 struct ivi_layout_surface *ivisurf = NULL;
842 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
843 const int32_t width = hmi_ctrl->base_layer.width;
844 int32_t ret = 0;
845 int32_t panel_height = 0;
846 const int32_t dstx = 0;
847 int32_t dsty = 0;
848
849 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
850 sizeof(*add_surface_id));
851 *add_surface_id = id_surface;
852
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000853 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900854 assert(ivisurf != NULL);
855
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000856 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900857 assert(!ret);
858
859 panel_height = hmi_ctrl->hmi_setting->panel_height;
860
861 dsty = hmi_ctrl->base_layer.height - panel_height;
862
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000863 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900864 ivisurf, dstx, dsty, width, panel_height);
865 assert(!ret);
866
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000867 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900868 assert(!ret);
869}
870
871/**
872 * A ivi_surface drawing buttons in panel is identified by id_surface.
873 * It can set several buttons. Properties of the ivi_surface is set by
874 * using ivi_layout APIs according to the scene graph of UI defined in
875 * hmi_controller_create. Additionally, the position of it is shifted to
876 * right when new one is requested.
877 *
878 * UI ivi_layer is used to add these ivi_surfaces.
879 */
880static void
881ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
882 uint32_t id_surface, int32_t number)
883{
884 struct ivi_layout_surface *ivisurf = NULL;
885 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
886 const int32_t width = 48;
887 const int32_t height = 48;
888 int32_t ret = 0;
889 int32_t panel_height = 0;
890 int32_t dstx = 0;
891 int32_t dsty = 0;
892 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
893 sizeof(*add_surface_id));
894 *add_surface_id = id_surface;
895
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000896 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900897 assert(ivisurf != NULL);
898
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000899 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900900 assert(!ret);
901
902 panel_height = hmi_ctrl->hmi_setting->panel_height;
903
904 dstx = (60 * number) + 15;
905 dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
906
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000907 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900908 ivisurf,dstx, dsty, width, height);
909 assert(!ret);
910
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000911 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900912 assert(!ret);
913}
914
915/**
916 * A ivi_surface drawing home button in panel is identified by id_surface.
917 * Properties of the ivi_surface is set by using ivi_layout APIs according to
918 * the scene graph of UI defined in hmi_controller_create.
919 *
920 * UI ivi_layer is used to add these ivi_surfaces.
921 */
922static void
923ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
924 uint32_t id_surface)
925{
926 struct ivi_layout_surface *ivisurf = NULL;
927 struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
928 int32_t ret = 0;
929 int32_t size = 48;
930 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
931 const int32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
932 const int32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
933
934 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
935 sizeof(*add_surface_id));
936 *add_surface_id = id_surface;
937
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000938 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900939 assert(ivisurf != NULL);
940
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000941 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900942 assert(!ret);
943
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000944 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900945 ivisurf, dstx, dsty, size, size);
946 assert(!ret);
947
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000948 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900949 assert(!ret);
950}
951
952/**
953 * A ivi_surface drawing background of workspace is identified by id_surface.
954 * Properties of the ivi_surface is set by using ivi_layout APIs according to
955 * the scene graph of UI defined in hmi_controller_create.
956 *
957 * A ivi_layer of workspace_background is used to add this ivi_surface.
958 */
959static void
960ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
961 uint32_t id_surface)
962{
963 struct ivi_layout_surface *ivisurf = NULL;
964 struct ivi_layout_layer *ivilayer = NULL;
965 const int32_t width = hmi_ctrl->workspace_background_layer.width;
966 const int32_t height = hmi_ctrl->workspace_background_layer.height;
967 int32_t ret = 0;
968
969 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
970 sizeof(*add_surface_id));
971 *add_surface_id = id_surface;
972 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
973
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000974 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900975 assert(ivisurf != NULL);
976
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000977 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900978 assert(!ret);
979
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000980 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900981 0, 0, width, height);
982 assert(!ret);
983
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000984 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900985 assert(!ret);
986}
987
988/**
989 * A list of ivi_surfaces drawing launchers in workspace is identified by
990 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
991 * APIs according to the scene graph of UI defined in hmi_controller_create.
992 *
993 * The workspace can have several pages to group ivi_surfaces of launcher.
994 * Each call of this interface increments a number of page to add a group
995 * of ivi_surfaces
996 */
997static void
998ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
999 int32_t icon_size)
1000{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001001 int32_t minspace_x = 10;
1002 int32_t minspace_y = minspace_x;
1003
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001004 int32_t width = hmi_ctrl->workspace_background_layer.width;
1005 int32_t height = hmi_ctrl->workspace_background_layer.height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001006
1007 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
1008 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
1009 float fcell_size_x = icon_size + space_x;
1010
1011 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
1012 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
1013 float fcell_size_y = icon_size + space_y;
1014
1015 struct weston_config *config = NULL;
1016 struct weston_config_section *section = NULL;
1017 const char *name = NULL;
1018 int launcher_count = 0;
1019 struct wl_array launchers;
1020 int32_t nx = 0;
1021 int32_t ny = 0;
1022 int32_t prev = -1;
1023 struct launcher_info *data = NULL;
1024
1025 uint32_t surfaceid = 0;
1026 uint32_t workspaceid = 0;
1027 struct launcher_info *info = NULL;
1028
1029 int32_t x = 0;
1030 int32_t y = 0;
1031 int32_t ret = 0;
1032 struct ivi_layout_surface* layout_surface = NULL;
1033 uint32_t *add_surface_id = NULL;
1034
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001035 struct ivi_layout_screen *iviscrn = NULL;
1036 struct link_layer *tmp_link_layer = NULL;
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001037
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001038 if (0 == x_count)
1039 x_count = 1;
1040
1041 if (0 == y_count)
1042 y_count = 1;
1043
1044 config = hmi_ctrl->compositor->config;
1045 if (!config)
1046 return;
1047
1048 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1049 if (!section)
1050 return;
1051
1052 wl_array_init(&launchers);
1053
1054 while (weston_config_next_section(config, &section, &name)) {
1055 surfaceid = 0;
1056 workspaceid = 0;
1057 info = NULL;
1058 if (0 != strcmp(name, "ivi-launcher"))
1059 continue;
1060
1061 if (0 != weston_config_section_get_uint(section, "icon-id",
1062 &surfaceid, 0))
1063 continue;
1064
1065 if (0 != weston_config_section_get_uint(section,
1066 "workspace-id",
1067 &workspaceid, 0))
1068 continue;
1069
1070 info = wl_array_add(&launchers, sizeof(*info));
1071
1072 if (info) {
1073 info->surface_id = surfaceid;
1074 info->workspace_id = workspaceid;
1075 info->index = launcher_count;
1076 ++launcher_count;
1077 }
1078 }
1079
1080 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1081 compare_launcher_info);
1082
1083 wl_array_for_each(data, &launchers) {
1084 x = 0;
1085 y = 0;
1086 ret = 0;
1087 layout_surface = NULL;
1088 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1089 sizeof(*add_surface_id));
1090
1091 *add_surface_id = data->surface_id;
1092
1093 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1094 nx = 0;
1095 ny = 0;
1096 prev = data->workspace_id;
1097
1098 if (0 <= prev)
1099 hmi_ctrl->workspace_count++;
1100 }
1101
1102 if (y_count == ny) {
1103 ny = 0;
1104 hmi_ctrl->workspace_count++;
1105 }
1106
1107 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1108 y = ny * fcell_size_y + space_y;
1109
1110 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001111 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001112 assert(layout_surface);
1113
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001114 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001115 layout_surface, x, y, icon_size, icon_size);
1116 assert(!ret);
1117
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001118 nx++;
1119
1120 if (x_count == nx) {
1121 ny++;
1122 nx = 0;
1123 }
1124 }
1125
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001126 /* init workspace ivi_layer */
1127 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1128 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1129 hmi_ctrl->workspace_layer.width =
1130 hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1131 hmi_ctrl->workspace_layer.height =
1132 hmi_ctrl->workspace_background_layer.height;
1133 hmi_ctrl->workspace_layer.id_layer =
1134 hmi_ctrl->hmi_setting->workspace_layer_id;
1135
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001136 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001137 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001138 ivi_layout_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1139 ivi_layout_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001140 false);
1141
1142 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1143 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1144 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1145 &tmp_link_layer->link);
1146
1147 /* Add surface to layer */
1148 wl_array_for_each(data, &launchers) {
1149 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001150 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001151 assert(layout_surface);
1152
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001153 ret = ivi_layout_interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001154 layout_surface);
1155 assert(!ret);
1156
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001157 ret = ivi_layout_interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001158 assert(!ret);
1159 }
1160
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001161 wl_array_release(&launchers);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001162 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001163}
1164
1165static void
1166ivi_hmi_controller_UI_ready(struct wl_client *client,
1167 struct wl_resource *resource)
1168{
1169 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1170
1171 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1172 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1173 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1174 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1175 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1176 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1177 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1178 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001179 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001180
1181 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1182 hmi_ctrl->is_initialized = 1;
1183}
1184
1185/**
1186 * Implementation of request and event of ivi_hmi_controller_workspace_control
1187 * and controlling workspace.
1188 *
1189 * When motion of input is detected in a ivi_surface of workspace background,
1190 * ivi_hmi_controller_workspace_control shall be invoked and to start
1191 * controlling of workspace. The workspace has several pages to show several
1192 * groups of applications.
1193 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1194 * according to motion. When motion finished, e.g. touch up detected, control is
1195 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1196 */
1197struct pointer_grab {
1198 struct weston_pointer_grab grab;
1199 struct ivi_layout_layer *layer;
1200 struct wl_resource *resource;
1201};
1202
1203struct touch_grab {
1204 struct weston_touch_grab grab;
1205 struct ivi_layout_layer *layer;
1206 struct wl_resource *resource;
1207};
1208
1209struct move_grab {
1210 wl_fixed_t dst[2];
1211 wl_fixed_t rgn[2][2];
1212 double v[2];
1213 struct timespec start_time;
1214 struct timespec pre_time;
1215 wl_fixed_t start_pos[2];
1216 wl_fixed_t pos[2];
1217 int32_t is_moved;
1218};
1219
1220struct pointer_move_grab {
1221 struct pointer_grab base;
1222 struct move_grab move;
1223};
1224
1225struct touch_move_grab {
1226 struct touch_grab base;
1227 struct move_grab move;
1228 int32_t is_active;
1229};
1230
1231static void
1232pointer_grab_start(struct pointer_grab *grab,
1233 struct ivi_layout_layer *layer,
1234 const struct weston_pointer_grab_interface *interface,
1235 struct weston_pointer *pointer)
1236{
1237 grab->grab.interface = interface;
1238 grab->layer = layer;
1239 weston_pointer_start_grab(pointer, &grab->grab);
1240}
1241
1242static void
1243touch_grab_start(struct touch_grab *grab,
1244 struct ivi_layout_layer *layer,
1245 const struct weston_touch_grab_interface *interface,
1246 struct weston_touch* touch)
1247{
1248 grab->grab.interface = interface;
1249 grab->layer = layer;
1250 weston_touch_start_grab(touch, &grab->grab);
1251}
1252
1253static int32_t
1254clamp(int32_t val, int32_t min, int32_t max)
1255{
1256 if (val < min)
1257 return min;
1258
1259 if (max < val)
1260 return max;
1261
1262 return val;
1263}
1264
1265static void
1266move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1267 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1268{
1269 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1270 int32_t width = hmi_ctrl->workspace_background_layer.width;
1271
1272 struct timespec time = {0};
1273 double grab_time = 0.0;
1274 double from_motion_time = 0.0;
1275 double pointer_v = 0.0;
1276 int32_t is_flick = 0;
1277 int32_t pos_x = 0;
1278 int32_t pos_y = 0;
1279 int page_no = 0;
1280 double end_pos = 0.0;
1281 uint32_t duration = 0;
1282
1283 clock_gettime(CLOCK_MONOTONIC, &time);
1284
1285 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1286 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1287
1288 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1289 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1290
1291 pointer_v = move->v[0];
1292
1293 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1294 if (200 < from_motion_time)
1295 pointer_v = 0.0;
1296
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001297 ivi_layout_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001298
1299
1300 if (is_flick) {
1301 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1302 page_no = (-orgx + width / 2) / width;
1303
1304 if (pointer_v < 0.0)
1305 page_no++;
1306 else
1307 page_no--;
1308 } else {
1309 page_no = (-pos_x + width / 2) / width;
1310 }
1311
1312 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1313 end_pos = -page_no * width;
1314
1315 duration = hmi_ctrl->hmi_setting->transition_duration;
1316 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001317 ivi_layout_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001318 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1319 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001320 ivi_layout_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001321 end_pos, pos_y,
Nobuhiko Tanibata4412cd12015-08-24 09:12:37 +09001322 hmi_ctrl->workspace_layer.width,
1323 hmi_ctrl->workspace_layer.height);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001324 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001325}
1326
1327static void
1328pointer_move_workspace_grab_end(struct pointer_grab *grab)
1329{
1330 struct pointer_move_grab *pnt_move_grab =
1331 (struct pointer_move_grab *)grab;
1332 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1333
1334 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1335 grab->grab.pointer->grab_x, layer);
1336
1337 weston_pointer_end_grab(grab->grab.pointer);
1338}
1339
1340static void
1341touch_move_workspace_grab_end(struct touch_grab *grab)
1342{
1343 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1344 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1345
1346 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1347 grab->grab.touch->grab_x, layer);
1348
1349 weston_touch_end_grab(grab->grab.touch);
1350}
1351
1352static void
1353pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1354{
1355}
1356
1357static void
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001358pointer_default_grab_axis(struct weston_pointer_grab *grab,
1359 uint32_t time, uint32_t axis, wl_fixed_t value)
1360{
1361 weston_pointer_send_axis(grab->pointer, time, axis, value);
1362}
1363
1364static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001365move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1366{
1367 struct timespec timestamp = {0};
1368 int32_t ii = 0;
1369 double dt = 0.0;
1370
1371 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1372 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1373 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1374
1375 if (dt < 1e-6)
1376 dt = 1e-6;
1377
1378 move->pre_time = timestamp;
1379
1380 for (ii = 0; ii < 2; ii++) {
1381 wl_fixed_t prepos = move->pos[ii];
1382 move->pos[ii] = pointer[ii] + move->dst[ii];
1383
1384 if (move->pos[ii] < move->rgn[0][ii]) {
1385 move->pos[ii] = move->rgn[0][ii];
1386 move->dst[ii] = move->pos[ii] - pointer[ii];
1387 } else if (move->rgn[1][ii] < move->pos[ii]) {
1388 move->pos[ii] = move->rgn[1][ii];
1389 move->dst[ii] = move->pos[ii] - pointer[ii];
1390 }
1391
1392 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1393
1394 if (!move->is_moved &&
1395 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1396 move->is_moved = 1;
1397 }
1398}
1399
1400static void
1401layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1402 wl_fixed_t pos_y)
1403{
1404 int32_t layout_pos_x = 0;
1405 int32_t layout_pos_y = 0;
1406
1407 layout_pos_x = wl_fixed_to_int(pos_x);
1408 layout_pos_y = wl_fixed_to_int(pos_y);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001409 ivi_layout_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1410 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001411}
1412
1413static void
1414pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001415 struct weston_pointer_motion_event *event)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001416{
1417 struct pointer_move_grab *pnt_move_grab =
1418 (struct pointer_move_grab *)grab;
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001419 wl_fixed_t pointer_pos[2];
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001420
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001421 weston_pointer_motion_to_abs(grab->pointer, event,
1422 &pointer_pos[0], &pointer_pos[1]);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001423 move_grab_update(&pnt_move_grab->move, pointer_pos);
1424 layer_set_pos(pnt_move_grab->base.layer,
1425 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001426 weston_pointer_move(pnt_move_grab->base.grab.pointer, event);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001427}
1428
1429static void
1430touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1431 int touch_id, wl_fixed_t x, wl_fixed_t y)
1432{
1433 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1434
1435 if (!tch_move_grab->is_active)
1436 return;
1437
1438 wl_fixed_t pointer_pos[2] = {
1439 grab->touch->grab_x,
1440 grab->touch->grab_y
1441 };
1442
1443 move_grab_update(&tch_move_grab->move, pointer_pos);
1444 layer_set_pos(tch_move_grab->base.layer,
1445 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1446}
1447
1448static void
1449pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1450 uint32_t time, uint32_t button,
1451 uint32_t state_w)
1452{
1453 if (BTN_LEFT == button &&
1454 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1455 struct pointer_grab *pg = (struct pointer_grab *)grab;
1456
1457 pointer_move_workspace_grab_end(pg);
1458 free(grab);
1459 }
1460}
1461
1462static void
1463touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1464 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1465{
1466}
1467
1468static void
1469touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1470 int touch_id)
1471{
1472 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1473
1474 if (0 == touch_id)
1475 tch_move_grab->is_active = 0;
1476
1477 if (0 == grab->touch->num_tp) {
1478 touch_move_workspace_grab_end(&tch_move_grab->base);
1479 free(grab);
1480 }
1481}
1482
1483static void
1484pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1485{
1486 struct pointer_grab *pg = (struct pointer_grab *)grab;
1487
1488 pointer_move_workspace_grab_end(pg);
1489 free(grab);
1490}
1491
1492static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001493touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1494{
1495}
1496
1497static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001498touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1499{
1500 struct touch_grab *tg = (struct touch_grab *)grab;
1501
1502 touch_move_workspace_grab_end(tg);
1503 free(grab);
1504}
1505
1506static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1507 pointer_noop_grab_focus,
1508 pointer_move_grab_motion,
1509 pointer_move_workspace_grab_button,
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001510 pointer_default_grab_axis,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001511 pointer_move_workspace_grab_cancel
1512};
1513
1514static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1515 touch_nope_grab_down,
1516 touch_move_workspace_grab_up,
1517 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001518 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001519 touch_move_workspace_grab_cancel
1520};
1521
1522enum HMI_GRAB_DEVICE {
1523 HMI_GRAB_DEVICE_NONE,
1524 HMI_GRAB_DEVICE_POINTER,
1525 HMI_GRAB_DEVICE_TOUCH
1526};
1527
1528static enum HMI_GRAB_DEVICE
1529get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1530{
Derek Foreman1281a362015-07-31 16:55:32 -05001531 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1532 struct weston_touch *touch = weston_seat_get_touch(seat);
1533
1534 if (pointer &&
1535 pointer->focus &&
1536 pointer->button_count &&
1537 pointer->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001538 return HMI_GRAB_DEVICE_POINTER;
1539
Derek Foreman1281a362015-07-31 16:55:32 -05001540 if (touch &&
1541 touch->focus &&
1542 touch->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001543 return HMI_GRAB_DEVICE_TOUCH;
1544
1545 return HMI_GRAB_DEVICE_NONE;
1546}
1547
1548static void
1549move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1550 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1551 struct wl_resource* resource)
1552{
1553 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1554 move->pre_time = move->start_time;
1555 move->pos[0] = start_pos[0];
1556 move->pos[1] = start_pos[1];
1557 move->start_pos[0] = start_pos[0];
1558 move->start_pos[1] = start_pos[1];
1559 move->dst[0] = start_pos[0] - grab_pos[0];
1560 move->dst[1] = start_pos[1] - grab_pos[1];
1561 memcpy(move->rgn, rgn, sizeof(move->rgn));
1562}
1563
1564static void
1565move_grab_init_workspace(struct move_grab* move,
1566 wl_fixed_t grab_x, wl_fixed_t grab_y,
1567 struct wl_resource *resource)
1568{
1569 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1570 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1571 int32_t workspace_count = hmi_ctrl->workspace_count;
1572 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1573 int32_t layer_pos_x = 0;
1574 int32_t layer_pos_y = 0;
1575 wl_fixed_t start_pos[2] = {0};
1576 wl_fixed_t rgn[2][2] = {{0}};
1577 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1578
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001579 ivi_layout_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001580
1581 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1582 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1583
1584 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1585
1586 rgn[0][1] = wl_fixed_from_int(0);
1587 rgn[1][0] = wl_fixed_from_int(0);
1588 rgn[1][1] = wl_fixed_from_int(0);
1589
1590 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1591}
1592
1593static struct pointer_move_grab *
1594create_workspace_pointer_move(struct weston_pointer *pointer,
1595 struct wl_resource* resource)
1596{
1597 struct pointer_move_grab *pnt_move_grab =
1598 MEM_ALLOC(sizeof(*pnt_move_grab));
1599
1600 pnt_move_grab->base.resource = resource;
1601 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1602 pointer->grab_y, resource);
1603
1604 return pnt_move_grab;
1605}
1606
1607static struct touch_move_grab *
1608create_workspace_touch_move(struct weston_touch *touch,
1609 struct wl_resource* resource)
1610{
1611 struct touch_move_grab *tch_move_grab =
1612 MEM_ALLOC(sizeof(*tch_move_grab));
1613
1614 tch_move_grab->base.resource = resource;
1615 tch_move_grab->is_active = 1;
1616 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1617 touch->grab_y, resource);
1618
1619 return tch_move_grab;
1620}
1621
1622static void
1623ivi_hmi_controller_workspace_control(struct wl_client *client,
1624 struct wl_resource *resource,
1625 struct wl_resource *seat_resource,
1626 uint32_t serial)
1627{
1628 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1629 struct ivi_layout_layer *layer = NULL;
1630 struct pointer_move_grab *pnt_move_grab = NULL;
1631 struct touch_move_grab *tch_move_grab = NULL;
1632 struct weston_seat *seat = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001633 struct weston_pointer *pointer;
1634 struct weston_touch *touch;
1635
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001636 enum HMI_GRAB_DEVICE device;
1637
1638 if (hmi_ctrl->workspace_count < 2)
1639 return;
1640
1641 seat = wl_resource_get_user_data(seat_resource);
1642 device = get_hmi_grab_device(seat, serial);
1643
1644 if (HMI_GRAB_DEVICE_POINTER != device &&
1645 HMI_GRAB_DEVICE_TOUCH != device)
1646 return;
1647
1648 layer = hmi_ctrl->workspace_layer.ivilayer;
1649
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001650 ivi_layout_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001651
1652 switch (device) {
1653 case HMI_GRAB_DEVICE_POINTER:
Derek Foreman1281a362015-07-31 16:55:32 -05001654 pointer = weston_seat_get_pointer(seat);
1655 pnt_move_grab = create_workspace_pointer_move(pointer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001656 resource);
1657
1658 pointer_grab_start(&pnt_move_grab->base, layer,
1659 &pointer_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001660 pointer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001661 break;
1662
1663 case HMI_GRAB_DEVICE_TOUCH:
Derek Foreman1281a362015-07-31 16:55:32 -05001664 touch = weston_seat_get_touch(seat);
1665 tch_move_grab = create_workspace_touch_move(touch,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001666 resource);
1667
1668 touch_grab_start(&tch_move_grab->base, layer,
1669 &touch_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001670 touch);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001671 break;
1672
1673 default:
1674 break;
1675 }
1676}
1677
1678/**
1679 * Implementation of switch_mode
1680 */
1681static void
1682ivi_hmi_controller_switch_mode(struct wl_client *client,
1683 struct wl_resource *resource,
1684 uint32_t layout_mode)
1685{
1686 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1687
1688 switch_mode(hmi_ctrl, layout_mode);
1689}
1690
1691/**
1692 * Implementation of on/off displaying workspace and workspace background
1693 * ivi_layers.
1694 */
1695static void
1696ivi_hmi_controller_home(struct wl_client *client,
1697 struct wl_resource *resource,
1698 uint32_t home)
1699{
1700 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1701 uint32_t is_fade_in;
1702
1703 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1704 !hmi_ctrl->workspace_fade.is_fade_in) ||
1705 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1706 hmi_ctrl->workspace_fade.is_fade_in)) {
1707 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1708 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1709 &hmi_ctrl->workspace_fade);
1710 }
1711
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001712 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001713}
1714
1715/**
1716 * binding ivi-hmi-controller implementation
1717 */
1718static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1719 ivi_hmi_controller_UI_ready,
1720 ivi_hmi_controller_workspace_control,
1721 ivi_hmi_controller_switch_mode,
1722 ivi_hmi_controller_home
1723};
1724
1725static void
1726unbind_hmi_controller(struct wl_resource *resource)
1727{
1728}
1729
1730static void
1731bind_hmi_controller(struct wl_client *client,
1732 void *data, uint32_t version, uint32_t id)
1733{
1734 struct wl_resource *resource = NULL;
1735 struct hmi_controller *hmi_ctrl = data;
1736
1737 if (hmi_ctrl->user_interface != client) {
1738 struct wl_resource *res = wl_client_get_object(client, 1);
1739 wl_resource_post_error(res,
1740 WL_DISPLAY_ERROR_INVALID_OBJECT,
1741 "hmi-controller failed: permission denied");
1742 return;
1743 }
1744
1745 resource = wl_resource_create(
1746 client, &ivi_hmi_controller_interface, 1, id);
1747
1748 wl_resource_set_implementation(
1749 resource, &ivi_hmi_controller_implementation,
1750 hmi_ctrl, unbind_hmi_controller);
1751}
1752
1753static int32_t
1754initialize(struct hmi_controller *hmi_ctrl)
1755{
1756 struct config_command {
1757 char *key;
1758 uint32_t *dest;
1759 };
1760
1761 struct weston_config *config = hmi_ctrl->compositor->config;
1762 struct weston_config_section *section = NULL;
1763 int result = 0;
1764 int i = 0;
1765
1766 const struct config_command uint_commands[] = {
1767 { "background-id", &hmi_ctrl->ui_setting.background_id },
1768 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1769 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1770 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1771 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1772 { "random-id", &hmi_ctrl->ui_setting.random_id },
1773 { "home-id", &hmi_ctrl->ui_setting.home_id },
1774 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
1775 { NULL, NULL }
1776 };
1777
1778 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1779
1780 for (i = 0; -1 != result; ++i) {
1781 const struct config_command *command = &uint_commands[i];
1782
1783 if (!command->key)
1784 break;
1785
1786 if (weston_config_section_get_uint(
1787 section, command->key, command->dest, 0) != 0)
1788 result = -1;
1789 }
1790
1791 if (-1 == result) {
1792 weston_log("Failed to initialize hmi-controller\n");
1793 return 0;
1794 }
1795
1796 return 1;
1797}
1798
1799static void
1800launch_hmi_client_process(void *data)
1801{
1802 struct hmi_controller *hmi_ctrl =
1803 (struct hmi_controller *)data;
1804
1805 hmi_ctrl->user_interface =
1806 weston_client_start(hmi_ctrl->compositor,
1807 hmi_ctrl->hmi_setting->ivi_homescreen);
1808
1809 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1810}
1811
1812/*****************************************************************************
1813 * exported functions
1814 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001815WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001816controller_module_init(struct weston_compositor *ec,
1817 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001818 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001819 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001820{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001821 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001822 struct wl_event_loop *loop = NULL;
1823
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001824 if (interface_version < sizeof(struct ivi_layout_interface)) {
Chris Michaelc083af92015-10-01 10:51:29 -04001825 weston_log("ivi-shell: version mismatch of controller interface\n");
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001826 return -1;
1827 }
1828
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001829 ivi_layout_interface = interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001830
1831 hmi_ctrl = hmi_controller_create(ec);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001832 if (hmi_ctrl == NULL)
1833 return -1;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001834
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001835 if (!initialize(hmi_ctrl)) {
1836 return -1;
1837 }
1838
1839 if (wl_global_create(ec->wl_display,
1840 &ivi_hmi_controller_interface, 1,
1841 hmi_ctrl, bind_hmi_controller) == NULL) {
1842 return -1;
1843 }
1844
1845 loop = wl_display_get_event_loop(ec->wl_display);
1846 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1847
1848 return 0;
1849}