blob: 7739aa794413b55682180e582ea64283b64d4b84 [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;
108};
109
110struct hmi_controller {
111 struct hmi_server_setting *hmi_setting;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900112 /* List of struct hmi_controller_layer */
113 struct wl_list base_layer_list;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900114 struct hmi_controller_layer application_layer;
115 struct hmi_controller_layer workspace_background_layer;
116 struct hmi_controller_layer workspace_layer;
117 enum ivi_hmi_controller_layout_mode layout_mode;
118
119 struct hmi_controller_fade workspace_fade;
120
121 int32_t workspace_count;
122 struct wl_array ui_widgets;
123 int32_t is_initialized;
124
125 struct weston_compositor *compositor;
126 struct wl_listener destroy_listener;
127
128 struct wl_client *user_interface;
129 struct ui_setting ui_setting;
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900130
131 int32_t screen_num;
132 struct ivi_layout_screen **pp_screen;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900133};
134
135struct launcher_info {
136 uint32_t surface_id;
137 uint32_t workspace_id;
138 int32_t index;
139};
140
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000141const struct ivi_layout_interface *ivi_layout_interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900142
143int
144controller_module_init(struct weston_compositor *ec,
145 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000146 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900147 size_t interface_version);
148
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900149/*****************************************************************************
150 * local functions
151 ****************************************************************************/
152static void *
153fail_on_null(void *p, size_t size, char *file, int32_t line)
154{
155 if (size && !p) {
156 weston_log("%s(%d) %zd: out of memory\n", file, line, size);
157 exit(EXIT_FAILURE);
158 }
159
160 return p;
161}
162
163static void *
164mem_alloc(size_t size, char *file, int32_t line)
165{
166 return fail_on_null(calloc(1, size), size, file, line);
167}
168
169#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
170
171static int32_t
172is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
173 struct ivi_layout_surface *ivisurf)
174{
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000175 uint32_t id = ivi_layout_interface->get_id_of_surface(ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900176
177 uint32_t *ui_widget_id = NULL;
178 wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
179 if (*ui_widget_id == id)
180 return 1;
181 }
182
183 return 0;
184}
185
186static int
187compare_launcher_info(const void *lhs, const void *rhs)
188{
189 const struct launcher_info *left = lhs;
190 const struct launcher_info *right = rhs;
191
192 if (left->workspace_id < right->workspace_id)
193 return -1;
194
195 if (left->workspace_id > right->workspace_id)
196 return 1;
197
198 if (left->index < right->index)
199 return -1;
200
201 if (left->index > right->index)
202 return 1;
203
204 return 0;
205}
206
207/**
208 * Internal methods called by mainly ivi_hmi_controller_switch_mode
209 * This reference shows 4 examples how to use ivi_layout APIs.
210 */
211static void
212mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
213 struct ivi_layout_surface **pp_surface,
214 int32_t surface_length,
215 struct hmi_controller_layer *layer)
216{
217 const float surface_width = (float)layer->width * 0.25;
218 const float surface_height = (float)layer->height * 0.5;
219 int32_t surface_x = 0;
220 int32_t surface_y = 0;
221 struct ivi_layout_surface *ivisurf = NULL;
222 struct ivi_layout_surface **surfaces;
223 struct ivi_layout_surface **new_order;
224 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
225
226 int32_t i = 0;
227 int32_t surf_num = 0;
228 uint32_t num = 1;
229
230 surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
231 new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
232
233 for (i = 0; i < surface_length; i++) {
234 ivisurf = pp_surface[i];
235
236 /* skip ui widgets */
237 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
238 continue;
239
240 surfaces[surf_num++] = ivisurf;
241 }
242
243 for (i = 0; i < surf_num; i++) {
244 ivisurf = surfaces[i];
245 new_order[i] = ivisurf;
246
247 if (num <= 8) {
248 if (num < 5) {
249 surface_x = (int32_t)((num - 1) * (surface_width));
250 surface_y = 0;
251 } else {
252 surface_x = (int32_t)((num - 5) * (surface_width));
253 surface_y = (int32_t)surface_height;
254 }
255
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000256 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900257 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
258 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000259 ivi_layout_interface->surface_set_visibility(ivisurf, true);
260 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900261 surface_x, surface_y,
262 (int32_t)surface_width,
263 (int32_t)surface_height);
264
265 num++;
266 continue;
267 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000268 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900269 }
270
271 if (surf_num > 0) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000272 ivi_layout_interface->layer_set_transition(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900273 IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
274 duration);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900275 }
276
277 free(surfaces);
278 free(new_order);
279}
280
281static void
282mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
283 struct ivi_layout_surface **pp_surface,
284 int32_t surface_length,
285 struct hmi_controller_layer *layer)
286{
287 int32_t surface_width = layer->width / 2;
288 int32_t surface_height = layer->height;
289 struct ivi_layout_surface *ivisurf = NULL;
290
291 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
292 int32_t i = 0;
293 int32_t num = 1;
294
295 for (i = 0; i < surface_length; i++) {
296 ivisurf = pp_surface[i];
297
298 /* skip ui widgets */
299 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
300 continue;
301
302 if (num == 1) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000303 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900304 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
305 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000306 ivi_layout_interface->surface_set_visibility(ivisurf, true);
307 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900308 0, 0,
309 surface_width,
310 surface_height);
311
312 num++;
313 continue;
314 } else if (num == 2) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000315 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900316 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
317 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000318 ivi_layout_interface->surface_set_visibility(ivisurf, true);
319 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900320 surface_width, 0,
321 surface_width,
322 surface_height);
323
324 num++;
325 continue;
326 }
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000327 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900328 IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
329 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000330 ivi_layout_interface->surface_set_visibility(ivisurf, false);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900331 }
332}
333
334static void
335mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
336 struct ivi_layout_surface **pp_surface,
337 int32_t surface_length,
338 struct hmi_controller_layer *layer)
339{
340 const int32_t surface_width = layer->width;
341 const int32_t surface_height = layer->height;
342 struct ivi_layout_surface *ivisurf = NULL;
343 int32_t i = 0;
344 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
345
346 for (i = 0; i < surface_length; i++) {
347 ivisurf = pp_surface[i];
348
349 /* skip ui widgets */
350 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
351 continue;
352
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000353 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900354 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
355 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000356 ivi_layout_interface->surface_set_visibility(ivisurf, true);
357 ivi_layout_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900358 surface_width,
359 surface_height);
360 }
361}
362
363static void
364mode_random_replace(struct hmi_controller *hmi_ctrl,
365 struct ivi_layout_surface **pp_surface,
366 int32_t surface_length,
367 struct hmi_controller_layer *layer)
368{
369 const int32_t surface_width = (int32_t)(layer->width * 0.25f);
370 const int32_t surface_height = (int32_t)(layer->height * 0.25f);
371 int32_t surface_x = 0;
372 int32_t surface_y = 0;
373 struct ivi_layout_surface *ivisurf = NULL;
374 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
375 int32_t i = 0;
376
377 for (i = 0; i < surface_length; i++) {
378 ivisurf = pp_surface[i];
379
380 /* skip ui widgets */
381 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
382 continue;
383
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000384 ivi_layout_interface->surface_set_transition(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900385 IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
386 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000387 ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900388 surface_x = rand() % (layer->width - surface_width);
389 surface_y = rand() % (layer->height - surface_height);
390
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000391 ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900392 surface_x,
393 surface_y,
394 surface_width,
395 surface_height);
396 }
397}
398
399static int32_t
400has_application_surface(struct hmi_controller *hmi_ctrl,
401 struct ivi_layout_surface **pp_surface,
402 int32_t surface_length)
403{
404 struct ivi_layout_surface *ivisurf = NULL;
405 int32_t i = 0;
406
407 for (i = 0; i < surface_length; i++) {
408 ivisurf = pp_surface[i];
409
410 /* skip ui widgets */
411 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
412 continue;
413
414 return 1;
415 }
416
417 return 0;
418}
419
420/**
421 * Supports 4 example to layout of application ivi_surfaces;
422 * tiling, side by side, fullscreen, and random.
423 */
424static void
425switch_mode(struct hmi_controller *hmi_ctrl,
426 enum ivi_hmi_controller_layout_mode layout_mode)
427{
428 struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
429 struct ivi_layout_surface **pp_surface = NULL;
430 int32_t surface_length = 0;
431 int32_t ret = 0;
432
433 if (!hmi_ctrl->is_initialized)
434 return;
435
436 hmi_ctrl->layout_mode = layout_mode;
437
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000438 ret = ivi_layout_interface->get_surfaces(&surface_length, &pp_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900439 assert(!ret);
440
441 if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
442 free(pp_surface);
443 pp_surface = NULL;
444 return;
445 }
446
447 switch (layout_mode) {
448 case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
449 mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
450 layer);
451 break;
452 case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
453 mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
454 surface_length, layer);
455 break;
456 case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
457 mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
458 layer);
459 break;
460 case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
461 mode_random_replace(hmi_ctrl, pp_surface, surface_length,
462 layer);
463 break;
464 }
465
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000466 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900467 free(pp_surface);
468}
469
470/**
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900471 * Internal method to get screens from weston core
472 * TODO: shall support hotplug of screens
473 */
474static int32_t
475get_screens(struct hmi_controller *hmi_ctrl)
476{
477 hmi_ctrl->pp_screen = NULL;
478 hmi_ctrl->screen_num = 0;
479 ivi_layout_interface->get_screens(&hmi_ctrl->screen_num, &hmi_ctrl->pp_screen);
480
481 if (hmi_ctrl->pp_screen == NULL)
482 return -1;
483 else
484 return 0;
485}
486
487/**
488 * Internal method to get ivi_layout_screen
489 */
490static struct ivi_layout_screen *
491get_screen(int32_t screen_idx, struct hmi_controller *hmi_ctrl)
492{
493 struct ivi_layout_screen *iviscrn = NULL;
494
495 if (screen_idx > hmi_ctrl->screen_num - 1)
496 weston_log("Invalid index. Return NULL\n");
497 else
498 iviscrn = hmi_ctrl->pp_screen[screen_idx];
499
500 return iviscrn;
501}
502
503/**
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900504 * Internal method for transition
505 */
506static void
507hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
508 struct hmi_controller_fade *fade)
509{
510 double tint = is_fade_in ? 1.0 : 0.0;
511 struct link_layer *linklayer = NULL;
512 const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
513
514 fade->is_fade_in = is_fade_in;
515
516 wl_list_for_each(linklayer, &fade->layer_list, link) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000517 ivi_layout_interface->layer_set_transition(linklayer->layout_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900518 IVI_LAYOUT_TRANSITION_LAYER_FADE,
519 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000520 ivi_layout_interface->layer_set_fade_info(linklayer->layout_layer,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +0900521 is_fade_in, 1.0 - tint, tint);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900522 }
523}
524
525/**
526 * Internal method to create ivi_layer with hmi_controller_layer and
527 * add to a ivi_screen
528 */
529static void
530create_layer(struct ivi_layout_screen *iviscrn,
531 struct hmi_controller_layer *layer)
532{
533 int32_t ret = 0;
534
535 layer->ivilayer =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000536 ivi_layout_interface->layer_create_with_dimension(layer->id_layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900537 layer->width,
538 layer->height);
539 assert(layer->ivilayer != NULL);
540
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000541 ret = ivi_layout_interface->screen_add_layer(iviscrn, layer->ivilayer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900542 assert(!ret);
543
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000544 ret = ivi_layout_interface->layer_set_destination_rectangle(layer->ivilayer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900545 layer->x, layer->y,
546 layer->width,
547 layer->height);
548 assert(!ret);
549
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000550 ret = ivi_layout_interface->layer_set_visibility(layer->ivilayer, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900551 assert(!ret);
552}
553
554/**
555 * Internal set notification
556 */
557static void
558set_notification_create_surface(struct ivi_layout_surface *ivisurf,
559 void *userdata)
560{
561 struct hmi_controller *hmi_ctrl = userdata;
562 struct ivi_layout_layer *application_layer =
563 hmi_ctrl->application_layer.ivilayer;
564 int32_t ret = 0;
565
566 /* skip ui widgets */
567 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
568 return;
569
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000570 ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900571 assert(!ret);
572}
573
574static void
575set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
576 void *userdata)
577{
578 struct hmi_controller *hmi_ctrl = userdata;
579
580 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
581}
582
583static void
584set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
585 void *userdata)
586{
587 struct hmi_controller *hmi_ctrl = userdata;
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900588 struct ivi_layout_layer *application_layer =
589 hmi_ctrl->application_layer.ivilayer;
590 struct weston_surface *surface;
591 struct ivi_layout_surface **ivisurfs;
592 int32_t length = 0;
593 int32_t i;
594
595 /* return if the surface is not application content */
596 if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
597 return;
598 }
599
600 /*
601 * if application changes size of wl_buffer. The source rectangle shall be
602 * fit to the size.
603 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000604 surface = ivi_layout_interface->surface_get_weston_surface(ivisurf);
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900605 if (surface) {
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000606 ivi_layout_interface->surface_set_source_rectangle(
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900607 ivisurf, 0, 0, surface->width,
608 surface->height);
609 }
610
611 /*
612 * search if the surface is already added to layer.
613 * If not yet, it is newly invoded application to go to switch_mode.
614 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000615 ivi_layout_interface->get_surfaces_on_layer(application_layer,
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900616 &length, &ivisurfs);
617 for (i = 0; i < length; i++) {
618 if (ivisurf == ivisurfs[i]) {
Michael Vetter2a18a522015-05-15 17:17:47 +0200619 /*
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900620 * if it is non new invoked application, just call
621 * commit_changes to apply source_rectangle.
622 */
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000623 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata65160dc2015-04-27 17:00:25 +0900624 return;
625 }
626 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900627
628 switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
629}
630
631/**
632 * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
633 * corresponding ivi_layer are defined in weston.ini. Default scene graph
634 * of ivi_layers are initialized in hmi_controller_create
635 */
636static struct hmi_server_setting *
637hmi_server_setting_create(struct weston_compositor *ec)
638{
639 struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
640 struct weston_config *config = ec->config;
641 struct weston_config_section *shell_section = NULL;
642
643 shell_section = weston_config_get_section(config, "ivi-shell",
644 NULL, NULL);
645
646 weston_config_section_get_uint(shell_section, "base-layer-id",
647 &setting->base_layer_id, 1000);
648
649 weston_config_section_get_uint(shell_section,
650 "workspace-background-layer-id",
651 &setting->workspace_background_layer_id,
652 2000);
653
654 weston_config_section_get_uint(shell_section, "workspace-layer-id",
655 &setting->workspace_layer_id, 3000);
656
657 weston_config_section_get_uint(shell_section, "application-layer-id",
658 &setting->application_layer_id, 4000);
659
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900660 weston_config_section_get_uint(shell_section, "base-layer-id-offset",
661 &setting->base_layer_id_offset, 10000);
662
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900663 weston_config_section_get_uint(shell_section, "transition-duration",
664 &setting->transition_duration, 300);
665
666 setting->panel_height = 70;
667
668 weston_config_section_get_string(shell_section,
669 "ivi-shell-user-interface",
670 &setting->ivi_homescreen, NULL);
671
672 return setting;
673}
674
675static void
676hmi_controller_destroy(struct wl_listener *listener, void *data)
677{
678 struct link_layer *link = NULL;
679 struct link_layer *next = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900680 struct hmi_controller_layer *ctrl_layer_link = NULL;
681 struct hmi_controller_layer *ctrl_layer_next = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900682 struct hmi_controller *hmi_ctrl =
683 container_of(listener, struct hmi_controller, destroy_listener);
684
685 wl_list_for_each_safe(link, next,
686 &hmi_ctrl->workspace_fade.layer_list, link) {
687 wl_list_remove(&link->link);
688 free(link);
689 }
690
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900691 wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
692 &hmi_ctrl->base_layer_list, link) {
693 wl_list_remove(&ctrl_layer_link->link);
694 free(ctrl_layer_link);
695 }
696
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900697 wl_array_release(&hmi_ctrl->ui_widgets);
698 free(hmi_ctrl->hmi_setting);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900699 free(hmi_ctrl->pp_screen);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900700 free(hmi_ctrl);
701}
702
703/**
704 * This is a starting method called from module_init.
705 * This sets up scene graph of ivi_layers; base, application, workspace
706 * background, and workspace. These ivi_layers are created/added to
707 * ivi_screen in create_layer
708 *
709 * base: to group ivi_surfaces of panel and background
710 * application: to group ivi_surfaces of ivi_applications
711 * workspace background: to group a ivi_surface of background in workspace
712 * workspace: to group ivi_surfaces for launching ivi_applications
713 *
714 * ivi_layers of workspace background and workspace is set to invisible at
715 * first. The properties of it is updated with animation when
716 * ivi_hmi_controller_home is requested.
717 */
718static struct hmi_controller *
719hmi_controller_create(struct weston_compositor *ec)
720{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900721 struct ivi_layout_screen *iviscrn = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900722 int32_t screen_width = 0;
723 int32_t screen_height = 0;
724 struct link_layer *tmp_link_layer = NULL;
725 int32_t panel_height = 0;
726 struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900727 struct hmi_controller_layer *base_layer = NULL;
728
729 int32_t i = 0;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900730
731 wl_array_init(&hmi_ctrl->ui_widgets);
732 hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
733 hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
734 hmi_ctrl->compositor = ec;
735
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900736 /* TODO: shall support hotplug of screens */
737 if (get_screens(hmi_ctrl) < 0) {
738 weston_log("ivi-shell: Failed to get screens\n");
739 hmi_ctrl = NULL;
740 return hmi_ctrl;
741 }
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900742
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +0900743 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900744
745 /* init base ivi_layer*/
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900746 wl_list_init(&hmi_ctrl->base_layer_list);
747 for (i = 0; i < hmi_ctrl->screen_num; i++) {
748 ivi_layout_interface->get_screen_resolution(get_screen(i, hmi_ctrl),
749 &screen_width,
750 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900751
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900752 base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
753 base_layer->x = 0;
754 base_layer->y = 0;
755 base_layer->width = screen_width;
756 base_layer->height = screen_height;
757 base_layer->id_layer =
758 hmi_ctrl->hmi_setting->base_layer_id +
759 (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
760 wl_list_insert(&hmi_ctrl->base_layer_list, &base_layer->link);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900761
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900762 create_layer(get_screen(i, hmi_ctrl), base_layer);
763 }
764
765 ivi_layout_interface->get_screen_resolution(iviscrn, &screen_width,
766 &screen_height);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900767 panel_height = hmi_ctrl->hmi_setting->panel_height;
768
769 /* init application ivi_layer */
770 hmi_ctrl->application_layer.x = 0;
771 hmi_ctrl->application_layer.y = 0;
772 hmi_ctrl->application_layer.width = screen_width;
773 hmi_ctrl->application_layer.height = screen_height - panel_height;
774 hmi_ctrl->application_layer.id_layer =
775 hmi_ctrl->hmi_setting->application_layer_id;
776
777 create_layer(iviscrn, &hmi_ctrl->application_layer);
778
779 /* init workspace background ivi_layer */
780 hmi_ctrl->workspace_background_layer.x = 0;
781 hmi_ctrl->workspace_background_layer.y = 0;
782 hmi_ctrl->workspace_background_layer.width = screen_width;
783 hmi_ctrl->workspace_background_layer.height =
784 screen_height - panel_height;
785
786 hmi_ctrl->workspace_background_layer.id_layer =
787 hmi_ctrl->hmi_setting->workspace_background_layer_id;
788
789 create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000790 ivi_layout_interface->layer_set_opacity(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900791 hmi_ctrl->workspace_background_layer.ivilayer, 0);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000792 ivi_layout_interface->layer_set_visibility(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900793 hmi_ctrl->workspace_background_layer.ivilayer, false);
794
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900795
796 wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
797 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900798 tmp_link_layer->layout_layer =
799 hmi_ctrl->workspace_background_layer.ivilayer;
800 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
801 &tmp_link_layer->link);
802
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000803 ivi_layout_interface->add_notification_create_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900804 set_notification_create_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000805 ivi_layout_interface->add_notification_remove_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900806 set_notification_remove_surface, hmi_ctrl);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000807 ivi_layout_interface->add_notification_configure_surface(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900808 set_notification_configure_surface, hmi_ctrl);
809
810 hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
811 wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
812 &hmi_ctrl->destroy_listener);
813
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900814 return hmi_ctrl;
815}
816
817/**
818 * Implementations of ivi-hmi-controller.xml
819 */
820
821/**
822 * A ivi_surface drawing background is identified by id_surface.
823 * Properties of the ivi_surface is set by using ivi_layout APIs according to
824 * the scene graph of UI defined in hmi_controller_create.
825 *
826 * UI ivi_layer is used to add this ivi_surface.
827 */
828static void
829ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
830 uint32_t id_surface)
831{
832 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900833 struct hmi_controller_layer *base_layer =
834 wl_container_of(hmi_ctrl->base_layer_list.prev,
835 base_layer,
836 link);
837 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900838 const int32_t dstx = hmi_ctrl->application_layer.x;
839 const int32_t dsty = hmi_ctrl->application_layer.y;
840 const int32_t width = hmi_ctrl->application_layer.width;
841 const int32_t height = hmi_ctrl->application_layer.height;
842 int32_t ret = 0;
843
844 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
845 sizeof(*add_surface_id));
846 *add_surface_id = id_surface;
847
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000848 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900849 assert(ivisurf != NULL);
850
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000851 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900852 assert(!ret);
853
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000854 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900855 dstx, dsty, width, height);
856 assert(!ret);
857
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000858 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900859 assert(!ret);
860}
861
862/**
863 * A ivi_surface drawing panel is identified by id_surface.
864 * Properties of the ivi_surface is set by using ivi_layout APIs according to
865 * the scene graph of UI defined in hmi_controller_create.
866 *
867 * UI ivi_layer is used to add this ivi_surface.
868 */
869static void
870ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
871 uint32_t id_surface)
872{
873 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900874 struct hmi_controller_layer *base_layer =
875 wl_container_of(hmi_ctrl->base_layer_list.prev,
876 base_layer,
877 link);
878 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
879 const int32_t width = base_layer->width;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900880 int32_t ret = 0;
881 int32_t panel_height = 0;
882 const int32_t dstx = 0;
883 int32_t dsty = 0;
884
885 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
886 sizeof(*add_surface_id));
887 *add_surface_id = id_surface;
888
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000889 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900890 assert(ivisurf != NULL);
891
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000892 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900893 assert(!ret);
894
895 panel_height = hmi_ctrl->hmi_setting->panel_height;
896
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900897 dsty = base_layer->height - panel_height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900898
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000899 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900900 ivisurf, dstx, dsty, width, panel_height);
901 assert(!ret);
902
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000903 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900904 assert(!ret);
905}
906
907/**
908 * A ivi_surface drawing buttons in panel is identified by id_surface.
909 * It can set several buttons. Properties of the ivi_surface is set by
910 * using ivi_layout APIs according to the scene graph of UI defined in
911 * hmi_controller_create. Additionally, the position of it is shifted to
912 * right when new one is requested.
913 *
914 * UI ivi_layer is used to add these ivi_surfaces.
915 */
916static void
917ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
918 uint32_t id_surface, int32_t number)
919{
920 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900921 struct hmi_controller_layer *base_layer =
922 wl_container_of(hmi_ctrl->base_layer_list.prev,
923 base_layer,
924 link);
925 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900926 const int32_t width = 48;
927 const int32_t height = 48;
928 int32_t ret = 0;
929 int32_t panel_height = 0;
930 int32_t dstx = 0;
931 int32_t dsty = 0;
932 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
933 sizeof(*add_surface_id));
934 *add_surface_id = id_surface;
935
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000936 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900937 assert(ivisurf != NULL);
938
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000939 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900940 assert(!ret);
941
942 panel_height = hmi_ctrl->hmi_setting->panel_height;
943
944 dstx = (60 * number) + 15;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900945 dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900946
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000947 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900948 ivisurf,dstx, dsty, width, height);
949 assert(!ret);
950
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000951 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900952 assert(!ret);
953}
954
955/**
956 * A ivi_surface drawing home button in panel is identified by id_surface.
957 * Properties of the ivi_surface is set by using ivi_layout APIs according to
958 * the scene graph of UI defined in hmi_controller_create.
959 *
960 * UI ivi_layer is used to add these ivi_surfaces.
961 */
962static void
963ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
964 uint32_t id_surface)
965{
966 struct ivi_layout_surface *ivisurf = NULL;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900967 struct hmi_controller_layer *base_layer =
968 wl_container_of(hmi_ctrl->base_layer_list.prev,
969 base_layer,
970 link);
971 struct ivi_layout_layer *ivilayer = base_layer->ivilayer;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900972 int32_t ret = 0;
973 int32_t size = 48;
974 int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
Nobuhiko Tanibata744b0302015-12-09 15:41:00 +0900975 const int32_t dstx = (base_layer->width - size) / 2;
976 const int32_t dsty = (base_layer->height - panel_height) + 5;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900977
978 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
979 sizeof(*add_surface_id));
980 *add_surface_id = id_surface;
981
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000982 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900983 assert(ivisurf != NULL);
984
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000985 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900986 assert(!ret);
987
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000988 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900989 ivisurf, dstx, dsty, size, size);
990 assert(!ret);
991
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +0000992 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +0900993 assert(!ret);
994}
995
996/**
997 * A ivi_surface drawing background of workspace is identified by id_surface.
998 * Properties of the ivi_surface is set by using ivi_layout APIs according to
999 * the scene graph of UI defined in hmi_controller_create.
1000 *
1001 * A ivi_layer of workspace_background is used to add this ivi_surface.
1002 */
1003static void
1004ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
1005 uint32_t id_surface)
1006{
1007 struct ivi_layout_surface *ivisurf = NULL;
1008 struct ivi_layout_layer *ivilayer = NULL;
1009 const int32_t width = hmi_ctrl->workspace_background_layer.width;
1010 const int32_t height = hmi_ctrl->workspace_background_layer.height;
1011 int32_t ret = 0;
1012
1013 uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1014 sizeof(*add_surface_id));
1015 *add_surface_id = id_surface;
1016 ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
1017
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001018 ivisurf = ivi_layout_interface->get_surface_from_id(id_surface);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001019 assert(ivisurf != NULL);
1020
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001021 ret = ivi_layout_interface->layer_add_surface(ivilayer, ivisurf);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001022 assert(!ret);
1023
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001024 ret = ivi_layout_interface->surface_set_destination_rectangle(ivisurf,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001025 0, 0, width, height);
1026 assert(!ret);
1027
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001028 ret = ivi_layout_interface->surface_set_visibility(ivisurf, true);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001029 assert(!ret);
1030}
1031
1032/**
1033 * A list of ivi_surfaces drawing launchers in workspace is identified by
1034 * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
1035 * APIs according to the scene graph of UI defined in hmi_controller_create.
1036 *
1037 * The workspace can have several pages to group ivi_surfaces of launcher.
1038 * Each call of this interface increments a number of page to add a group
1039 * of ivi_surfaces
1040 */
1041static void
1042ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
1043 int32_t icon_size)
1044{
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001045 int32_t minspace_x = 10;
1046 int32_t minspace_y = minspace_x;
1047
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001048 int32_t width = hmi_ctrl->workspace_background_layer.width;
1049 int32_t height = hmi_ctrl->workspace_background_layer.height;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001050
1051 int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
1052 int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
1053 float fcell_size_x = icon_size + space_x;
1054
1055 int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
1056 int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
1057 float fcell_size_y = icon_size + space_y;
1058
1059 struct weston_config *config = NULL;
1060 struct weston_config_section *section = NULL;
1061 const char *name = NULL;
1062 int launcher_count = 0;
1063 struct wl_array launchers;
1064 int32_t nx = 0;
1065 int32_t ny = 0;
1066 int32_t prev = -1;
1067 struct launcher_info *data = NULL;
1068
1069 uint32_t surfaceid = 0;
1070 uint32_t workspaceid = 0;
1071 struct launcher_info *info = NULL;
1072
1073 int32_t x = 0;
1074 int32_t y = 0;
1075 int32_t ret = 0;
1076 struct ivi_layout_surface* layout_surface = NULL;
1077 uint32_t *add_surface_id = NULL;
1078
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001079 struct ivi_layout_screen *iviscrn = NULL;
1080 struct link_layer *tmp_link_layer = NULL;
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001081
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001082 if (0 == x_count)
1083 x_count = 1;
1084
1085 if (0 == y_count)
1086 y_count = 1;
1087
1088 config = hmi_ctrl->compositor->config;
1089 if (!config)
1090 return;
1091
1092 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1093 if (!section)
1094 return;
1095
1096 wl_array_init(&launchers);
1097
1098 while (weston_config_next_section(config, &section, &name)) {
1099 surfaceid = 0;
1100 workspaceid = 0;
1101 info = NULL;
1102 if (0 != strcmp(name, "ivi-launcher"))
1103 continue;
1104
1105 if (0 != weston_config_section_get_uint(section, "icon-id",
1106 &surfaceid, 0))
1107 continue;
1108
1109 if (0 != weston_config_section_get_uint(section,
1110 "workspace-id",
1111 &workspaceid, 0))
1112 continue;
1113
1114 info = wl_array_add(&launchers, sizeof(*info));
1115
1116 if (info) {
1117 info->surface_id = surfaceid;
1118 info->workspace_id = workspaceid;
1119 info->index = launcher_count;
1120 ++launcher_count;
1121 }
1122 }
1123
1124 qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1125 compare_launcher_info);
1126
1127 wl_array_for_each(data, &launchers) {
1128 x = 0;
1129 y = 0;
1130 ret = 0;
1131 layout_surface = NULL;
1132 add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1133 sizeof(*add_surface_id));
1134
1135 *add_surface_id = data->surface_id;
1136
1137 if (0 > prev || (uint32_t)prev != data->workspace_id) {
1138 nx = 0;
1139 ny = 0;
1140 prev = data->workspace_id;
1141
1142 if (0 <= prev)
1143 hmi_ctrl->workspace_count++;
1144 }
1145
1146 if (y_count == ny) {
1147 ny = 0;
1148 hmi_ctrl->workspace_count++;
1149 }
1150
1151 x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1152 y = ny * fcell_size_y + space_y;
1153
1154 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001155 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001156 assert(layout_surface);
1157
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001158 ret = ivi_layout_interface->surface_set_destination_rectangle(
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001159 layout_surface, x, y, icon_size, icon_size);
1160 assert(!ret);
1161
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001162 nx++;
1163
1164 if (x_count == nx) {
1165 ny++;
1166 nx = 0;
1167 }
1168 }
1169
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001170 /* init workspace ivi_layer */
1171 hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1172 hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1173 hmi_ctrl->workspace_layer.width =
1174 hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1175 hmi_ctrl->workspace_layer.height =
1176 hmi_ctrl->workspace_background_layer.height;
1177 hmi_ctrl->workspace_layer.id_layer =
1178 hmi_ctrl->hmi_setting->workspace_layer_id;
1179
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001180 iviscrn = get_screen(0, hmi_ctrl);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001181 create_layer(iviscrn, &hmi_ctrl->workspace_layer);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001182 ivi_layout_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1183 ivi_layout_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001184 false);
1185
1186 tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1187 tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1188 wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1189 &tmp_link_layer->link);
1190
1191 /* Add surface to layer */
1192 wl_array_for_each(data, &launchers) {
1193 layout_surface =
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001194 ivi_layout_interface->get_surface_from_id(data->surface_id);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001195 assert(layout_surface);
1196
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001197 ret = ivi_layout_interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001198 layout_surface);
1199 assert(!ret);
1200
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001201 ret = ivi_layout_interface->surface_set_visibility(layout_surface, true);
Nobuhiko Tanibatad290f882015-08-24 09:12:23 +09001202 assert(!ret);
1203 }
1204
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001205 wl_array_release(&launchers);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001206 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001207}
1208
1209static void
1210ivi_hmi_controller_UI_ready(struct wl_client *client,
1211 struct wl_resource *resource)
1212{
1213 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1214
1215 ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1216 ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1217 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1218 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1219 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1220 ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1221 ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1222 ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001223 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001224
1225 ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1226 hmi_ctrl->is_initialized = 1;
1227}
1228
1229/**
1230 * Implementation of request and event of ivi_hmi_controller_workspace_control
1231 * and controlling workspace.
1232 *
1233 * When motion of input is detected in a ivi_surface of workspace background,
1234 * ivi_hmi_controller_workspace_control shall be invoked and to start
1235 * controlling of workspace. The workspace has several pages to show several
1236 * groups of applications.
1237 * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
1238 * according to motion. When motion finished, e.g. touch up detected, control is
1239 * terminated and event:ivi_hmi_controller_workspace_control is notified.
1240 */
1241struct pointer_grab {
1242 struct weston_pointer_grab grab;
1243 struct ivi_layout_layer *layer;
1244 struct wl_resource *resource;
1245};
1246
1247struct touch_grab {
1248 struct weston_touch_grab grab;
1249 struct ivi_layout_layer *layer;
1250 struct wl_resource *resource;
1251};
1252
1253struct move_grab {
1254 wl_fixed_t dst[2];
1255 wl_fixed_t rgn[2][2];
1256 double v[2];
1257 struct timespec start_time;
1258 struct timespec pre_time;
1259 wl_fixed_t start_pos[2];
1260 wl_fixed_t pos[2];
1261 int32_t is_moved;
1262};
1263
1264struct pointer_move_grab {
1265 struct pointer_grab base;
1266 struct move_grab move;
1267};
1268
1269struct touch_move_grab {
1270 struct touch_grab base;
1271 struct move_grab move;
1272 int32_t is_active;
1273};
1274
1275static void
1276pointer_grab_start(struct pointer_grab *grab,
1277 struct ivi_layout_layer *layer,
1278 const struct weston_pointer_grab_interface *interface,
1279 struct weston_pointer *pointer)
1280{
1281 grab->grab.interface = interface;
1282 grab->layer = layer;
1283 weston_pointer_start_grab(pointer, &grab->grab);
1284}
1285
1286static void
1287touch_grab_start(struct touch_grab *grab,
1288 struct ivi_layout_layer *layer,
1289 const struct weston_touch_grab_interface *interface,
1290 struct weston_touch* touch)
1291{
1292 grab->grab.interface = interface;
1293 grab->layer = layer;
1294 weston_touch_start_grab(touch, &grab->grab);
1295}
1296
1297static int32_t
1298clamp(int32_t val, int32_t min, int32_t max)
1299{
1300 if (val < min)
1301 return min;
1302
1303 if (max < val)
1304 return max;
1305
1306 return val;
1307}
1308
1309static void
1310move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1311 wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1312{
1313 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1314 int32_t width = hmi_ctrl->workspace_background_layer.width;
1315
1316 struct timespec time = {0};
1317 double grab_time = 0.0;
1318 double from_motion_time = 0.0;
1319 double pointer_v = 0.0;
1320 int32_t is_flick = 0;
1321 int32_t pos_x = 0;
1322 int32_t pos_y = 0;
1323 int page_no = 0;
1324 double end_pos = 0.0;
1325 uint32_t duration = 0;
1326
1327 clock_gettime(CLOCK_MONOTONIC, &time);
1328
1329 grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
1330 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1331
1332 from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
1333 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1334
1335 pointer_v = move->v[0];
1336
1337 is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1338 if (200 < from_motion_time)
1339 pointer_v = 0.0;
1340
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001341 ivi_layout_interface->layer_get_position(layer, &pos_x, &pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001342
1343
1344 if (is_flick) {
1345 int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1346 page_no = (-orgx + width / 2) / width;
1347
1348 if (pointer_v < 0.0)
1349 page_no++;
1350 else
1351 page_no--;
1352 } else {
1353 page_no = (-pos_x + width / 2) / width;
1354 }
1355
1356 page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1357 end_pos = -page_no * width;
1358
1359 duration = hmi_ctrl->hmi_setting->transition_duration;
1360 ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001361 ivi_layout_interface->layer_set_transition(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001362 IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1363 duration);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001364 ivi_layout_interface->layer_set_destination_rectangle(layer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001365 end_pos, pos_y,
Nobuhiko Tanibata4412cd12015-08-24 09:12:37 +09001366 hmi_ctrl->workspace_layer.width,
1367 hmi_ctrl->workspace_layer.height);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001368 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001369}
1370
1371static void
1372pointer_move_workspace_grab_end(struct pointer_grab *grab)
1373{
1374 struct pointer_move_grab *pnt_move_grab =
1375 (struct pointer_move_grab *)grab;
1376 struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1377
1378 move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1379 grab->grab.pointer->grab_x, layer);
1380
1381 weston_pointer_end_grab(grab->grab.pointer);
1382}
1383
1384static void
1385touch_move_workspace_grab_end(struct touch_grab *grab)
1386{
1387 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1388 struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1389
1390 move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1391 grab->grab.touch->grab_x, layer);
1392
1393 weston_touch_end_grab(grab->grab.touch);
1394}
1395
1396static void
1397pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1398{
1399}
1400
1401static void
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001402pointer_default_grab_axis(struct weston_pointer_grab *grab,
1403 uint32_t time, uint32_t axis, wl_fixed_t value)
1404{
1405 weston_pointer_send_axis(grab->pointer, time, axis, value);
1406}
1407
1408static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001409move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1410{
1411 struct timespec timestamp = {0};
1412 int32_t ii = 0;
1413 double dt = 0.0;
1414
1415 clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1416 dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
1417 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1418
1419 if (dt < 1e-6)
1420 dt = 1e-6;
1421
1422 move->pre_time = timestamp;
1423
1424 for (ii = 0; ii < 2; ii++) {
1425 wl_fixed_t prepos = move->pos[ii];
1426 move->pos[ii] = pointer[ii] + move->dst[ii];
1427
1428 if (move->pos[ii] < move->rgn[0][ii]) {
1429 move->pos[ii] = move->rgn[0][ii];
1430 move->dst[ii] = move->pos[ii] - pointer[ii];
1431 } else if (move->rgn[1][ii] < move->pos[ii]) {
1432 move->pos[ii] = move->rgn[1][ii];
1433 move->dst[ii] = move->pos[ii] - pointer[ii];
1434 }
1435
1436 move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1437
1438 if (!move->is_moved &&
1439 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1440 move->is_moved = 1;
1441 }
1442}
1443
1444static void
1445layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
1446 wl_fixed_t pos_y)
1447{
1448 int32_t layout_pos_x = 0;
1449 int32_t layout_pos_y = 0;
1450
1451 layout_pos_x = wl_fixed_to_int(pos_x);
1452 layout_pos_y = wl_fixed_to_int(pos_y);
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001453 ivi_layout_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
1454 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001455}
1456
1457static void
1458pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001459 struct weston_pointer_motion_event *event)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001460{
1461 struct pointer_move_grab *pnt_move_grab =
1462 (struct pointer_move_grab *)grab;
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001463 wl_fixed_t pointer_pos[2];
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001464
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001465 weston_pointer_motion_to_abs(grab->pointer, event,
1466 &pointer_pos[0], &pointer_pos[1]);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001467 move_grab_update(&pnt_move_grab->move, pointer_pos);
1468 layer_set_pos(pnt_move_grab->base.layer,
1469 pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
Jonas Ã…dahld2510102014-10-05 21:39:14 +02001470 weston_pointer_move(pnt_move_grab->base.grab.pointer, event);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001471}
1472
1473static void
1474touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1475 int touch_id, wl_fixed_t x, wl_fixed_t y)
1476{
1477 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1478
1479 if (!tch_move_grab->is_active)
1480 return;
1481
1482 wl_fixed_t pointer_pos[2] = {
1483 grab->touch->grab_x,
1484 grab->touch->grab_y
1485 };
1486
1487 move_grab_update(&tch_move_grab->move, pointer_pos);
1488 layer_set_pos(tch_move_grab->base.layer,
1489 tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1490}
1491
1492static void
1493pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1494 uint32_t time, uint32_t button,
1495 uint32_t state_w)
1496{
1497 if (BTN_LEFT == button &&
1498 WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1499 struct pointer_grab *pg = (struct pointer_grab *)grab;
1500
1501 pointer_move_workspace_grab_end(pg);
1502 free(grab);
1503 }
1504}
1505
1506static void
1507touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
1508 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1509{
1510}
1511
1512static void
1513touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
1514 int touch_id)
1515{
1516 struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1517
1518 if (0 == touch_id)
1519 tch_move_grab->is_active = 0;
1520
1521 if (0 == grab->touch->num_tp) {
1522 touch_move_workspace_grab_end(&tch_move_grab->base);
1523 free(grab);
1524 }
1525}
1526
1527static void
1528pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1529{
1530 struct pointer_grab *pg = (struct pointer_grab *)grab;
1531
1532 pointer_move_workspace_grab_end(pg);
1533 free(grab);
1534}
1535
1536static void
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001537touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1538{
1539}
1540
1541static void
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001542touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1543{
1544 struct touch_grab *tg = (struct touch_grab *)grab;
1545
1546 touch_move_workspace_grab_end(tg);
1547 free(grab);
1548}
1549
1550static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1551 pointer_noop_grab_focus,
1552 pointer_move_grab_motion,
1553 pointer_move_workspace_grab_button,
Jonas Ã…dahl0336ca02014-10-04 16:28:29 +02001554 pointer_default_grab_axis,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001555 pointer_move_workspace_grab_cancel
1556};
1557
1558static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1559 touch_nope_grab_down,
1560 touch_move_workspace_grab_up,
1561 touch_move_grab_motion,
Nobuhiko Tanibata82cc25b2015-02-06 16:08:52 +09001562 touch_move_workspace_grab_frame,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001563 touch_move_workspace_grab_cancel
1564};
1565
1566enum HMI_GRAB_DEVICE {
1567 HMI_GRAB_DEVICE_NONE,
1568 HMI_GRAB_DEVICE_POINTER,
1569 HMI_GRAB_DEVICE_TOUCH
1570};
1571
1572static enum HMI_GRAB_DEVICE
1573get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1574{
Derek Foreman1281a362015-07-31 16:55:32 -05001575 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1576 struct weston_touch *touch = weston_seat_get_touch(seat);
1577
1578 if (pointer &&
1579 pointer->focus &&
1580 pointer->button_count &&
1581 pointer->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001582 return HMI_GRAB_DEVICE_POINTER;
1583
Derek Foreman1281a362015-07-31 16:55:32 -05001584 if (touch &&
1585 touch->focus &&
1586 touch->grab_serial == serial)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001587 return HMI_GRAB_DEVICE_TOUCH;
1588
1589 return HMI_GRAB_DEVICE_NONE;
1590}
1591
1592static void
1593move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1594 wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1595 struct wl_resource* resource)
1596{
1597 clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1598 move->pre_time = move->start_time;
1599 move->pos[0] = start_pos[0];
1600 move->pos[1] = start_pos[1];
1601 move->start_pos[0] = start_pos[0];
1602 move->start_pos[1] = start_pos[1];
1603 move->dst[0] = start_pos[0] - grab_pos[0];
1604 move->dst[1] = start_pos[1] - grab_pos[1];
1605 memcpy(move->rgn, rgn, sizeof(move->rgn));
1606}
1607
1608static void
1609move_grab_init_workspace(struct move_grab* move,
1610 wl_fixed_t grab_x, wl_fixed_t grab_y,
1611 struct wl_resource *resource)
1612{
1613 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1614 struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1615 int32_t workspace_count = hmi_ctrl->workspace_count;
1616 int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1617 int32_t layer_pos_x = 0;
1618 int32_t layer_pos_y = 0;
1619 wl_fixed_t start_pos[2] = {0};
1620 wl_fixed_t rgn[2][2] = {{0}};
1621 wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1622
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001623 ivi_layout_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001624
1625 start_pos[0] = wl_fixed_from_int(layer_pos_x);
1626 start_pos[1] = wl_fixed_from_int(layer_pos_y);
1627
1628 rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1629
1630 rgn[0][1] = wl_fixed_from_int(0);
1631 rgn[1][0] = wl_fixed_from_int(0);
1632 rgn[1][1] = wl_fixed_from_int(0);
1633
1634 move_grab_init(move, start_pos, grab_pos, rgn, resource);
1635}
1636
1637static struct pointer_move_grab *
1638create_workspace_pointer_move(struct weston_pointer *pointer,
1639 struct wl_resource* resource)
1640{
1641 struct pointer_move_grab *pnt_move_grab =
1642 MEM_ALLOC(sizeof(*pnt_move_grab));
1643
1644 pnt_move_grab->base.resource = resource;
1645 move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1646 pointer->grab_y, resource);
1647
1648 return pnt_move_grab;
1649}
1650
1651static struct touch_move_grab *
1652create_workspace_touch_move(struct weston_touch *touch,
1653 struct wl_resource* resource)
1654{
1655 struct touch_move_grab *tch_move_grab =
1656 MEM_ALLOC(sizeof(*tch_move_grab));
1657
1658 tch_move_grab->base.resource = resource;
1659 tch_move_grab->is_active = 1;
1660 move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1661 touch->grab_y, resource);
1662
1663 return tch_move_grab;
1664}
1665
1666static void
1667ivi_hmi_controller_workspace_control(struct wl_client *client,
1668 struct wl_resource *resource,
1669 struct wl_resource *seat_resource,
1670 uint32_t serial)
1671{
1672 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1673 struct ivi_layout_layer *layer = NULL;
1674 struct pointer_move_grab *pnt_move_grab = NULL;
1675 struct touch_move_grab *tch_move_grab = NULL;
1676 struct weston_seat *seat = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001677 struct weston_pointer *pointer;
1678 struct weston_touch *touch;
1679
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001680 enum HMI_GRAB_DEVICE device;
1681
1682 if (hmi_ctrl->workspace_count < 2)
1683 return;
1684
1685 seat = wl_resource_get_user_data(seat_resource);
1686 device = get_hmi_grab_device(seat, serial);
1687
1688 if (HMI_GRAB_DEVICE_POINTER != device &&
1689 HMI_GRAB_DEVICE_TOUCH != device)
1690 return;
1691
1692 layer = hmi_ctrl->workspace_layer.ivilayer;
1693
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001694 ivi_layout_interface->transition_move_layer_cancel(layer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001695
1696 switch (device) {
1697 case HMI_GRAB_DEVICE_POINTER:
Derek Foreman1281a362015-07-31 16:55:32 -05001698 pointer = weston_seat_get_pointer(seat);
1699 pnt_move_grab = create_workspace_pointer_move(pointer,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001700 resource);
1701
1702 pointer_grab_start(&pnt_move_grab->base, layer,
1703 &pointer_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001704 pointer);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001705 break;
1706
1707 case HMI_GRAB_DEVICE_TOUCH:
Derek Foreman1281a362015-07-31 16:55:32 -05001708 touch = weston_seat_get_touch(seat);
1709 tch_move_grab = create_workspace_touch_move(touch,
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001710 resource);
1711
1712 touch_grab_start(&tch_move_grab->base, layer,
1713 &touch_move_grab_workspace_interface,
Derek Foreman1281a362015-07-31 16:55:32 -05001714 touch);
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001715 break;
1716
1717 default:
1718 break;
1719 }
1720}
1721
1722/**
1723 * Implementation of switch_mode
1724 */
1725static void
1726ivi_hmi_controller_switch_mode(struct wl_client *client,
1727 struct wl_resource *resource,
1728 uint32_t layout_mode)
1729{
1730 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1731
1732 switch_mode(hmi_ctrl, layout_mode);
1733}
1734
1735/**
1736 * Implementation of on/off displaying workspace and workspace background
1737 * ivi_layers.
1738 */
1739static void
1740ivi_hmi_controller_home(struct wl_client *client,
1741 struct wl_resource *resource,
1742 uint32_t home)
1743{
1744 struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1745 uint32_t is_fade_in;
1746
1747 if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
1748 !hmi_ctrl->workspace_fade.is_fade_in) ||
1749 (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1750 hmi_ctrl->workspace_fade.is_fade_in)) {
1751 is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1752 hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1753 &hmi_ctrl->workspace_fade);
1754 }
1755
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001756 ivi_layout_interface->commit_changes();
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001757}
1758
1759/**
1760 * binding ivi-hmi-controller implementation
1761 */
1762static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1763 ivi_hmi_controller_UI_ready,
1764 ivi_hmi_controller_workspace_control,
1765 ivi_hmi_controller_switch_mode,
1766 ivi_hmi_controller_home
1767};
1768
1769static void
1770unbind_hmi_controller(struct wl_resource *resource)
1771{
1772}
1773
1774static void
1775bind_hmi_controller(struct wl_client *client,
1776 void *data, uint32_t version, uint32_t id)
1777{
1778 struct wl_resource *resource = NULL;
1779 struct hmi_controller *hmi_ctrl = data;
1780
1781 if (hmi_ctrl->user_interface != client) {
1782 struct wl_resource *res = wl_client_get_object(client, 1);
1783 wl_resource_post_error(res,
1784 WL_DISPLAY_ERROR_INVALID_OBJECT,
1785 "hmi-controller failed: permission denied");
1786 return;
1787 }
1788
1789 resource = wl_resource_create(
1790 client, &ivi_hmi_controller_interface, 1, id);
1791
1792 wl_resource_set_implementation(
1793 resource, &ivi_hmi_controller_implementation,
1794 hmi_ctrl, unbind_hmi_controller);
1795}
1796
1797static int32_t
1798initialize(struct hmi_controller *hmi_ctrl)
1799{
1800 struct config_command {
1801 char *key;
1802 uint32_t *dest;
1803 };
1804
1805 struct weston_config *config = hmi_ctrl->compositor->config;
1806 struct weston_config_section *section = NULL;
1807 int result = 0;
1808 int i = 0;
1809
1810 const struct config_command uint_commands[] = {
1811 { "background-id", &hmi_ctrl->ui_setting.background_id },
1812 { "panel-id", &hmi_ctrl->ui_setting.panel_id },
1813 { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1814 { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1815 { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1816 { "random-id", &hmi_ctrl->ui_setting.random_id },
1817 { "home-id", &hmi_ctrl->ui_setting.home_id },
1818 { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
1819 { NULL, NULL }
1820 };
1821
1822 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1823
1824 for (i = 0; -1 != result; ++i) {
1825 const struct config_command *command = &uint_commands[i];
1826
1827 if (!command->key)
1828 break;
1829
1830 if (weston_config_section_get_uint(
1831 section, command->key, command->dest, 0) != 0)
1832 result = -1;
1833 }
1834
1835 if (-1 == result) {
1836 weston_log("Failed to initialize hmi-controller\n");
1837 return 0;
1838 }
1839
1840 return 1;
1841}
1842
1843static void
1844launch_hmi_client_process(void *data)
1845{
1846 struct hmi_controller *hmi_ctrl =
1847 (struct hmi_controller *)data;
1848
1849 hmi_ctrl->user_interface =
1850 weston_client_start(hmi_ctrl->compositor,
1851 hmi_ctrl->hmi_setting->ivi_homescreen);
1852
1853 free(hmi_ctrl->hmi_setting->ivi_homescreen);
1854}
1855
1856/*****************************************************************************
1857 * exported functions
1858 ****************************************************************************/
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001859WL_EXPORT int
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001860controller_module_init(struct weston_compositor *ec,
1861 int *argc, char *argv[],
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001862 const struct ivi_layout_interface *interface,
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001863 size_t interface_version)
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001864{
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001865 struct hmi_controller *hmi_ctrl = NULL;
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001866 struct wl_event_loop *loop = NULL;
1867
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001868 if (interface_version < sizeof(struct ivi_layout_interface)) {
Chris Michaelc083af92015-10-01 10:51:29 -04001869 weston_log("ivi-shell: version mismatch of controller interface\n");
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001870 return -1;
1871 }
1872
Ucan, Emre \(ADITG/SW1\)0c0e51e2015-10-15 14:51:41 +00001873 ivi_layout_interface = interface;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001874
1875 hmi_ctrl = hmi_controller_create(ec);
Nobuhiko Tanibata35711df2015-12-09 15:40:13 +09001876 if (hmi_ctrl == NULL)
1877 return -1;
Nobuhiko Tanibataee8e5832014-12-15 13:25:39 +09001878
Nobuhiko Tanibata4f6853b2014-11-27 13:23:12 +09001879 if (!initialize(hmi_ctrl)) {
1880 return -1;
1881 }
1882
1883 if (wl_global_create(ec->wl_display,
1884 &ivi_hmi_controller_interface, 1,
1885 hmi_ctrl, bind_hmi_controller) == NULL) {
1886 return -1;
1887 }
1888
1889 loop = wl_display_get_event_loop(ec->wl_display);
1890 wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
1891
1892 return 0;
1893}