blob: 765d15ff832616c612c55f09cd59723958f46b56 [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 Tanibata4f6853b2014-11-27 13:23:12 +0900115 struct hmi_controller_layer application_layer;
116 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,
216 struct hmi_controller_layer *layer)
217{
218 const float surface_width = (float)layer->width * 0.25;
219 const float surface_height = (float)layer->height * 0.5;
220 int32_t surface_x = 0;
221 int32_t surface_y = 0;
222 struct ivi_layout_surface *ivisurf = NULL;
223 struct ivi_layout_surface **surfaces;
224 struct ivi_layout_surface **new_order;
225 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
226
227 int32_t i = 0;
228 int32_t surf_num = 0;
229 uint32_t num = 1;
230
231 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
232 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
233
234 for (i = 0; i < surface_length; i++) {
235 ivisurf = pp_surface[i];
236
237 /* skip ui widgets */
238 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
239 continue;
240
241 surfaces[surf_num++] = ivisurf;
242 }
243
244 for (i = 0; i < surf_num; i++) {
245 ivisurf = surfaces[i];
246 new_order[i] = ivisurf;
247
248 if (num <= 8) {
249 if (num < 5) {
250 surface_x = (int32_t)((num - 1) * (surface_width));
251 surface_y = 0;
252 } else {
253 surface_x = (int32_t)((num - 5) * (surface_width));
254 surface_y = (int32_t)surface_height;
255 }
256
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000257 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900258 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
259 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000260 ivi_layout_interface->surface_set_visibility(ivisurf, true);
261 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900262 surface_x, surface_y,
263 (int32_t)surface_width,
264 (int32_t)surface_height);
265
266 num++;
267 continue;
268 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000269 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900270 }
271
272 if (surf_num > 0) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000273 ivi_layout_interface->layer_set_transition(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900274 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
275 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900276 }
277
278 free(surfaces);
279 free(new_order);
280}
281
282static void
283mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
284 struct ivi_layout_surface **pp_surface,
285 int32_t surface_length,
286 struct hmi_controller_layer *layer)
287{
288 int32_t surface_width = layer->width / 2;
289 int32_t surface_height = layer->height;
290 struct ivi_layout_surface *ivisurf = NULL;
291
292 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
293 int32_t i = 0;
294 int32_t num = 1;
295
296 for (i = 0; i < surface_length; i++) {
297 ivisurf = pp_surface[i];
298
299 /* skip ui widgets */
300 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
301 continue;
302
303 if (num == 1) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000304 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900305 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
306 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000307 ivi_layout_interface->surface_set_visibility(ivisurf, true);
308 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900309 0, 0,
310 surface_width,
311 surface_height);
312
313 num++;
314 continue;
315 } else if (num == 2) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000316 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900317 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
318 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000319 ivi_layout_interface->surface_set_visibility(ivisurf, true);
320 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900321 surface_width, 0,
322 surface_width,
323 surface_height);
324
325 num++;
326 continue;
327 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000328 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900329 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
330 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000331 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900332 }
333}
334
335static void
336mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
337 struct ivi_layout_surface **pp_surface,
338 int32_t surface_length,
339 struct hmi_controller_layer *layer)
340{
341 const int32_t surface_width = layer->width;
342 const int32_t surface_height = layer->height;
343 struct ivi_layout_surface *ivisurf = NULL;
344 int32_t i = 0;
345 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
346
347 for (i = 0; i < surface_length; i++) {
348 ivisurf = pp_surface[i];
349
350 /* skip ui widgets */
351 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
352 continue;
353
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000354 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900355 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
356 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000357 ivi_layout_interface->surface_set_visibility(ivisurf, true);
358 ivi_layout_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900359 surface_width,
360 surface_height);
361 }
362}
363
364static void
365mode_random_replace(struct hmi_controller *hmi_ctrl,
366 struct ivi_layout_surface **pp_surface,
367 int32_t surface_length,
368 struct hmi_controller_layer *layer)
369{
370 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
371 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
372 int32_t surface_x = 0;
373 int32_t surface_y = 0;
374 struct ivi_layout_surface *ivisurf = NULL;
375 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
376 int32_t i = 0;
377
378 for (i = 0; i < surface_length; i++) {
379 ivisurf = pp_surface[i];
380
381 /* skip ui widgets */
382 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
383 continue;
384
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000385 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900386 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
387 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000388 ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900389 surface_x = rand() % (layer->width - surface_width);
390 surface_y = rand() % (layer->height - surface_height);
391
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000392 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900393 surface_x,
394 surface_y,
395 surface_width,
396 surface_height);
397 }
398}
399
400static int32_t
401has_application_surface(struct hmi_controller *hmi_ctrl,
402 struct ivi_layout_surface **pp_surface,
403 int32_t surface_length)
404{
405 struct ivi_layout_surface *ivisurf = NULL;
406 int32_t i = 0;
407
408 for (i = 0; i < surface_length; i++) {
409 ivisurf = pp_surface[i];
410
411 /* skip ui widgets */
412 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
413 continue;
414
415 return 1;
416 }
417
418 return 0;
419}
420
421/**
422 * Supports 4 example to layout of application ivi_surfaces;
423 * tiling, side by side, fullscreen, and random.
424 */
425static void
426switch_mode(struct hmi_controller *hmi_ctrl,
427 enum ivi_hmi_controller_layout_mode layout_mode)
428{
429 struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
430 struct ivi_layout_surface **pp_surface = NULL;
431 int32_t surface_length = 0;
432 int32_t ret = 0;
433
434 if (!hmi_ctrl->is_initialized)
435 return;
436
437 hmi_ctrl->layout_mode = layout_mode;
438
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000439 ret = ivi_layout_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900440 assert(!ret);
441
442 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
443 free(pp_surface);
444 pp_surface = NULL;
445 return;
446 }
447
448 switch (layout_mode) {
449 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
450 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
451 layer);
452 break;
453 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
454 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
455 surface_length, layer);
456 break;
457 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
458 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
459 layer);
460 break;
461 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
462 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
463 layer);
464 break;
465 }
466
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000467 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900468 free(pp_surface);
469}
470
471/**
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900472 * Internal method to get screens from weston core
473 * TODO: shall support hotplug of screens
474 */
475static int32_t
476get_screens(struct hmi_controller *hmi_ctrl)
477{
478 hmi_ctrl->pp_screen = NULL;
479 hmi_ctrl->screen_num = 0;
480 ivi_layout_interface->get_screens(&hmi_ctrl->screen_num, &hmi_ctrl->pp_screen);
481
482 if (hmi_ctrl->pp_screen == NULL)
483 return -1;
484 else
485 return 0;
486}
487
488/**
489 * Internal method to get ivi_layout_screen
490 */
491static struct ivi_layout_screen *
492get_screen(int32_t screen_idx, struct hmi_controller *hmi_ctrl)
493{
494 struct ivi_layout_screen *iviscrn = NULL;
495
496 if (screen_idx > hmi_ctrl->screen_num - 1)
497 weston_log("Invalid index. Return NULL\n");
498 else
499 iviscrn = hmi_ctrl->pp_screen[screen_idx];
500
501 return iviscrn;
502}
503
504/**
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900505 * Internal method for transition
506 */
507static void
508hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
509 struct hmi_controller_fade *fade)
510{
511 double tint = is_fade_in ? 1.0 : 0.0;
512 struct link_layer *linklayer = NULL;
513 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
514
515 fade->is_fade_in = is_fade_in;
516
517 wl_list_for_each(linklayer, &fade->layer_list, link) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000518 ivi_layout_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900519 IVI_LAYOUT_TRANSITION_LAYER_FADE,
520 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000521 ivi_layout_interface->layer_set_fade_info(linklayer->layout_layer,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900522 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900523 }
524}
525
526/**
527 * Internal method to create ivi_layer with hmi_controller_layer and
528 * add to a ivi_screen
529 */
530static void
531create_layer(struct ivi_layout_screen *iviscrn,
532 struct hmi_controller_layer *layer)
533{
534 int32_t ret = 0;
535
536 layer->ivilayer =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000537 ivi_layout_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900538 layer->width,
539 layer->height);
540 assert(layer->ivilayer != NULL);
541
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000542 ret = ivi_layout_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900543 assert(!ret);
544
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000545 ret = ivi_layout_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900546 layer->x, layer->y,
547 layer->width,
548 layer->height);
549 assert(!ret);
550
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000551 ret = ivi_layout_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900552 assert(!ret);
553}
554
555/**
556 * Internal set notification
557 */
558static void
559set_notification_create_surface(struct ivi_layout_surface *ivisurf,
560 void *userdata)
561{
562 struct hmi_controller *hmi_ctrl = userdata;
563 struct ivi_layout_layer *application_layer =
564 hmi_ctrl->application_layer.ivilayer;
565 int32_t ret = 0;
566
567 /* skip ui widgets */
568 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
569 return;
570
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000571 ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900572 assert(!ret);
573}
574
575static void
576set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
577 void *userdata)
578{
579 struct hmi_controller *hmi_ctrl = userdata;
580
581 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
582}
583
584static void
585set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
586 void *userdata)
587{
588 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900589 struct ivi_layout_layer *application_layer =
590 hmi_ctrl->application_layer.ivilayer;
591 struct weston_surface *surface;
592 struct ivi_layout_surface **ivisurfs;
593 int32_t length = 0;
594 int32_t i;
595
596 /* return if the surface is not application content */
597 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
598 return;
599 }
600
601 /*
602 * if application changes size of wl_buffer. The source rectangle shall be
603 * fit to the size.
604 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000605 surface = ivi_layout_interface->surface_get_weston_surface(ivisurf);
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900606 if (surface) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000607 ivi_layout_interface->surface_set_source_rectangle(
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900608 ivisurf, 0, 0, surface->width,
609 surface->height);
610 }
611
612 /*
613 * search if the surface is already added to layer.
614 * If not yet, it is newly invoded application to go to switch_mode.
615 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000616 ivi_layout_interface->get_surfaces_on_layer(application_layer,
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900617 &length, &ivisurfs);
618 for (i = 0; i < length; i++) {
619 if (ivisurf == ivisurfs[i]) {
Michael Vetter2a18a522015-05-15 17:17:47 +0200620 /*
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900621 * if it is non new invoked application, just call
622 * commit_changes to apply source_rectangle.
623 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000624 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900625 return;
626 }
627 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900628
629 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
630}
631
632/**
633 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
634 * corresponding ivi_layer are defined in weston.ini. Default scene graph
635 * of ivi_layers are initialized in hmi_controller_create
636 */
637static struct hmi_server_setting *
638hmi_server_setting_create(struct weston_compositor *ec)
639{
640 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
641 struct weston_config *config = ec->config;
642 struct weston_config_section *shell_section = NULL;
643
644 shell_section = weston_config_get_section(config, "ivi-shell",
645 NULL, NULL);
646
647 weston_config_section_get_uint(shell_section, "base-layer-id",
648 &setting->base_layer_id, 1000);
649
650 weston_config_section_get_uint(shell_section,
651 "workspace-background-layer-id",
652 &setting->workspace_background_layer_id,
653 2000);
654
655 weston_config_section_get_uint(shell_section, "workspace-layer-id",
656 &setting->workspace_layer_id, 3000);
657
658 weston_config_section_get_uint(shell_section, "application-layer-id",
659 &setting->application_layer_id, 4000);
660
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900661 weston_config_section_get_uint(shell_section, "base-layer-id-offset",
662 &setting->base_layer_id_offset, 10000);
663
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900664 weston_config_section_get_uint(shell_section, "transition-duration",
665 &setting->transition_duration, 300);
666
667 setting->panel_height = 70;
668
669 weston_config_section_get_string(shell_section,
670 "ivi-shell-user-interface",
671 &setting->ivi_homescreen, NULL);
672
673 return setting;
674}
675
676static void
677hmi_controller_destroy(struct wl_listener *listener, void *data)
678{
679 struct link_layer *link = NULL;
680 struct link_layer *next = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900681 struct hmi_controller_layer *ctrl_layer_link = NULL;
682 struct hmi_controller_layer *ctrl_layer_next = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900683 struct hmi_controller *hmi_ctrl =
684 container_of(listener, struct hmi_controller, destroy_listener);
685
686 wl_list_for_each_safe(link, next,
687 &hmi_ctrl->workspace_fade.layer_list, link) {
688 wl_list_remove(&link->link);
689 free(link);
690 }
691
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900692 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
693 &hmi_ctrl->base_layer_list, link) {
694 wl_list_remove(&ctrl_layer_link->link);
695 free(ctrl_layer_link);
696 }
697
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900698 wl_array_release(&hmi_ctrl->ui_widgets);
699 free(hmi_ctrl->hmi_setting);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900700 free(hmi_ctrl->pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900701 free(hmi_ctrl);
702}
703
704/**
705 * This is a starting method called from module_init.
706 * This sets up scene graph of ivi_layers; base, application, workspace
707 * background, and workspace. These ivi_layers are created/added to
708 * ivi_screen in create_layer
709 *
710 * base: to group ivi_surfaces of panel and background
711 * application: to group ivi_surfaces of ivi_applications
712 * workspace background: to group a ivi_surface of background in workspace
713 * workspace: to group ivi_surfaces for launching ivi_applications
714 *
715 * ivi_layers of workspace background and workspace is set to invisible at
716 * first. The properties of it is updated with animation when
717 * ivi_hmi_controller_home is requested.
718 */
719static struct hmi_controller *
720hmi_controller_create(struct weston_compositor *ec)
721{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900722 struct ivi_layout_screen *iviscrn = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900723 int32_t screen_width = 0;
724 int32_t screen_height = 0;
725 struct link_layer *tmp_link_layer = NULL;
726 int32_t panel_height = 0;
727 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900728 struct hmi_controller_layer *base_layer = NULL;
729
730 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900731
732 wl_array_init(&hmi_ctrl->ui_widgets);
733 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
734 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
735 hmi_ctrl->compositor = ec;
736
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900737 /* TODO: shall support hotplug of screens */
738 if (get_screens(hmi_ctrl) < 0) {
739 weston_log("ivi-shell: Failed to get screens\n");
740 hmi_ctrl = NULL;
741 return hmi_ctrl;
742 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900743
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900744 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900745
746 /* init base ivi_layer*/
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900747 wl_list_init(&hmi_ctrl->base_layer_list);
748 for (i = 0; i < hmi_ctrl->screen_num; i++) {
749 ivi_layout_interface->get_screen_resolution(get_screen(i, hmi_ctrl),
750 &screen_width,
751 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900752
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900753 base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
754 base_layer->x = 0;
755 base_layer->y = 0;
756 base_layer->width = screen_width;
757 base_layer->height = screen_height;
758 base_layer->id_layer =
759 hmi_ctrl->hmi_setting->base_layer_id +
760 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
761 wl_list_insert(&hmi_ctrl->base_layer_list, &base_layer->link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900762
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900763 create_layer(get_screen(i, hmi_ctrl), base_layer);
764 }
765
766 ivi_layout_interface->get_screen_resolution(iviscrn, &screen_width,
767 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900768 panel_height = hmi_ctrl->hmi_setting->panel_height;
769
770 /* init application ivi_layer */
771 hmi_ctrl->application_layer.x = 0;
772 hmi_ctrl->application_layer.y = 0;
773 hmi_ctrl->application_layer.width = screen_width;
774 hmi_ctrl->application_layer.height = screen_height - panel_height;
775 hmi_ctrl->application_layer.id_layer =
776 hmi_ctrl->hmi_setting->application_layer_id;
777
778 create_layer(iviscrn, &hmi_ctrl->application_layer);
779
780 /* init workspace background ivi_layer */
781 hmi_ctrl->workspace_background_layer.x = 0;
782 hmi_ctrl->workspace_background_layer.y = 0;
783 hmi_ctrl->workspace_background_layer.width = screen_width;
784 hmi_ctrl->workspace_background_layer.height =
785 screen_height - panel_height;
786
787 hmi_ctrl->workspace_background_layer.id_layer =
788 hmi_ctrl->hmi_setting->workspace_background_layer_id;
789
790 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000791 ivi_layout_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900792 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000793 ivi_layout_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900794 hmi_ctrl->workspace_background_layer.ivilayer, false);
795
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900796
797 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
798 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900799 tmp_link_layer->layout_layer =
800 hmi_ctrl->workspace_background_layer.ivilayer;
801 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
802 &tmp_link_layer->link);
803
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000804 ivi_layout_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900805 set_notification_create_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000806 ivi_layout_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900807 set_notification_remove_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000808 ivi_layout_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900809 set_notification_configure_surface, hmi_ctrl);
810
811 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
812 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
813 &hmi_ctrl->destroy_listener);
814
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900815 return hmi_ctrl;
816}
817
818/**
819 * Implementations of ivi-hmi-controller.xml
820 */
821
822/**
823 * A ivi_surface drawing background is identified by id_surface.
824 * Properties of the ivi_surface is set by using ivi_layout APIs according to
825 * the scene graph of UI defined in hmi_controller_create.
826 *
827 * UI ivi_layer is used to add this ivi_surface.
828 */
829static void
830ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
831 uint32_t id_surface)
832{
833 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900834 struct hmi_controller_layer *base_layer = NULL;
835 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900836 const int32_t dstx = hmi_ctrl->application_layer.x;
837 const int32_t dsty = hmi_ctrl->application_layer.y;
838 const int32_t width = hmi_ctrl->application_layer.width;
839 const int32_t height = hmi_ctrl->application_layer.height;
840 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900841 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900842
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900843 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
844 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
845 sizeof(*add_surface_id));
846 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900847
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900848 ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900849
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900850 ivisurf = ivi_layout_interface->get_surface_from_id(*add_surface_id);
851 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900852
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900853 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
854 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900855
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900856 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
857 dstx, dsty, width, height);
858 assert(!ret);
859
860 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
861 assert(!ret);
862
863 i++;
864 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900865}
866
867/**
868 * A ivi_surface drawing panel is identified by id_surface.
869 * Properties of the ivi_surface is set by using ivi_layout APIs according to
870 * the scene graph of UI defined in hmi_controller_create.
871 *
872 * UI ivi_layer is used to add this ivi_surface.
873 */
874static void
875ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
876 uint32_t id_surface)
877{
878 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900879 struct hmi_controller_layer *base_layer =
880 wl_container_of(hmi_ctrl->base_layer_list.prev,
881 base_layer,
882 link);
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900883 struct ivi_layout_layer *ivilayer = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900884 const int32_t width = base_layer->width;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900885 int32_t ret = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900886 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900887 const int32_t dstx = 0;
888 int32_t dsty = 0;
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900889 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900890
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900891 wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
892 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
893 sizeof(*add_surface_id));
894 *add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900895
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900896 ivilayer = base_layer->ivilayer;
897 ivisurf = ivi_layout_interface->get_surface_from_id(*add_surface_id);
898 assert(ivisurf != NULL);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900899
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900900 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
901 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900902
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900903 dsty = base_layer->height - panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900904
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900905 ret = ivi_layout_interface->surface_set_destination_rectangle(
906 ivisurf, dstx, dsty, width, panel_height);
907 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900908
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900909 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
910 assert(!ret);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900911
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +0900912 i++;
913 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900914}
915
916/**
917 * A ivi_surface drawing buttons in panel is identified by id_surface.
918 * It can set several buttons. Properties of the ivi_surface is set by
919 * using ivi_layout APIs according to the scene graph of UI defined in
920 * hmi_controller_create. Additionally, the position of it is shifted to
921 * right when new one is requested.
922 *
923 * UI ivi_layer is used to add these ivi_surfaces.
924 */
925static void
926ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
927 uint32_t id_surface, int32_t number)
928{
929 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900930 struct hmi_controller_layer *base_layer =
931 wl_container_of(hmi_ctrl->base_layer_list.prev,
932 base_layer,
933 link);
934 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900935 const int32_t width = 48;
936 const int32_t height = 48;
937 int32_t ret = 0;
938 int32_t panel_height = 0;
939 int32_t dstx = 0;
940 int32_t dsty = 0;
941 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
942 sizeof(*add_surface_id));
943 *add_surface_id = id_surface;
944
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000945 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900946 assert(ivisurf != NULL);
947
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000948 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900949 assert(!ret);
950
951 panel_height = hmi_ctrl->hmi_setting->panel_height;
952
953 dstx = (60 * number) + 15;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900954 dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900955
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000956 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900957 ivisurf,dstx, dsty, width, height);
958 assert(!ret);
959
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000960 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900961 assert(!ret);
962}
963
964/**
965 * A ivi_surface drawing home button in panel is identified by id_surface.
966 * Properties of the ivi_surface is set by using ivi_layout APIs according to
967 * the scene graph of UI defined in hmi_controller_create.
968 *
969 * UI ivi_layer is used to add these ivi_surfaces.
970 */
971static void
972ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
973 uint32_t id_surface)
974{
975 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900976 struct hmi_controller_layer *base_layer =
977 wl_container_of(hmi_ctrl->base_layer_list.prev,
978 base_layer,
979 link);
980 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900981 int32_t ret = 0;
982 int32_t size = 48;
983 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900984 const int32_t dstx = (base_layer->width - size) / 2;
985 const int32_t dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900986
987 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
988 sizeof(*add_surface_id));
989 *add_surface_id = id_surface;
990
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000991 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900992 assert(ivisurf != NULL);
993
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000994 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900995 assert(!ret);
996
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000997 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900998 ivisurf, dstx, dsty, size, size);
999 assert(!ret);
1000
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001001 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001002 assert(!ret);
1003}
1004
1005/**
1006 * A ivi_surface drawing background of workspace is identified by id_surface.
1007 * Properties of the ivi_surface is set by using ivi_layout APIs according to
1008 * the scene graph of UI defined in hmi_controller_create.
1009 *
1010 * A ivi_layer of workspace_background is used to add this ivi_surface.
1011 */
1012static void
1013ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
1014 uint32_t id_surface)
1015{
1016 struct ivi_layout_surface *ivisurf = NULL;
1017 struct ivi_layout_layer *ivilayer = NULL;
1018 const int32_t width = hmi_ctrl->workspace_background_layer.width;
1019 const int32_t height = hmi_ctrl->workspace_background_layer.height;
1020 int32_t ret = 0;
1021
1022 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1023 sizeof(*add_surface_id));
1024 *add_surface_id = id_surface;
1025 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
1026
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001027 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001028 assert(ivisurf != NULL);
1029
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001030 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001031 assert(!ret);
1032
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001033 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001034 0, 0, width, height);
1035 assert(!ret);
1036
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001037 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001038 assert(!ret);
1039}
1040
1041/**
1042 * A list of ivi_surfaces drawing launchers in workspace is identified by
1043 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
1044 * APIs according to the scene graph of UI defined in hmi_controller_create.
1045 *
1046 * The workspace can have several pages to group ivi_surfaces of launcher.
1047 * Each call of this interface increments a number of page to add a group
1048 * of ivi_surfaces
1049 */
1050static void
1051ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
1052 int32_t icon_size)
1053{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001054 int32_t minspace_x = 10;
1055 int32_t minspace_y = minspace_x;
1056
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001057 int32_t width = hmi_ctrl->workspace_background_layer.width;
1058 int32_t height = hmi_ctrl->workspace_background_layer.height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001059
1060 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
1061 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
1062 float fcell_size_x = icon_size + space_x;
1063
1064 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
1065 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
1066 float fcell_size_y = icon_size + space_y;
1067
1068 struct weston_config *config = NULL;
1069 struct weston_config_section *section = NULL;
1070 const char *name = NULL;
1071 int launcher_count = 0;
1072 struct wl_array launchers;
1073 int32_t nx = 0;
1074 int32_t ny = 0;
1075 int32_t prev = -1;
1076 struct launcher_info *data = NULL;
1077
1078 uint32_t surfaceid = 0;
1079 uint32_t workspaceid = 0;
1080 struct launcher_info *info = NULL;
1081
1082 int32_t x = 0;
1083 int32_t y = 0;
1084 int32_t ret = 0;
1085 struct ivi_layout_surface* layout_surface = NULL;
1086 uint32_t *add_surface_id = NULL;
1087
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001088 struct ivi_layout_screen *iviscrn = NULL;
1089 struct link_layer *tmp_link_layer = NULL;
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001090
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001091 if (0 == x_count)
1092 x_count = 1;
1093
1094 if (0 == y_count)
1095 y_count = 1;
1096
1097 config = hmi_ctrl->compositor->config;
1098 if (!config)
1099 return;
1100
1101 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1102 if (!section)
1103 return;
1104
1105 wl_array_init(&launchers);
1106
1107 while (weston_config_next_section(config, &section, &name)) {
1108 surfaceid = 0;
1109 workspaceid = 0;
1110 info = NULL;
1111 if (0 != strcmp(name, "ivi-launcher"))
1112 continue;
1113
1114 if (0 != weston_config_section_get_uint(section, "icon-id",
1115 &surfaceid, 0))
1116 continue;
1117
1118 if (0 != weston_config_section_get_uint(section,
1119 "workspace-id",
1120 &workspaceid, 0))
1121 continue;
1122
1123 info = wl_array_add(&launchers, sizeof(*info));
1124
1125 if (info) {
1126 info->surface_id = surfaceid;
1127 info->workspace_id = workspaceid;
1128 info->index = launcher_count;
1129 ++launcher_count;
1130 }
1131 }
1132
1133 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1134 compare_launcher_info);
1135
1136 wl_array_for_each(data, &launchers) {
1137 x = 0;
1138 y = 0;
1139 ret = 0;
1140 layout_surface = NULL;
1141 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1142 sizeof(*add_surface_id));
1143
1144 *add_surface_id = data->surface_id;
1145
1146 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1147 nx = 0;
1148 ny = 0;
1149 prev = data->workspace_id;
1150
1151 if (0 <= prev)
1152 hmi_ctrl->workspace_count++;
1153 }
1154
1155 if (y_count == ny) {
1156 ny = 0;
1157 hmi_ctrl->workspace_count++;
1158 }
1159
1160 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1161 y = ny * fcell_size_y + space_y;
1162
1163 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001164 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001165 assert(layout_surface);
1166
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001167 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001168 layout_surface, x, y, icon_size, icon_size);
1169 assert(!ret);
1170
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001171 nx++;
1172
1173 if (x_count == nx) {
1174 ny++;
1175 nx = 0;
1176 }
1177 }
1178
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001179 /* init workspace ivi_layer */
1180 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1181 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1182 hmi_ctrl->workspace_layer.width =
1183 hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1184 hmi_ctrl->workspace_layer.height =
1185 hmi_ctrl->workspace_background_layer.height;
1186 hmi_ctrl->workspace_layer.id_layer =
1187 hmi_ctrl->hmi_setting->workspace_layer_id;
1188
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001189 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001190 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001191 ivi_layout_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1192 ivi_layout_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001193 false);
1194
1195 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1196 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1197 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1198 &tmp_link_layer->link);
1199
1200 /* Add surface to layer */
1201 wl_array_for_each(data, &launchers) {
1202 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001203 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001204 assert(layout_surface);
1205
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001206 ret = ivi_layout_interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001207 layout_surface);
1208 assert(!ret);
1209
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001210 ret = ivi_layout_interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001211 assert(!ret);
1212 }
1213
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001214 wl_array_release(&launchers);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001215 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001216}
1217
1218static void
1219ivi_hmi_controller_UI_ready(struct wl_client *client,
1220 struct wl_resource *resource)
1221{
1222 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1223
1224 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1225 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1226 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1227 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1228 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1229 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1230 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1231 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001232 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001233
1234 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1235 hmi_ctrl->is_initialized = 1;
1236}
1237
1238/**
1239 * Implementation of request and event of ivi_hmi_controller_workspace_control
1240 * and controlling workspace.
1241 *
1242 * When motion of input is detected in a ivi_surface of workspace background,
1243 * ivi_hmi_controller_workspace_control shall be invoked and to start
1244 * controlling of workspace. The workspace has several pages to show several
1245 * groups of applications.
1246 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1247 * according to motion. When motion finished, e.g. touch up detected, control is
1248 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1249 */
1250struct pointer_grab {
1251 struct weston_pointer_grab grab;
1252 struct ivi_layout_layer *layer;
1253 struct wl_resource *resource;
1254};
1255
1256struct touch_grab {
1257 struct weston_touch_grab grab;
1258 struct ivi_layout_layer *layer;
1259 struct wl_resource *resource;
1260};
1261
1262struct move_grab {
1263 wl_fixed_t dst[2];
1264 wl_fixed_t rgn[2][2];
1265 double v[2];
1266 struct timespec start_time;
1267 struct timespec pre_time;
1268 wl_fixed_t start_pos[2];
1269 wl_fixed_t pos[2];
1270 int32_t is_moved;
1271};
1272
1273struct pointer_move_grab {
1274 struct pointer_grab base;
1275 struct move_grab move;
1276};
1277
1278struct touch_move_grab {
1279 struct touch_grab base;
1280 struct move_grab move;
1281 int32_t is_active;
1282};
1283
1284static void
1285pointer_grab_start(struct pointer_grab *grab,
1286 struct ivi_layout_layer *layer,
1287 const struct weston_pointer_grab_interface *interface,
1288 struct weston_pointer *pointer)
1289{
1290 grab->grab.interface = interface;
1291 grab->layer = layer;
1292 weston_pointer_start_grab(pointer, &grab->grab);
1293}
1294
1295static void
1296touch_grab_start(struct touch_grab *grab,
1297 struct ivi_layout_layer *layer,
1298 const struct weston_touch_grab_interface *interface,
1299 struct weston_touch* touch)
1300{
1301 grab->grab.interface = interface;
1302 grab->layer = layer;
1303 weston_touch_start_grab(touch, &grab->grab);
1304}
1305
1306static int32_t
1307clamp(int32_t val, int32_t min, int32_t max)
1308{
1309 if (val < min)
1310 return min;
1311
1312 if (max < val)
1313 return max;
1314
1315 return val;
1316}
1317
1318static void
1319move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1320 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1321{
1322 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1323 int32_t width = hmi_ctrl->workspace_background_layer.width;
1324
1325 struct timespec time = {0};
1326 double grab_time = 0.0;
1327 double from_motion_time = 0.0;
1328 double pointer_v = 0.0;
1329 int32_t is_flick = 0;
1330 int32_t pos_x = 0;
1331 int32_t pos_y = 0;
1332 int page_no = 0;
1333 double end_pos = 0.0;
1334 uint32_t duration = 0;
1335
1336 clock_gettime(CLOCK_MONOTONIC, &time);
1337
1338 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1339 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1340
1341 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1342 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1343
1344 pointer_v = move->v[0];
1345
1346 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1347 if (200 < from_motion_time)
1348 pointer_v = 0.0;
1349
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001350 ivi_layout_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001351
1352
1353 if (is_flick) {
1354 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1355 page_no = (-orgx + width / 2) / width;
1356
1357 if (pointer_v < 0.0)
1358 page_no++;
1359 else
1360 page_no--;
1361 } else {
1362 page_no = (-pos_x + width / 2) / width;
1363 }
1364
1365 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1366 end_pos = -page_no * width;
1367
1368 duration = hmi_ctrl->hmi_setting->transition_duration;
1369 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001370 ivi_layout_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001371 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1372 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001373 ivi_layout_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001374 end_pos, pos_y,
Nobuhiko Tanibata4412cd12015-08-24 09:12:37 +09001375 hmi_ctrl->workspace_layer.width,
1376 hmi_ctrl->workspace_layer.height);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001377 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001378}
1379
1380static void
1381pointer_move_workspace_grab_end(struct pointer_grab *grab)
1382{
1383 struct pointer_move_grab *pnt_move_grab =
1384 (struct pointer_move_grab *)grab;
1385 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1386
1387 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1388 grab->grab.pointer->grab_x, layer);
1389
1390 weston_pointer_end_grab(grab->grab.pointer);
1391}
1392
1393static void
1394touch_move_workspace_grab_end(struct touch_grab *grab)
1395{
1396 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1397 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1398
1399 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1400 grab->grab.touch->grab_x, layer);
1401
1402 weston_touch_end_grab(grab->grab.touch);
1403}
1404
1405static void
1406pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1407{
1408}
1409
1410static void
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001411pointer_default_grab_axis(struct weston_pointer_grab *grab,
1412 uint32_t time, uint32_t axis, wl_fixed_t value)
1413{
1414 weston_pointer_send_axis(grab->pointer, time, axis, value);
1415}
1416
1417static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001418move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1419{
1420 struct timespec timestamp = {0};
1421 int32_t ii = 0;
1422 double dt = 0.0;
1423
1424 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1425 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1426 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1427
1428 if (dt < 1e-6)
1429 dt = 1e-6;
1430
1431 move->pre_time = timestamp;
1432
1433 for (ii = 0; ii < 2; ii++) {
1434 wl_fixed_t prepos = move->pos[ii];
1435 move->pos[ii] = pointer[ii] + move->dst[ii];
1436
1437 if (move->pos[ii] < move->rgn[0][ii]) {
1438 move->pos[ii] = move->rgn[0][ii];
1439 move->dst[ii] = move->pos[ii] - pointer[ii];
1440 } else if (move->rgn[1][ii] < move->pos[ii]) {
1441 move->pos[ii] = move->rgn[1][ii];
1442 move->dst[ii] = move->pos[ii] - pointer[ii];
1443 }
1444
1445 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1446
1447 if (!move->is_moved &&
1448 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1449 move->is_moved = 1;
1450 }
1451}
1452
1453static void
1454layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1455 wl_fixed_t pos_y)
1456{
1457 int32_t layout_pos_x = 0;
1458 int32_t layout_pos_y = 0;
1459
1460 layout_pos_x = wl_fixed_to_int(pos_x);
1461 layout_pos_y = wl_fixed_to_int(pos_y);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001462 ivi_layout_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1463 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001464}
1465
1466static void
1467pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001468 struct weston_pointer_motion_event *event)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001469{
1470 struct pointer_move_grab *pnt_move_grab =
1471 (struct pointer_move_grab *)grab;
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001472 wl_fixed_t pointer_pos[2];
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001473
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001474 weston_pointer_motion_to_abs(grab->pointer, event,
1475 &pointer_pos[0], &pointer_pos[1]);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001476 move_grab_update(&pnt_move_grab->move, pointer_pos);
1477 layer_set_pos(pnt_move_grab->base.layer,
1478 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001479 weston_pointer_move(pnt_move_grab->base.grab.pointer, event);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001480}
1481
1482static void
1483touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1484 int touch_id, wl_fixed_t x, wl_fixed_t y)
1485{
1486 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1487
1488 if (!tch_move_grab->is_active)
1489 return;
1490
1491 wl_fixed_t pointer_pos[2] = {
1492 grab->touch->grab_x,
1493 grab->touch->grab_y
1494 };
1495
1496 move_grab_update(&tch_move_grab->move, pointer_pos);
1497 layer_set_pos(tch_move_grab->base.layer,
1498 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1499}
1500
1501static void
1502pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1503 uint32_t time, uint32_t button,
1504 uint32_t state_w)
1505{
1506 if (BTN_LEFT == button &&
1507 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1508 struct pointer_grab *pg = (struct pointer_grab *)grab;
1509
1510 pointer_move_workspace_grab_end(pg);
1511 free(grab);
1512 }
1513}
1514
1515static void
1516touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1517 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1518{
1519}
1520
1521static void
1522touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1523 int touch_id)
1524{
1525 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1526
1527 if (0 == touch_id)
1528 tch_move_grab->is_active = 0;
1529
1530 if (0 == grab->touch->num_tp) {
1531 touch_move_workspace_grab_end(&tch_move_grab->base);
1532 free(grab);
1533 }
1534}
1535
1536static void
1537pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1538{
1539 struct pointer_grab *pg = (struct pointer_grab *)grab;
1540
1541 pointer_move_workspace_grab_end(pg);
1542 free(grab);
1543}
1544
1545static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001546touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1547{
1548}
1549
1550static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001551touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1552{
1553 struct touch_grab *tg = (struct touch_grab *)grab;
1554
1555 touch_move_workspace_grab_end(tg);
1556 free(grab);
1557}
1558
1559static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1560 pointer_noop_grab_focus,
1561 pointer_move_grab_motion,
1562 pointer_move_workspace_grab_button,
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001563 pointer_default_grab_axis,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001564 pointer_move_workspace_grab_cancel
1565};
1566
1567static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1568 touch_nope_grab_down,
1569 touch_move_workspace_grab_up,
1570 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001571 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001572 touch_move_workspace_grab_cancel
1573};
1574
1575enum HMI_GRAB_DEVICE {
1576 HMI_GRAB_DEVICE_NONE,
1577 HMI_GRAB_DEVICE_POINTER,
1578 HMI_GRAB_DEVICE_TOUCH
1579};
1580
1581static enum HMI_GRAB_DEVICE
1582get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1583{
Derek Foreman1281a362015-07-31 16:55:32 -05001584 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1585 struct weston_touch *touch = weston_seat_get_touch(seat);
1586
1587 if (pointer &&
1588 pointer->focus &&
1589 pointer->button_count &&
1590 pointer->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001591 return HMI_GRAB_DEVICE_POINTER;
1592
Derek Foreman1281a362015-07-31 16:55:32 -05001593 if (touch &&
1594 touch->focus &&
1595 touch->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001596 return HMI_GRAB_DEVICE_TOUCH;
1597
1598 return HMI_GRAB_DEVICE_NONE;
1599}
1600
1601static void
1602move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1603 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1604 struct wl_resource* resource)
1605{
1606 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1607 move->pre_time = move->start_time;
1608 move->pos[0] = start_pos[0];
1609 move->pos[1] = start_pos[1];
1610 move->start_pos[0] = start_pos[0];
1611 move->start_pos[1] = start_pos[1];
1612 move->dst[0] = start_pos[0] - grab_pos[0];
1613 move->dst[1] = start_pos[1] - grab_pos[1];
1614 memcpy(move->rgn, rgn, sizeof(move->rgn));
1615}
1616
1617static void
1618move_grab_init_workspace(struct move_grab* move,
1619 wl_fixed_t grab_x, wl_fixed_t grab_y,
1620 struct wl_resource *resource)
1621{
1622 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1623 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1624 int32_t workspace_count = hmi_ctrl->workspace_count;
1625 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1626 int32_t layer_pos_x = 0;
1627 int32_t layer_pos_y = 0;
1628 wl_fixed_t start_pos[2] = {0};
1629 wl_fixed_t rgn[2][2] = {{0}};
1630 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1631
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001632 ivi_layout_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001633
1634 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1635 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1636
1637 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1638
1639 rgn[0][1] = wl_fixed_from_int(0);
1640 rgn[1][0] = wl_fixed_from_int(0);
1641 rgn[1][1] = wl_fixed_from_int(0);
1642
1643 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1644}
1645
1646static struct pointer_move_grab *
1647create_workspace_pointer_move(struct weston_pointer *pointer,
1648 struct wl_resource* resource)
1649{
1650 struct pointer_move_grab *pnt_move_grab =
1651 MEM_ALLOC(sizeof(*pnt_move_grab));
1652
1653 pnt_move_grab->base.resource = resource;
1654 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1655 pointer->grab_y, resource);
1656
1657 return pnt_move_grab;
1658}
1659
1660static struct touch_move_grab *
1661create_workspace_touch_move(struct weston_touch *touch,
1662 struct wl_resource* resource)
1663{
1664 struct touch_move_grab *tch_move_grab =
1665 MEM_ALLOC(sizeof(*tch_move_grab));
1666
1667 tch_move_grab->base.resource = resource;
1668 tch_move_grab->is_active = 1;
1669 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1670 touch->grab_y, resource);
1671
1672 return tch_move_grab;
1673}
1674
1675static void
1676ivi_hmi_controller_workspace_control(struct wl_client *client,
1677 struct wl_resource *resource,
1678 struct wl_resource *seat_resource,
1679 uint32_t serial)
1680{
1681 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1682 struct ivi_layout_layer *layer = NULL;
1683 struct pointer_move_grab *pnt_move_grab = NULL;
1684 struct touch_move_grab *tch_move_grab = NULL;
1685 struct weston_seat *seat = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001686 struct weston_pointer *pointer;
1687 struct weston_touch *touch;
1688
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001689 enum HMI_GRAB_DEVICE device;
1690
1691 if (hmi_ctrl->workspace_count < 2)
1692 return;
1693
1694 seat = wl_resource_get_user_data(seat_resource);
1695 device = get_hmi_grab_device(seat, serial);
1696
1697 if (HMI_GRAB_DEVICE_POINTER != device &&
1698 HMI_GRAB_DEVICE_TOUCH != device)
1699 return;
1700
1701 layer = hmi_ctrl->workspace_layer.ivilayer;
1702
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001703 ivi_layout_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001704
1705 switch (device) {
1706 case HMI_GRAB_DEVICE_POINTER:
Derek Foreman1281a362015-07-31 16:55:32 -05001707 pointer = weston_seat_get_pointer(seat);
1708 pnt_move_grab = create_workspace_pointer_move(pointer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001709 resource);
1710
1711 pointer_grab_start(&pnt_move_grab->base, layer,
1712 &pointer_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001713 pointer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001714 break;
1715
1716 case HMI_GRAB_DEVICE_TOUCH:
Derek Foreman1281a362015-07-31 16:55:32 -05001717 touch = weston_seat_get_touch(seat);
1718 tch_move_grab = create_workspace_touch_move(touch,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001719 resource);
1720
1721 touch_grab_start(&tch_move_grab->base, layer,
1722 &touch_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001723 touch);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001724 break;
1725
1726 default:
1727 break;
1728 }
1729}
1730
1731/**
1732 * Implementation of switch_mode
1733 */
1734static void
1735ivi_hmi_controller_switch_mode(struct wl_client *client,
1736 struct wl_resource *resource,
1737 uint32_t layout_mode)
1738{
1739 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1740
1741 switch_mode(hmi_ctrl, layout_mode);
1742}
1743
1744/**
1745 * Implementation of on/off displaying workspace and workspace background
1746 * ivi_layers.
1747 */
1748static void
1749ivi_hmi_controller_home(struct wl_client *client,
1750 struct wl_resource *resource,
1751 uint32_t home)
1752{
1753 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1754 uint32_t is_fade_in;
1755
1756 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1757 !hmi_ctrl->workspace_fade.is_fade_in) ||
1758 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1759 hmi_ctrl->workspace_fade.is_fade_in)) {
1760 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1761 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1762 &hmi_ctrl->workspace_fade);
1763 }
1764
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001765 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001766}
1767
1768/**
1769 * binding ivi-hmi-controller implementation
1770 */
1771static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1772 ivi_hmi_controller_UI_ready,
1773 ivi_hmi_controller_workspace_control,
1774 ivi_hmi_controller_switch_mode,
1775 ivi_hmi_controller_home
1776};
1777
1778static void
1779unbind_hmi_controller(struct wl_resource *resource)
1780{
1781}
1782
1783static void
1784bind_hmi_controller(struct wl_client *client,
1785 void *data, uint32_t version, uint32_t id)
1786{
1787 struct wl_resource *resource = NULL;
1788 struct hmi_controller *hmi_ctrl = data;
1789
1790 if (hmi_ctrl->user_interface != client) {
1791 struct wl_resource *res = wl_client_get_object(client, 1);
1792 wl_resource_post_error(res,
1793 WL_DISPLAY_ERROR_INVALID_OBJECT,
1794 "hmi-controller failed: permission denied");
1795 return;
1796 }
1797
1798 resource = wl_resource_create(
1799 client, &ivi_hmi_controller_interface, 1, id);
1800
1801 wl_resource_set_implementation(
1802 resource, &ivi_hmi_controller_implementation,
1803 hmi_ctrl, unbind_hmi_controller);
1804}
1805
1806static int32_t
1807initialize(struct hmi_controller *hmi_ctrl)
1808{
1809 struct config_command {
1810 char *key;
1811 uint32_t *dest;
1812 };
1813
1814 struct weston_config *config = hmi_ctrl->compositor->config;
1815 struct weston_config_section *section = NULL;
1816 int result = 0;
1817 int i = 0;
1818
1819 const struct config_command uint_commands[] = {
1820 { "background-id", &hmi_ctrl->ui_setting.background_id },
1821 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1822 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1823 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1824 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1825 { "random-id", &hmi_ctrl->ui_setting.random_id },
1826 { "home-id", &hmi_ctrl->ui_setting.home_id },
1827 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
Nobuhiko Tanibata2e656762015-12-09 15:41:46 +09001828 { "surface-id-offset", &hmi_ctrl->ui_setting.surface_id_offset },
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001829 { NULL, NULL }
1830 };
1831
1832 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1833
1834 for (i = 0; -1 != result; ++i) {
1835 const struct config_command *command = &uint_commands[i];
1836
1837 if (!command->key)
1838 break;
1839
1840 if (weston_config_section_get_uint(
1841 section, command->key, command->dest, 0) != 0)
1842 result = -1;
1843 }
1844
1845 if (-1 == result) {
1846 weston_log("Failed to initialize hmi-controller\n");
1847 return 0;
1848 }
1849
1850 return 1;
1851}
1852
1853static void
1854launch_hmi_client_process(void *data)
1855{
1856 struct hmi_controller *hmi_ctrl =
1857 (struct hmi_controller *)data;
1858
1859 hmi_ctrl->user_interface =
1860 weston_client_start(hmi_ctrl->compositor,
1861 hmi_ctrl->hmi_setting->ivi_homescreen);
1862
1863 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1864}
1865
1866/*****************************************************************************
1867 * exported functions
1868 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001869WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001870controller_module_init(struct weston_compositor *ec,
1871 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001872 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001873 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001874{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001875 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001876 struct wl_event_loop *loop = NULL;
1877
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001878 if (interface_version < sizeof(struct ivi_layout_interface)) {
Chris Michaelc083af92015-10-01 10:51:29 -04001879 weston_log("ivi-shell: version mismatch of controller interface\n");
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001880 return -1;
1881 }
1882
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001883 ivi_layout_interface = interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001884
1885 hmi_ctrl = hmi_controller_create(ec);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001886 if (hmi_ctrl == NULL)
1887 return -1;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001888
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001889 if (!initialize(hmi_ctrl)) {
1890 return -1;
1891 }
1892
1893 if (wl_global_create(ec->wl_display,
1894 &ivi_hmi_controller_interface, 1,
1895 hmi_ctrl, bind_hmi_controller) == NULL) {
1896 return -1;
1897 }
1898
1899 loop = wl_display_get_event_loop(ec->wl_display);
1900 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1901
1902 return 0;
1903}