blob: 4b2084886d45329ea2a146200b20d07e2e2a9c6e [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;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +090075 struct wl_list link;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090076};
77
78struct link_layer {
79 struct ivi_layout_layer *layout_layer;
80 struct wl_list link;
81};
82
83struct hmi_controller_fade {
84 uint32_t is_fade_in;
85 struct wl_list layer_list;
86};
87
88struct hmi_server_setting {
89 uint32_t base_layer_id;
90 uint32_t application_layer_id;
91 uint32_t workspace_background_layer_id;
92 uint32_t workspace_layer_id;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +090093 uint32_t base_layer_id_offset;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +090094 int32_t panel_height;
95 uint32_t transition_duration;
96 char *ivi_homescreen;
97};
98
99struct ui_setting {
100 uint32_t background_id;
101 uint32_t panel_id;
102 uint32_t tiling_id;
103 uint32_t sidebyside_id;
104 uint32_t fullscreen_id;
105 uint32_t random_id;
106 uint32_t home_id;
107 uint32_t workspace_background_id;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900108 uint32_t surface_id_offset;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900109};
110
111struct hmi_controller {
112 struct hmi_server_setting *hmi_setting;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900113 /* List of struct hmi_controller_layer */
114 struct wl_list base_layer_list;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900115 struct wl_list application_layer_list;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900116 struct hmi_controller_layer workspace_background_layer;
117 struct hmi_controller_layer workspace_layer;
118 enum ivi_hmi_controller_layout_mode layout_mode;
119
120 struct hmi_controller_fade workspace_fade;
121
122 int32_t workspace_count;
123 struct wl_array ui_widgets;
124 int32_t is_initialized;
125
126 struct weston_compositor *compositor;
127 struct wl_listener destroy_listener;
128
129 struct wl_client *user_interface;
130 struct ui_setting ui_setting;
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900131
132 int32_t screen_num;
133 struct ivi_layout_screen **pp_screen;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900134};
135
136struct launcher_info {
137 uint32_t surface_id;
138 uint32_t workspace_id;
139 int32_t index;
140};
141
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000142const struct ivi_layout_interface *ivi_layout_interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900143
144int
145controller_module_init(struct weston_compositor *ec,
146 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000147 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900148 size_t interface_version);
149
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900150/*****************************************************************************
151 * local functions
152 ****************************************************************************/
153static void *
154fail_on_null(void *p, size_t size, char *file, int32_t line)
155{
156 if (size && !p) {
157 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
158 exit(EXIT_FAILURE);
159 }
160
161 return p;
162}
163
164static void *
165mem_alloc(size_t size, char *file, int32_t line)
166{
167 return fail_on_null(calloc(1, size), size, file, line);
168}
169
170#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
171
172static int32_t
173is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
174 struct ivi_layout_surface *ivisurf)
175{
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000176 uint32_t id = ivi_layout_interface->get_id_of_surface(ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900177
178 uint32_t *ui_widget_id = NULL;
179 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
180 if (*ui_widget_id == id)
181 return 1;
182 }
183
184 return 0;
185}
186
187static int
188compare_launcher_info(const void *lhs, const void *rhs)
189{
190 const struct launcher_info *left = lhs;
191 const struct launcher_info *right = rhs;
192
193 if (left->workspace_id < right->workspace_id)
194 return -1;
195
196 if (left->workspace_id > right->workspace_id)
197 return 1;
198
199 if (left->index < right->index)
200 return -1;
201
202 if (left->index > right->index)
203 return 1;
204
205 return 0;
206}
207
208/**
209 * Internal methods called by mainly ivi_hmi_controller_switch_mode
210 * This reference shows 4 examples how to use ivi_layout APIs.
211 */
212static void
213mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
214 struct ivi_layout_surface **pp_surface,
215 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900216 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900217{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900218 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900219 const float surface_width = (float)layer->width * 0.25;
220 const float surface_height = (float)layer->height * 0.5;
221 int32_t surface_x = 0;
222 int32_t surface_y = 0;
223 struct ivi_layout_surface *ivisurf = NULL;
224 struct ivi_layout_surface **surfaces;
225 struct ivi_layout_surface **new_order;
226 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
227
228 int32_t i = 0;
229 int32_t surf_num = 0;
230 uint32_t num = 1;
231
232 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
233 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
234
235 for (i = 0; i < surface_length; i++) {
236 ivisurf = pp_surface[i];
237
238 /* skip ui widgets */
239 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
240 continue;
241
242 surfaces[surf_num++] = ivisurf;
243 }
244
245 for (i = 0; i < surf_num; i++) {
246 ivisurf = surfaces[i];
247 new_order[i] = ivisurf;
248
249 if (num <= 8) {
250 if (num < 5) {
251 surface_x = (int32_t)((num - 1) * (surface_width));
252 surface_y = 0;
253 } else {
254 surface_x = (int32_t)((num - 5) * (surface_width));
255 surface_y = (int32_t)surface_height;
256 }
257
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000258 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900259 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
260 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000261 ivi_layout_interface->surface_set_visibility(ivisurf, true);
262 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900263 surface_x, surface_y,
264 (int32_t)surface_width,
265 (int32_t)surface_height);
266
267 num++;
268 continue;
269 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000270 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900271 }
272
273 if (surf_num > 0) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000274 ivi_layout_interface->layer_set_transition(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900275 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
276 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900277 }
278
279 free(surfaces);
280 free(new_order);
281}
282
283static void
284mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
285 struct ivi_layout_surface **pp_surface,
286 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900287 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900288{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900289 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900290 int32_t surface_width = layer->width / 2;
291 int32_t surface_height = layer->height;
292 struct ivi_layout_surface *ivisurf = NULL;
293
294 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
295 int32_t i = 0;
296 int32_t num = 1;
297
298 for (i = 0; i < surface_length; i++) {
299 ivisurf = pp_surface[i];
300
301 /* skip ui widgets */
302 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
303 continue;
304
305 if (num == 1) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000306 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900307 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
308 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000309 ivi_layout_interface->surface_set_visibility(ivisurf, true);
310 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900311 0, 0,
312 surface_width,
313 surface_height);
314
315 num++;
316 continue;
317 } else if (num == 2) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000318 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900319 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
320 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000321 ivi_layout_interface->surface_set_visibility(ivisurf, true);
322 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900323 surface_width, 0,
324 surface_width,
325 surface_height);
326
327 num++;
328 continue;
329 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000330 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900331 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
332 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000333 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900334 }
335}
336
337static void
338mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
339 struct ivi_layout_surface **pp_surface,
340 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900341 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900342{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900343 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900344 const int32_t surface_width = layer->width;
345 const int32_t surface_height = layer->height;
346 struct ivi_layout_surface *ivisurf = NULL;
347 int32_t i = 0;
348 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
349
350 for (i = 0; i < surface_length; i++) {
351 ivisurf = pp_surface[i];
352
353 /* skip ui widgets */
354 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
355 continue;
356
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000357 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900358 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
359 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000360 ivi_layout_interface->surface_set_visibility(ivisurf, true);
361 ivi_layout_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900362 surface_width,
363 surface_height);
364 }
365}
366
367static void
368mode_random_replace(struct hmi_controller *hmi_ctrl,
369 struct ivi_layout_surface **pp_surface,
370 int32_t surface_length,
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900371 struct wl_list *layer_list)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900372{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900373 struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900374 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
375 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
376 int32_t surface_x = 0;
377 int32_t surface_y = 0;
378 struct ivi_layout_surface *ivisurf = NULL;
379 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
380 int32_t i = 0;
381
382 for (i = 0; i < surface_length; i++) {
383 ivisurf = pp_surface[i];
384
385 /* skip ui widgets */
386 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
387 continue;
388
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000389 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900390 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
391 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000392 ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900393 surface_x = rand() % (layer->width - surface_width);
394 surface_y = rand() % (layer->height - surface_height);
395
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000396 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900397 surface_x,
398 surface_y,
399 surface_width,
400 surface_height);
401 }
402}
403
404static int32_t
405has_application_surface(struct hmi_controller *hmi_ctrl,
406 struct ivi_layout_surface **pp_surface,
407 int32_t surface_length)
408{
409 struct ivi_layout_surface *ivisurf = NULL;
410 int32_t i = 0;
411
412 for (i = 0; i < surface_length; i++) {
413 ivisurf = pp_surface[i];
414
415 /* skip ui widgets */
416 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
417 continue;
418
419 return 1;
420 }
421
422 return 0;
423}
424
425/**
426 * Supports 4 example to layout of application ivi_surfaces;
427 * tiling, side by side, fullscreen, and random.
428 */
429static void
430switch_mode(struct hmi_controller *hmi_ctrl,
431 enum ivi_hmi_controller_layout_mode layout_mode)
432{
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900433 struct wl_list *layer = &hmi_ctrl->application_layer_list;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900434 struct ivi_layout_surface **pp_surface = NULL;
435 int32_t surface_length = 0;
436 int32_t ret = 0;
437
438 if (!hmi_ctrl->is_initialized)
439 return;
440
441 hmi_ctrl->layout_mode = layout_mode;
442
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000443 ret = ivi_layout_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900444 assert(!ret);
445
446 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
447 free(pp_surface);
448 pp_surface = NULL;
449 return;
450 }
451
452 switch (layout_mode) {
453 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
454 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
455 layer);
456 break;
457 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
458 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
459 surface_length, layer);
460 break;
461 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
462 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
463 layer);
464 break;
465 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
466 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
467 layer);
468 break;
469 }
470
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000471 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900472 free(pp_surface);
473}
474
475/**
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900476 * Internal method to get screens from weston core
477 * TODO: shall support hotplug of screens
478 */
479static int32_t
480get_screens(struct hmi_controller *hmi_ctrl)
481{
482 hmi_ctrl->pp_screen = NULL;
483 hmi_ctrl->screen_num = 0;
484 ivi_layout_interface->get_screens(&hmi_ctrl->screen_num, &hmi_ctrl->pp_screen);
485
486 if (hmi_ctrl->pp_screen == NULL)
487 return -1;
488 else
489 return 0;
490}
491
492/**
493 * Internal method to get ivi_layout_screen
494 */
495static struct ivi_layout_screen *
496get_screen(int32_t screen_idx, struct hmi_controller *hmi_ctrl)
497{
498 struct ivi_layout_screen *iviscrn = NULL;
499
500 if (screen_idx > hmi_ctrl->screen_num - 1)
501 weston_log("Invalid index. Return NULL\n");
502 else
503 iviscrn = hmi_ctrl->pp_screen[screen_idx];
504
505 return iviscrn;
506}
507
508/**
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900509 * Internal method for transition
510 */
511static void
512hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
513 struct hmi_controller_fade *fade)
514{
515 double tint = is_fade_in ? 1.0 : 0.0;
516 struct link_layer *linklayer = NULL;
517 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
518
519 fade->is_fade_in = is_fade_in;
520
521 wl_list_for_each(linklayer, &fade->layer_list, link) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000522 ivi_layout_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900523 IVI_LAYOUT_TRANSITION_LAYER_FADE,
524 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000525 ivi_layout_interface->layer_set_fade_info(linklayer->layout_layer,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900526 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900527 }
528}
529
530/**
531 * Internal method to create ivi_layer with hmi_controller_layer and
532 * add to a ivi_screen
533 */
534static void
535create_layer(struct ivi_layout_screen *iviscrn,
536 struct hmi_controller_layer *layer)
537{
538 int32_t ret = 0;
539
540 layer->ivilayer =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000541 ivi_layout_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900542 layer->width,
543 layer->height);
544 assert(layer->ivilayer != NULL);
545
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000546 ret = ivi_layout_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900547 assert(!ret);
548
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000549 ret = ivi_layout_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900550 layer->x, layer->y,
551 layer->width,
552 layer->height);
553 assert(!ret);
554
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000555 ret = ivi_layout_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900556 assert(!ret);
557}
558
559/**
560 * Internal set notification
561 */
562static void
563set_notification_create_surface(struct ivi_layout_surface *ivisurf,
564 void *userdata)
565{
566 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900567 struct hmi_controller_layer *layer_link =
568 wl_container_of(hmi_ctrl->application_layer_list.prev,
569 layer_link,
570 link);
571 struct ivi_layout_layer *application_layer = layer_link->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900572 int32_t ret = 0;
573
574 /* skip ui widgets */
575 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
576 return;
577
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000578 ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900579 assert(!ret);
580}
581
582static void
583set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
584 void *userdata)
585{
586 struct hmi_controller *hmi_ctrl = userdata;
587
588 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
589}
590
591static void
592set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
593 void *userdata)
594{
595 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900596 struct hmi_controller_layer *layer_link = NULL;
597 struct ivi_layout_layer *application_layer = NULL;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900598 struct weston_surface *surface;
599 struct ivi_layout_surface **ivisurfs;
600 int32_t length = 0;
601 int32_t i;
602
603 /* return if the surface is not application content */
604 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
605 return;
606 }
607
608 /*
609 * if application changes size of wl_buffer. The source rectangle shall be
610 * fit to the size.
611 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000612 surface = ivi_layout_interface->surface_get_weston_surface(ivisurf);
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900613 if (surface) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000614 ivi_layout_interface->surface_set_source_rectangle(
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900615 ivisurf, 0, 0, surface->width,
616 surface->height);
617 }
618
619 /*
620 * search if the surface is already added to layer.
621 * If not yet, it is newly invoded application to go to switch_mode.
622 */
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900623 wl_list_for_each_reverse(layer_link, &hmi_ctrl->application_layer_list, link) {
624 application_layer = layer_link->ivilayer;
625 ivi_layout_interface->get_surfaces_on_layer(application_layer,
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900626 &length, &ivisurfs);
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900627 for (i = 0; i < length; i++) {
628 if (ivisurf == ivisurfs[i]) {
629 /*
630 * if it is non new invoked application, just call
631 * commit_changes to apply source_rectangle.
632 */
633 ivi_layout_interface->commit_changes();
634 return;
635 }
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900636 }
637 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900638
639 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
640}
641
642/**
643 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
644 * corresponding ivi_layer are defined in weston.ini. Default scene graph
645 * of ivi_layers are initialized in hmi_controller_create
646 */
647static struct hmi_server_setting *
648hmi_server_setting_create(struct weston_compositor *ec)
649{
650 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
651 struct weston_config *config = ec->config;
652 struct weston_config_section *shell_section = NULL;
653
654 shell_section = weston_config_get_section(config, "ivi-shell",
655 NULL, NULL);
656
657 weston_config_section_get_uint(shell_section, "base-layer-id",
658 &setting->base_layer_id, 1000);
659
660 weston_config_section_get_uint(shell_section,
661 "workspace-background-layer-id",
662 &setting->workspace_background_layer_id,
663 2000);
664
665 weston_config_section_get_uint(shell_section, "workspace-layer-id",
666 &setting->workspace_layer_id, 3000);
667
668 weston_config_section_get_uint(shell_section, "application-layer-id",
669 &setting->application_layer_id, 4000);
670
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900671 weston_config_section_get_uint(shell_section, "base-layer-id-offset",
672 &setting->base_layer_id_offset, 10000);
673
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900674 weston_config_section_get_uint(shell_section, "transition-duration",
675 &setting->transition_duration, 300);
676
677 setting->panel_height = 70;
678
679 weston_config_section_get_string(shell_section,
680 "ivi-shell-user-interface",
681 &setting->ivi_homescreen, NULL);
682
683 return setting;
684}
685
686static void
687hmi_controller_destroy(struct wl_listener *listener, void *data)
688{
689 struct link_layer *link = NULL;
690 struct link_layer *next = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900691 struct hmi_controller_layer *ctrl_layer_link = NULL;
692 struct hmi_controller_layer *ctrl_layer_next = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900693 struct hmi_controller *hmi_ctrl =
694 container_of(listener, struct hmi_controller, destroy_listener);
695
696 wl_list_for_each_safe(link, next,
697 &hmi_ctrl->workspace_fade.layer_list, link) {
698 wl_list_remove(&link->link);
699 free(link);
700 }
701
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900702 /* clear base_layer_list */
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900703 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
704 &hmi_ctrl->base_layer_list, link) {
705 wl_list_remove(&ctrl_layer_link->link);
706 free(ctrl_layer_link);
707 }
708
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900709 /* clear application_layer_list */
710 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
711 &hmi_ctrl->application_layer_list, link) {
712 wl_list_remove(&ctrl_layer_link->link);
713 free(ctrl_layer_link);
714 }
715
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900716 wl_array_release(&hmi_ctrl->ui_widgets);
717 free(hmi_ctrl->hmi_setting);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900718 free(hmi_ctrl->pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900719 free(hmi_ctrl);
720}
721
722/**
723 * This is a starting method called from module_init.
724 * This sets up scene graph of ivi_layers; base, application, workspace
725 * background, and workspace. These ivi_layers are created/added to
726 * ivi_screen in create_layer
727 *
728 * base: to group ivi_surfaces of panel and background
729 * application: to group ivi_surfaces of ivi_applications
730 * workspace background: to group a ivi_surface of background in workspace
731 * workspace: to group ivi_surfaces for launching ivi_applications
732 *
733 * ivi_layers of workspace background and workspace is set to invisible at
734 * first. The properties of it is updated with animation when
735 * ivi_hmi_controller_home is requested.
736 */
737static struct hmi_controller *
738hmi_controller_create(struct weston_compositor *ec)
739{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900740 struct ivi_layout_screen *iviscrn = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900741 int32_t screen_width = 0;
742 int32_t screen_height = 0;
743 struct link_layer *tmp_link_layer = NULL;
744 int32_t panel_height = 0;
745 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900746 struct hmi_controller_layer *base_layer = NULL;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900747 struct hmi_controller_layer *application_layer = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900748
749 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900750
751 wl_array_init(&hmi_ctrl->ui_widgets);
752 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
753 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
754 hmi_ctrl->compositor = ec;
755
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900756 /* TODO: shall support hotplug of screens */
757 if (get_screens(hmi_ctrl) < 0) {
758 weston_log("ivi-shell: Failed to get screens\n");
759 hmi_ctrl = NULL;
760 return hmi_ctrl;
761 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900762
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900763 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900764
765 /* init base ivi_layer*/
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900766 wl_list_init(&hmi_ctrl->base_layer_list);
767 for (i = 0; i < hmi_ctrl->screen_num; i++) {
768 ivi_layout_interface->get_screen_resolution(get_screen(i, hmi_ctrl),
769 &screen_width,
770 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900771
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900772 base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
773 base_layer->x = 0;
774 base_layer->y = 0;
775 base_layer->width = screen_width;
776 base_layer->height = screen_height;
777 base_layer->id_layer =
778 hmi_ctrl->hmi_setting->base_layer_id +
779 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
780 wl_list_insert(&hmi_ctrl->base_layer_list, &base_layer->link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900781
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900782 create_layer(get_screen(i, hmi_ctrl), base_layer);
783 }
784
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900785 panel_height = hmi_ctrl->hmi_setting->panel_height;
786
787 /* init application ivi_layer */
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900788 wl_list_init(&hmi_ctrl->application_layer_list);
789 for (i = 0; i < hmi_ctrl->screen_num; i++) {
790 ivi_layout_interface->get_screen_resolution(get_screen(i, hmi_ctrl),
791 &screen_width,
792 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900793
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900794 application_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
795 application_layer->x = 0;
796 application_layer->y = 0;
797 application_layer->width = screen_width;
798 application_layer->height = screen_height - panel_height;
799 application_layer->id_layer =
800 hmi_ctrl->hmi_setting->application_layer_id +
801 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
802 wl_list_insert(&hmi_ctrl->application_layer_list, &application_layer->link);
803
804 create_layer(get_screen(i, hmi_ctrl), application_layer);
805 }
806
807 ivi_layout_interface->get_screen_resolution(iviscrn, &screen_width,
808 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900809
810 /* init workspace background ivi_layer */
811 hmi_ctrl->workspace_background_layer.x = 0;
812 hmi_ctrl->workspace_background_layer.y = 0;
813 hmi_ctrl->workspace_background_layer.width = screen_width;
814 hmi_ctrl->workspace_background_layer.height =
815 screen_height - panel_height;
816
817 hmi_ctrl->workspace_background_layer.id_layer =
818 hmi_ctrl->hmi_setting->workspace_background_layer_id;
819
820 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000821 ivi_layout_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900822 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000823 ivi_layout_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900824 hmi_ctrl->workspace_background_layer.ivilayer, false);
825
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900826
827 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
828 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900829 tmp_link_layer->layout_layer =
830 hmi_ctrl->workspace_background_layer.ivilayer;
831 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
832 &tmp_link_layer->link);
833
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000834 ivi_layout_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900835 set_notification_create_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000836 ivi_layout_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900837 set_notification_remove_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000838 ivi_layout_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900839 set_notification_configure_surface, hmi_ctrl);
840
841 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
842 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
843 &hmi_ctrl->destroy_listener);
844
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900845 return hmi_ctrl;
846}
847
848/**
849 * Implementations of ivi-hmi-controller.xml
850 */
851
852/**
853 * A ivi_surface drawing background is identified by id_surface.
854 * Properties of the ivi_surface is set by using ivi_layout APIs according to
855 * the scene graph of UI defined in hmi_controller_create.
856 *
857 * UI ivi_layer is used to add this ivi_surface.
858 */
859static void
860ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
861 uint32_t id_surface)
862{
863 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900864 struct hmi_controller_layer *base_layer = NULL;
865 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibatad789c662015-12-09 15:42:46 +0900866 struct hmi_controller_layer *application_layer =
867 wl_container_of(hmi_ctrl->application_layer_list.prev,
868 application_layer,
869 link);
870 const int32_t dstx = application_layer->x;
871 const int32_t dsty = application_layer->y;
872 const int32_t width = application_layer->width;
873 const int32_t height = application_layer->height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900874 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900875 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900876
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900877 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
878 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
879 sizeof(*add_surface_id));
880 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900881
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900882 ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900883
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900884 ivisurf = ivi_layout_interface->get_surface_from_id(*add_surface_id);
885 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900886
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900887 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
888 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900889
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900890 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
891 dstx, dsty, width, height);
892 assert(!ret);
893
894 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
895 assert(!ret);
896
897 i++;
898 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900899}
900
901/**
902 * A ivi_surface drawing panel is identified by id_surface.
903 * Properties of the ivi_surface is set by using ivi_layout APIs according to
904 * the scene graph of UI defined in hmi_controller_create.
905 *
906 * UI ivi_layer is used to add this ivi_surface.
907 */
908static void
909ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
910 uint32_t id_surface)
911{
912 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900913 struct hmi_controller_layer *base_layer =
914 wl_container_of(hmi_ctrl->base_layer_list.prev,
915 base_layer,
916 link);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900917 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900918 const int32_t width = base_layer->width;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900919 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900920 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900921 const int32_t dstx = 0;
922 int32_t dsty = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900923 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900924
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900925 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
926 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
927 sizeof(*add_surface_id));
928 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900929
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900930 ivilayer = base_layer->ivilayer;
931 ivisurf = ivi_layout_interface->get_surface_from_id(*add_surface_id);
932 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900933
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900934 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
935 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900936
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900937 dsty = base_layer->height - panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900938
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900939 ret = ivi_layout_interface->surface_set_destination_rectangle(
940 ivisurf, dstx, dsty, width, panel_height);
941 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900942
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900943 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
944 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900945
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900946 i++;
947 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900948}
949
950/**
951 * A ivi_surface drawing buttons in panel is identified by id_surface.
952 * It can set several buttons. Properties of the ivi_surface is set by
953 * using ivi_layout APIs according to the scene graph of UI defined in
954 * hmi_controller_create. Additionally, the position of it is shifted to
955 * right when new one is requested.
956 *
957 * UI ivi_layer is used to add these ivi_surfaces.
958 */
959static void
960ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
961 uint32_t id_surface, int32_t number)
962{
963 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900964 struct hmi_controller_layer *base_layer =
965 wl_container_of(hmi_ctrl->base_layer_list.prev,
966 base_layer,
967 link);
968 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900969 const int32_t width = 48;
970 const int32_t height = 48;
971 int32_t ret = 0;
972 int32_t panel_height = 0;
973 int32_t dstx = 0;
974 int32_t dsty = 0;
975 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
976 sizeof(*add_surface_id));
977 *add_surface_id = id_surface;
978
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000979 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900980 assert(ivisurf != NULL);
981
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000982 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900983 assert(!ret);
984
985 panel_height = hmi_ctrl->hmi_setting->panel_height;
986
987 dstx = (60 * number) + 15;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900988 dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900989
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000990 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900991 ivisurf,dstx, dsty, width, height);
992 assert(!ret);
993
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000994 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900995 assert(!ret);
996}
997
998/**
999 * A ivi_surface drawing home button in panel is identified by id_surface.
1000 * Properties of the ivi_surface is set by using ivi_layout APIs according to
1001 * the scene graph of UI defined in hmi_controller_create.
1002 *
1003 * UI ivi_layer is used to add these ivi_surfaces.
1004 */
1005static void
1006ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
1007 uint32_t id_surface)
1008{
1009 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001010 struct hmi_controller_layer *base_layer =
1011 wl_container_of(hmi_ctrl->base_layer_list.prev,
1012 base_layer,
1013 link);
1014 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001015 int32_t ret = 0;
1016 int32_t size = 48;
1017 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +09001018 const int32_t dstx = (base_layer->width - size) / 2;
1019 const int32_t dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001020
1021 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1022 sizeof(*add_surface_id));
1023 *add_surface_id = id_surface;
1024
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001025 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001026 assert(ivisurf != NULL);
1027
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001028 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001029 assert(!ret);
1030
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001031 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001032 ivisurf, dstx, dsty, size, size);
1033 assert(!ret);
1034
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001035 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001036 assert(!ret);
1037}
1038
1039/**
1040 * A ivi_surface drawing background of workspace is identified by id_surface.
1041 * Properties of the ivi_surface is set by using ivi_layout APIs according to
1042 * the scene graph of UI defined in hmi_controller_create.
1043 *
1044 * A ivi_layer of workspace_background is used to add this ivi_surface.
1045 */
1046static void
1047ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
1048 uint32_t id_surface)
1049{
1050 struct ivi_layout_surface *ivisurf = NULL;
1051 struct ivi_layout_layer *ivilayer = NULL;
1052 const int32_t width = hmi_ctrl->workspace_background_layer.width;
1053 const int32_t height = hmi_ctrl->workspace_background_layer.height;
1054 int32_t ret = 0;
1055
1056 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1057 sizeof(*add_surface_id));
1058 *add_surface_id = id_surface;
1059 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
1060
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001061 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001062 assert(ivisurf != NULL);
1063
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001064 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001065 assert(!ret);
1066
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001067 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001068 0, 0, width, height);
1069 assert(!ret);
1070
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001071 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001072 assert(!ret);
1073}
1074
1075/**
1076 * A list of ivi_surfaces drawing launchers in workspace is identified by
1077 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
1078 * APIs according to the scene graph of UI defined in hmi_controller_create.
1079 *
1080 * The workspace can have several pages to group ivi_surfaces of launcher.
1081 * Each call of this interface increments a number of page to add a group
1082 * of ivi_surfaces
1083 */
1084static void
1085ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
1086 int32_t icon_size)
1087{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001088 int32_t minspace_x = 10;
1089 int32_t minspace_y = minspace_x;
1090
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001091 int32_t width = hmi_ctrl->workspace_background_layer.width;
1092 int32_t height = hmi_ctrl->workspace_background_layer.height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001093
1094 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
1095 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
1096 float fcell_size_x = icon_size + space_x;
1097
1098 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
1099 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
1100 float fcell_size_y = icon_size + space_y;
1101
1102 struct weston_config *config = NULL;
1103 struct weston_config_section *section = NULL;
1104 const char *name = NULL;
1105 int launcher_count = 0;
1106 struct wl_array launchers;
1107 int32_t nx = 0;
1108 int32_t ny = 0;
1109 int32_t prev = -1;
1110 struct launcher_info *data = NULL;
1111
1112 uint32_t surfaceid = 0;
1113 uint32_t workspaceid = 0;
1114 struct launcher_info *info = NULL;
1115
1116 int32_t x = 0;
1117 int32_t y = 0;
1118 int32_t ret = 0;
1119 struct ivi_layout_surface* layout_surface = NULL;
1120 uint32_t *add_surface_id = NULL;
1121
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001122 struct ivi_layout_screen *iviscrn = NULL;
1123 struct link_layer *tmp_link_layer = NULL;
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001124
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001125 if (0 == x_count)
1126 x_count = 1;
1127
1128 if (0 == y_count)
1129 y_count = 1;
1130
1131 config = hmi_ctrl->compositor->config;
1132 if (!config)
1133 return;
1134
1135 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1136 if (!section)
1137 return;
1138
1139 wl_array_init(&launchers);
1140
1141 while (weston_config_next_section(config, &section, &name)) {
1142 surfaceid = 0;
1143 workspaceid = 0;
1144 info = NULL;
1145 if (0 != strcmp(name, "ivi-launcher"))
1146 continue;
1147
1148 if (0 != weston_config_section_get_uint(section, "icon-id",
1149 &surfaceid, 0))
1150 continue;
1151
1152 if (0 != weston_config_section_get_uint(section,
1153 "workspace-id",
1154 &workspaceid, 0))
1155 continue;
1156
1157 info = wl_array_add(&launchers, sizeof(*info));
1158
1159 if (info) {
1160 info->surface_id = surfaceid;
1161 info->workspace_id = workspaceid;
1162 info->index = launcher_count;
1163 ++launcher_count;
1164 }
1165 }
1166
1167 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1168 compare_launcher_info);
1169
1170 wl_array_for_each(data, &launchers) {
1171 x = 0;
1172 y = 0;
1173 ret = 0;
1174 layout_surface = NULL;
1175 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1176 sizeof(*add_surface_id));
1177
1178 *add_surface_id = data->surface_id;
1179
1180 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1181 nx = 0;
1182 ny = 0;
1183 prev = data->workspace_id;
1184
1185 if (0 <= prev)
1186 hmi_ctrl->workspace_count++;
1187 }
1188
1189 if (y_count == ny) {
1190 ny = 0;
1191 hmi_ctrl->workspace_count++;
1192 }
1193
1194 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1195 y = ny * fcell_size_y + space_y;
1196
1197 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001198 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001199 assert(layout_surface);
1200
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001201 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001202 layout_surface, x, y, icon_size, icon_size);
1203 assert(!ret);
1204
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001205 nx++;
1206
1207 if (x_count == nx) {
1208 ny++;
1209 nx = 0;
1210 }
1211 }
1212
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001213 /* init workspace ivi_layer */
1214 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1215 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1216 hmi_ctrl->workspace_layer.width =
1217 hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1218 hmi_ctrl->workspace_layer.height =
1219 hmi_ctrl->workspace_background_layer.height;
1220 hmi_ctrl->workspace_layer.id_layer =
1221 hmi_ctrl->hmi_setting->workspace_layer_id;
1222
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001223 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001224 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001225 ivi_layout_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1226 ivi_layout_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001227 false);
1228
1229 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1230 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1231 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1232 &tmp_link_layer->link);
1233
1234 /* Add surface to layer */
1235 wl_array_for_each(data, &launchers) {
1236 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001237 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001238 assert(layout_surface);
1239
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001240 ret = ivi_layout_interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001241 layout_surface);
1242 assert(!ret);
1243
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001244 ret = ivi_layout_interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001245 assert(!ret);
1246 }
1247
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001248 wl_array_release(&launchers);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001249 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001250}
1251
1252static void
1253ivi_hmi_controller_UI_ready(struct wl_client *client,
1254 struct wl_resource *resource)
1255{
1256 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1257
1258 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1259 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1260 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1261 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1262 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1263 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1264 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1265 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001266 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001267
1268 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1269 hmi_ctrl->is_initialized = 1;
1270}
1271
1272/**
1273 * Implementation of request and event of ivi_hmi_controller_workspace_control
1274 * and controlling workspace.
1275 *
1276 * When motion of input is detected in a ivi_surface of workspace background,
1277 * ivi_hmi_controller_workspace_control shall be invoked and to start
1278 * controlling of workspace. The workspace has several pages to show several
1279 * groups of applications.
1280 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1281 * according to motion. When motion finished, e.g. touch up detected, control is
1282 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1283 */
1284struct pointer_grab {
1285 struct weston_pointer_grab grab;
1286 struct ivi_layout_layer *layer;
1287 struct wl_resource *resource;
1288};
1289
1290struct touch_grab {
1291 struct weston_touch_grab grab;
1292 struct ivi_layout_layer *layer;
1293 struct wl_resource *resource;
1294};
1295
1296struct move_grab {
1297 wl_fixed_t dst[2];
1298 wl_fixed_t rgn[2][2];
1299 double v[2];
1300 struct timespec start_time;
1301 struct timespec pre_time;
1302 wl_fixed_t start_pos[2];
1303 wl_fixed_t pos[2];
1304 int32_t is_moved;
1305};
1306
1307struct pointer_move_grab {
1308 struct pointer_grab base;
1309 struct move_grab move;
1310};
1311
1312struct touch_move_grab {
1313 struct touch_grab base;
1314 struct move_grab move;
1315 int32_t is_active;
1316};
1317
1318static void
1319pointer_grab_start(struct pointer_grab *grab,
1320 struct ivi_layout_layer *layer,
1321 const struct weston_pointer_grab_interface *interface,
1322 struct weston_pointer *pointer)
1323{
1324 grab->grab.interface = interface;
1325 grab->layer = layer;
1326 weston_pointer_start_grab(pointer, &grab->grab);
1327}
1328
1329static void
1330touch_grab_start(struct touch_grab *grab,
1331 struct ivi_layout_layer *layer,
1332 const struct weston_touch_grab_interface *interface,
1333 struct weston_touch* touch)
1334{
1335 grab->grab.interface = interface;
1336 grab->layer = layer;
1337 weston_touch_start_grab(touch, &grab->grab);
1338}
1339
1340static int32_t
1341clamp(int32_t val, int32_t min, int32_t max)
1342{
1343 if (val < min)
1344 return min;
1345
1346 if (max < val)
1347 return max;
1348
1349 return val;
1350}
1351
1352static void
1353move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1354 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1355{
1356 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1357 int32_t width = hmi_ctrl->workspace_background_layer.width;
1358
1359 struct timespec time = {0};
1360 double grab_time = 0.0;
1361 double from_motion_time = 0.0;
1362 double pointer_v = 0.0;
1363 int32_t is_flick = 0;
1364 int32_t pos_x = 0;
1365 int32_t pos_y = 0;
1366 int page_no = 0;
1367 double end_pos = 0.0;
1368 uint32_t duration = 0;
1369
1370 clock_gettime(CLOCK_MONOTONIC, &time);
1371
1372 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1373 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1374
1375 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1376 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1377
1378 pointer_v = move->v[0];
1379
1380 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1381 if (200 < from_motion_time)
1382 pointer_v = 0.0;
1383
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001384 ivi_layout_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001385
1386
1387 if (is_flick) {
1388 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1389 page_no = (-orgx + width / 2) / width;
1390
1391 if (pointer_v < 0.0)
1392 page_no++;
1393 else
1394 page_no--;
1395 } else {
1396 page_no = (-pos_x + width / 2) / width;
1397 }
1398
1399 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1400 end_pos = -page_no * width;
1401
1402 duration = hmi_ctrl->hmi_setting->transition_duration;
1403 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001404 ivi_layout_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001405 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1406 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001407 ivi_layout_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001408 end_pos, pos_y,
Nobuhiko Tanibata4412cd12015-08-24 09:12:37 +09001409 hmi_ctrl->workspace_layer.width,
1410 hmi_ctrl->workspace_layer.height);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001411 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001412}
1413
1414static void
1415pointer_move_workspace_grab_end(struct pointer_grab *grab)
1416{
1417 struct pointer_move_grab *pnt_move_grab =
1418 (struct pointer_move_grab *)grab;
1419 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1420
1421 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1422 grab->grab.pointer->grab_x, layer);
1423
1424 weston_pointer_end_grab(grab->grab.pointer);
1425}
1426
1427static void
1428touch_move_workspace_grab_end(struct touch_grab *grab)
1429{
1430 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1431 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1432
1433 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1434 grab->grab.touch->grab_x, layer);
1435
1436 weston_touch_end_grab(grab->grab.touch);
1437}
1438
1439static void
1440pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1441{
1442}
1443
1444static void
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001445pointer_default_grab_axis(struct weston_pointer_grab *grab,
1446 uint32_t time, uint32_t axis, wl_fixed_t value)
1447{
1448 weston_pointer_send_axis(grab->pointer, time, axis, value);
1449}
1450
1451static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001452move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1453{
1454 struct timespec timestamp = {0};
1455 int32_t ii = 0;
1456 double dt = 0.0;
1457
1458 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1459 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1460 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1461
1462 if (dt < 1e-6)
1463 dt = 1e-6;
1464
1465 move->pre_time = timestamp;
1466
1467 for (ii = 0; ii < 2; ii++) {
1468 wl_fixed_t prepos = move->pos[ii];
1469 move->pos[ii] = pointer[ii] + move->dst[ii];
1470
1471 if (move->pos[ii] < move->rgn[0][ii]) {
1472 move->pos[ii] = move->rgn[0][ii];
1473 move->dst[ii] = move->pos[ii] - pointer[ii];
1474 } else if (move->rgn[1][ii] < move->pos[ii]) {
1475 move->pos[ii] = move->rgn[1][ii];
1476 move->dst[ii] = move->pos[ii] - pointer[ii];
1477 }
1478
1479 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1480
1481 if (!move->is_moved &&
1482 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1483 move->is_moved = 1;
1484 }
1485}
1486
1487static void
1488layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1489 wl_fixed_t pos_y)
1490{
1491 int32_t layout_pos_x = 0;
1492 int32_t layout_pos_y = 0;
1493
1494 layout_pos_x = wl_fixed_to_int(pos_x);
1495 layout_pos_y = wl_fixed_to_int(pos_y);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001496 ivi_layout_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1497 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001498}
1499
1500static void
1501pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001502 struct weston_pointer_motion_event *event)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001503{
1504 struct pointer_move_grab *pnt_move_grab =
1505 (struct pointer_move_grab *)grab;
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001506 wl_fixed_t pointer_pos[2];
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001507
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001508 weston_pointer_motion_to_abs(grab->pointer, event,
1509 &pointer_pos[0], &pointer_pos[1]);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001510 move_grab_update(&pnt_move_grab->move, pointer_pos);
1511 layer_set_pos(pnt_move_grab->base.layer,
1512 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001513 weston_pointer_move(pnt_move_grab->base.grab.pointer, event);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001514}
1515
1516static void
1517touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1518 int touch_id, wl_fixed_t x, wl_fixed_t y)
1519{
1520 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1521
1522 if (!tch_move_grab->is_active)
1523 return;
1524
1525 wl_fixed_t pointer_pos[2] = {
1526 grab->touch->grab_x,
1527 grab->touch->grab_y
1528 };
1529
1530 move_grab_update(&tch_move_grab->move, pointer_pos);
1531 layer_set_pos(tch_move_grab->base.layer,
1532 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1533}
1534
1535static void
1536pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1537 uint32_t time, uint32_t button,
1538 uint32_t state_w)
1539{
1540 if (BTN_LEFT == button &&
1541 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1542 struct pointer_grab *pg = (struct pointer_grab *)grab;
1543
1544 pointer_move_workspace_grab_end(pg);
1545 free(grab);
1546 }
1547}
1548
1549static void
1550touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1551 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1552{
1553}
1554
1555static void
1556touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1557 int touch_id)
1558{
1559 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1560
1561 if (0 == touch_id)
1562 tch_move_grab->is_active = 0;
1563
1564 if (0 == grab->touch->num_tp) {
1565 touch_move_workspace_grab_end(&tch_move_grab->base);
1566 free(grab);
1567 }
1568}
1569
1570static void
1571pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1572{
1573 struct pointer_grab *pg = (struct pointer_grab *)grab;
1574
1575 pointer_move_workspace_grab_end(pg);
1576 free(grab);
1577}
1578
1579static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001580touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1581{
1582}
1583
1584static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001585touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1586{
1587 struct touch_grab *tg = (struct touch_grab *)grab;
1588
1589 touch_move_workspace_grab_end(tg);
1590 free(grab);
1591}
1592
1593static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1594 pointer_noop_grab_focus,
1595 pointer_move_grab_motion,
1596 pointer_move_workspace_grab_button,
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001597 pointer_default_grab_axis,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001598 pointer_move_workspace_grab_cancel
1599};
1600
1601static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1602 touch_nope_grab_down,
1603 touch_move_workspace_grab_up,
1604 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001605 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001606 touch_move_workspace_grab_cancel
1607};
1608
1609enum HMI_GRAB_DEVICE {
1610 HMI_GRAB_DEVICE_NONE,
1611 HMI_GRAB_DEVICE_POINTER,
1612 HMI_GRAB_DEVICE_TOUCH
1613};
1614
1615static enum HMI_GRAB_DEVICE
1616get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1617{
Derek Foreman1281a362015-07-31 16:55:32 -05001618 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1619 struct weston_touch *touch = weston_seat_get_touch(seat);
1620
1621 if (pointer &&
1622 pointer->focus &&
1623 pointer->button_count &&
1624 pointer->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001625 return HMI_GRAB_DEVICE_POINTER;
1626
Derek Foreman1281a362015-07-31 16:55:32 -05001627 if (touch &&
1628 touch->focus &&
1629 touch->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001630 return HMI_GRAB_DEVICE_TOUCH;
1631
1632 return HMI_GRAB_DEVICE_NONE;
1633}
1634
1635static void
1636move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1637 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1638 struct wl_resource* resource)
1639{
1640 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1641 move->pre_time = move->start_time;
1642 move->pos[0] = start_pos[0];
1643 move->pos[1] = start_pos[1];
1644 move->start_pos[0] = start_pos[0];
1645 move->start_pos[1] = start_pos[1];
1646 move->dst[0] = start_pos[0] - grab_pos[0];
1647 move->dst[1] = start_pos[1] - grab_pos[1];
1648 memcpy(move->rgn, rgn, sizeof(move->rgn));
1649}
1650
1651static void
1652move_grab_init_workspace(struct move_grab* move,
1653 wl_fixed_t grab_x, wl_fixed_t grab_y,
1654 struct wl_resource *resource)
1655{
1656 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1657 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1658 int32_t workspace_count = hmi_ctrl->workspace_count;
1659 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1660 int32_t layer_pos_x = 0;
1661 int32_t layer_pos_y = 0;
1662 wl_fixed_t start_pos[2] = {0};
1663 wl_fixed_t rgn[2][2] = {{0}};
1664 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1665
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001666 ivi_layout_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001667
1668 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1669 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1670
1671 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1672
1673 rgn[0][1] = wl_fixed_from_int(0);
1674 rgn[1][0] = wl_fixed_from_int(0);
1675 rgn[1][1] = wl_fixed_from_int(0);
1676
1677 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1678}
1679
1680static struct pointer_move_grab *
1681create_workspace_pointer_move(struct weston_pointer *pointer,
1682 struct wl_resource* resource)
1683{
1684 struct pointer_move_grab *pnt_move_grab =
1685 MEM_ALLOC(sizeof(*pnt_move_grab));
1686
1687 pnt_move_grab->base.resource = resource;
1688 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1689 pointer->grab_y, resource);
1690
1691 return pnt_move_grab;
1692}
1693
1694static struct touch_move_grab *
1695create_workspace_touch_move(struct weston_touch *touch,
1696 struct wl_resource* resource)
1697{
1698 struct touch_move_grab *tch_move_grab =
1699 MEM_ALLOC(sizeof(*tch_move_grab));
1700
1701 tch_move_grab->base.resource = resource;
1702 tch_move_grab->is_active = 1;
1703 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1704 touch->grab_y, resource);
1705
1706 return tch_move_grab;
1707}
1708
1709static void
1710ivi_hmi_controller_workspace_control(struct wl_client *client,
1711 struct wl_resource *resource,
1712 struct wl_resource *seat_resource,
1713 uint32_t serial)
1714{
1715 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1716 struct ivi_layout_layer *layer = NULL;
1717 struct pointer_move_grab *pnt_move_grab = NULL;
1718 struct touch_move_grab *tch_move_grab = NULL;
1719 struct weston_seat *seat = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001720 struct weston_pointer *pointer;
1721 struct weston_touch *touch;
1722
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001723 enum HMI_GRAB_DEVICE device;
1724
1725 if (hmi_ctrl->workspace_count < 2)
1726 return;
1727
1728 seat = wl_resource_get_user_data(seat_resource);
1729 device = get_hmi_grab_device(seat, serial);
1730
1731 if (HMI_GRAB_DEVICE_POINTER != device &&
1732 HMI_GRAB_DEVICE_TOUCH != device)
1733 return;
1734
1735 layer = hmi_ctrl->workspace_layer.ivilayer;
1736
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001737 ivi_layout_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001738
1739 switch (device) {
1740 case HMI_GRAB_DEVICE_POINTER:
Derek Foreman1281a362015-07-31 16:55:32 -05001741 pointer = weston_seat_get_pointer(seat);
1742 pnt_move_grab = create_workspace_pointer_move(pointer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001743 resource);
1744
1745 pointer_grab_start(&pnt_move_grab->base, layer,
1746 &pointer_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001747 pointer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001748 break;
1749
1750 case HMI_GRAB_DEVICE_TOUCH:
Derek Foreman1281a362015-07-31 16:55:32 -05001751 touch = weston_seat_get_touch(seat);
1752 tch_move_grab = create_workspace_touch_move(touch,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001753 resource);
1754
1755 touch_grab_start(&tch_move_grab->base, layer,
1756 &touch_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001757 touch);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001758 break;
1759
1760 default:
1761 break;
1762 }
1763}
1764
1765/**
1766 * Implementation of switch_mode
1767 */
1768static void
1769ivi_hmi_controller_switch_mode(struct wl_client *client,
1770 struct wl_resource *resource,
1771 uint32_t layout_mode)
1772{
1773 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1774
1775 switch_mode(hmi_ctrl, layout_mode);
1776}
1777
1778/**
1779 * Implementation of on/off displaying workspace and workspace background
1780 * ivi_layers.
1781 */
1782static void
1783ivi_hmi_controller_home(struct wl_client *client,
1784 struct wl_resource *resource,
1785 uint32_t home)
1786{
1787 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1788 uint32_t is_fade_in;
1789
1790 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1791 !hmi_ctrl->workspace_fade.is_fade_in) ||
1792 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1793 hmi_ctrl->workspace_fade.is_fade_in)) {
1794 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1795 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1796 &hmi_ctrl->workspace_fade);
1797 }
1798
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001799 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001800}
1801
1802/**
1803 * binding ivi-hmi-controller implementation
1804 */
1805static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1806 ivi_hmi_controller_UI_ready,
1807 ivi_hmi_controller_workspace_control,
1808 ivi_hmi_controller_switch_mode,
1809 ivi_hmi_controller_home
1810};
1811
1812static void
1813unbind_hmi_controller(struct wl_resource *resource)
1814{
1815}
1816
1817static void
1818bind_hmi_controller(struct wl_client *client,
1819 void *data, uint32_t version, uint32_t id)
1820{
1821 struct wl_resource *resource = NULL;
1822 struct hmi_controller *hmi_ctrl = data;
1823
1824 if (hmi_ctrl->user_interface != client) {
1825 struct wl_resource *res = wl_client_get_object(client, 1);
1826 wl_resource_post_error(res,
1827 WL_DISPLAY_ERROR_INVALID_OBJECT,
1828 "hmi-controller failed: permission denied");
1829 return;
1830 }
1831
1832 resource = wl_resource_create(
1833 client, &ivi_hmi_controller_interface, 1, id);
1834
1835 wl_resource_set_implementation(
1836 resource, &ivi_hmi_controller_implementation,
1837 hmi_ctrl, unbind_hmi_controller);
1838}
1839
1840static int32_t
1841initialize(struct hmi_controller *hmi_ctrl)
1842{
1843 struct config_command {
1844 char *key;
1845 uint32_t *dest;
1846 };
1847
1848 struct weston_config *config = hmi_ctrl->compositor->config;
1849 struct weston_config_section *section = NULL;
1850 int result = 0;
1851 int i = 0;
1852
1853 const struct config_command uint_commands[] = {
1854 { "background-id", &hmi_ctrl->ui_setting.background_id },
1855 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1856 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1857 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1858 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1859 { "random-id", &hmi_ctrl->ui_setting.random_id },
1860 { "home-id", &hmi_ctrl->ui_setting.home_id },
1861 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +09001862 { "surface-id-offset", &hmi_ctrl->ui_setting.surface_id_offset },
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001863 { NULL, NULL }
1864 };
1865
1866 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1867
1868 for (i = 0; -1 != result; ++i) {
1869 const struct config_command *command = &uint_commands[i];
1870
1871 if (!command->key)
1872 break;
1873
1874 if (weston_config_section_get_uint(
1875 section, command->key, command->dest, 0) != 0)
1876 result = -1;
1877 }
1878
1879 if (-1 == result) {
1880 weston_log("Failed to initialize hmi-controller\n");
1881 return 0;
1882 }
1883
1884 return 1;
1885}
1886
1887static void
1888launch_hmi_client_process(void *data)
1889{
1890 struct hmi_controller *hmi_ctrl =
1891 (struct hmi_controller *)data;
1892
1893 hmi_ctrl->user_interface =
1894 weston_client_start(hmi_ctrl->compositor,
1895 hmi_ctrl->hmi_setting->ivi_homescreen);
1896
1897 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1898}
1899
1900/*****************************************************************************
1901 * exported functions
1902 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001903WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001904controller_module_init(struct weston_compositor *ec,
1905 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001906 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001907 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001908{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001909 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001910 struct wl_event_loop *loop = NULL;
1911
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001912 if (interface_version < sizeof(struct ivi_layout_interface)) {
Chris Michaelc083af92015-10-01 10:51:29 -04001913 weston_log("ivi-shell: version mismatch of controller interface\n");
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001914 return -1;
1915 }
1916
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001917 ivi_layout_interface = interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001918
1919 hmi_ctrl = hmi_controller_create(ec);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001920 if (hmi_ctrl == NULL)
1921 return -1;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001922
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001923 if (!initialize(hmi_ctrl)) {
1924 return -1;
1925 }
1926
1927 if (wl_global_create(ec->wl_display,
1928 &ivi_hmi_controller_interface, 1,
1929 hmi_ctrl, bind_hmi_controller) == NULL) {
1930 return -1;
1931 }
1932
1933 loop = wl_display_get_event_loop(ec->wl_display);
1934 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1935
1936 return 0;
1937}