• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 DENSO CORPORATION
3  *
4  * 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:
11  *
12  * 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.
24  */
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, an 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 "config.h"
53 
54 #include <sys/wait.h>
55 #include <unistd.h>
56 #include <stdlib.h>
57 #include <stdint.h>
58 #include <stdio.h>
59 #include <string.h>
60 #include <linux/input.h>
61 #include <assert.h>
62 #include <time.h>
63 
64 #include "ivi-layout-export.h"
65 #include "ivi-hmi-controller-server-protocol.h"
66 #include "shared/helpers.h"
67 #include "shared/xalloc.h"
68 #include "compositor/weston.h"
69 
70 /*****************************************************************************
71  *  structure, globals
72  ****************************************************************************/
73 struct hmi_controller_layer {
74 	struct ivi_layout_layer *ivilayer;
75 	uint32_t id_layer;
76 	int32_t x;
77 	int32_t y;
78 	int32_t width;
79 	int32_t height;
80 	struct wl_list link;
81 };
82 
83 struct link_layer {
84 	struct ivi_layout_layer *layout_layer;
85 	struct wl_list link;
86 };
87 
88 struct hmi_controller_fade {
89 	uint32_t is_fade_in;
90 	struct wl_list layer_list;
91 };
92 
93 struct hmi_server_setting {
94 	uint32_t    base_layer_id;
95 	uint32_t    application_layer_id;
96 	uint32_t    workspace_background_layer_id;
97 	uint32_t    workspace_layer_id;
98 	uint32_t    base_layer_id_offset;
99 	int32_t     panel_height;
100 	uint32_t    transition_duration;
101 	char       *ivi_homescreen;
102 };
103 
104 struct ui_setting {
105 	uint32_t background_id;
106 	uint32_t panel_id;
107 	uint32_t tiling_id;
108 	uint32_t sidebyside_id;
109 	uint32_t fullscreen_id;
110 	uint32_t random_id;
111 	uint32_t home_id;
112 	uint32_t workspace_background_id;
113 	uint32_t surface_id_offset;
114 };
115 
116 struct hmi_controller {
117 	struct hmi_server_setting          *hmi_setting;
118 	/* List of struct hmi_controller_layer */
119 	struct wl_list                      base_layer_list;
120 	struct wl_list                      application_layer_list;
121 	struct hmi_controller_layer         workspace_background_layer;
122 	struct hmi_controller_layer         workspace_layer;
123 	enum ivi_hmi_controller_layout_mode layout_mode;
124 
125 	struct hmi_controller_fade          workspace_fade;
126 
127 	int32_t                             workspace_count;
128 	struct wl_array                     ui_widgets;
129 	int32_t                             is_initialized;
130 
131 	struct weston_compositor           *compositor;
132 	struct wl_listener                  destroy_listener;
133 
134 	struct wl_listener                  surface_removed;
135 	struct wl_listener                  surface_configured;
136 	struct wl_listener                  desktop_surface_configured;
137 
138 	struct wl_client                   *user_interface;
139 	struct ui_setting                   ui_setting;
140 
141 	struct weston_output * workspace_background_output;
142 	int32_t				    screen_num;
143 
144 	const struct ivi_layout_interface *interface;
145 };
146 
147 struct launcher_info {
148 	uint32_t surface_id;
149 	uint32_t workspace_id;
150 	int32_t index;
151 };
152 
153 /*****************************************************************************
154  *  local functions
155  ****************************************************************************/
156 static void *
mem_alloc(size_t size,char * file,int32_t line)157 mem_alloc(size_t size, char *file, int32_t line)
158 {
159 	return fail_on_null(calloc(1, size), size, file, line);
160 }
161 
162 #define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
163 
164 static int32_t
is_surf_in_ui_widget(struct hmi_controller * hmi_ctrl,struct ivi_layout_surface * ivisurf)165 is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
166 		     struct ivi_layout_surface *ivisurf)
167 {
168 	uint32_t id = hmi_ctrl->interface->get_id_of_surface(ivisurf);
169 
170 	uint32_t *ui_widget_id = NULL;
171 	wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
172 		if (*ui_widget_id == id)
173 			return 1;
174 	}
175 
176 	return 0;
177 }
178 
179 static int
compare_launcher_info(const void * lhs,const void * rhs)180 compare_launcher_info(const void *lhs, const void *rhs)
181 {
182 	const struct launcher_info *left = lhs;
183 	const struct launcher_info *right = rhs;
184 
185 	if (left->workspace_id < right->workspace_id)
186 		return -1;
187 
188 	if (left->workspace_id > right->workspace_id)
189 		return 1;
190 
191 	if (left->index < right->index)
192 		return -1;
193 
194 	if (left->index > right->index)
195 		return 1;
196 
197 	return 0;
198 }
199 
200 /**
201  * Internal methods called by mainly ivi_hmi_controller_switch_mode
202  * This reference shows 4 examples how to use ivi_layout APIs.
203  */
204 static void
mode_divided_into_tiling(struct hmi_controller * hmi_ctrl,struct ivi_layout_surface ** pp_surface,int32_t surface_length,struct wl_list * layer_list)205 mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
206 			 struct ivi_layout_surface **pp_surface,
207 			 int32_t surface_length,
208 			 struct wl_list *layer_list)
209 {
210 	struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
211 	const float surface_width  = (float)layer->width * 0.25;
212 	const float surface_height = (float)layer->height * 0.5;
213 	int32_t surface_x = 0;
214 	int32_t surface_y = 0;
215 	struct ivi_layout_surface *ivisurf  = NULL;
216 	struct ivi_layout_surface **surfaces;
217 	struct ivi_layout_surface **new_order;
218 	const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
219 	struct ivi_layout_layer *ivilayer = NULL;
220 
221 	int32_t i = 0;
222 	int32_t surf_num = 0;
223 	int32_t idx = 0;
224 
225 	surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
226 	new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
227 
228 	for (i = 0; i < surface_length; i++) {
229 		ivisurf = pp_surface[i];
230 
231 		/* skip ui widgets */
232 		if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
233 			continue;
234 
235 		surfaces[surf_num++] = ivisurf;
236 	}
237 
238 	wl_list_for_each_reverse(layer, layer_list, link) {
239 		if (idx >= surf_num)
240 			break;
241 
242 		ivilayer = layer->ivilayer;
243 
244 		for (i = 0; i < 8; i++, idx++) {
245 			if (idx >= surf_num)
246 				break;
247 
248 			ivisurf = surfaces[idx];
249 			new_order[i] = ivisurf;
250 			if (i < 4) {
251 				surface_x = (int32_t)(i * (surface_width));
252 				surface_y = 0;
253 			} else {
254 				surface_x = (int32_t)((i - 4) * (surface_width));
255 				surface_y = (int32_t)surface_height;
256 			}
257 
258 			hmi_ctrl->interface->surface_set_transition(ivisurf,
259 					IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
260 					duration);
261 			hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
262 			hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
263 					surface_x, surface_y,
264 					(int32_t)surface_width,
265 					(int32_t)surface_height);
266 
267 		}
268 		hmi_ctrl->interface->layer_set_render_order(ivilayer, new_order, i);
269 
270 		hmi_ctrl->interface->layer_set_transition(ivilayer,
271 					IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
272 					duration);
273 	}
274 	for (i = idx; i < surf_num; i++)
275 		hmi_ctrl->interface->surface_set_visibility(surfaces[i], false);
276 
277 	free(surfaces);
278 	free(new_order);
279 }
280 
281 static void
mode_divided_into_sidebyside(struct hmi_controller * hmi_ctrl,struct ivi_layout_surface ** pp_surface,int32_t surface_length,struct wl_list * layer_list)282 mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
283 			     struct ivi_layout_surface **pp_surface,
284 			     int32_t surface_length,
285 			     struct wl_list *layer_list)
286 {
287 	struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
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 	struct ivi_layout_surface **surfaces;
295 	struct ivi_layout_surface **new_order;
296 	struct ivi_layout_layer *ivilayer = NULL;
297 	int32_t surf_num = 0;
298 	int32_t idx = 0;
299 
300 	surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
301 	new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
302 
303 	for (i = 0; i < surface_length; i++) {
304 		ivisurf = pp_surface[i];
305 
306 		/* skip ui widgets */
307 		if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
308 			continue;
309 
310 		surfaces[surf_num++] = ivisurf;
311 	}
312 
313 	wl_list_for_each_reverse(layer, layer_list, link) {
314 		if (idx >= surf_num)
315 			break;
316 
317 		ivilayer = layer->ivilayer;
318 
319 		for (i = 0; i < 2; i++, idx++) {
320 			if (idx >= surf_num)
321 				break;
322 
323 			ivisurf = surfaces[idx];
324 			new_order[i] = ivisurf;
325 
326 			hmi_ctrl->interface->surface_set_transition(ivisurf,
327 					IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
328 					duration);
329 			hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
330 
331 			hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
332 								i * surface_width, 0,
333 								surface_width,
334 								surface_height);
335 		}
336 		hmi_ctrl->interface->layer_set_render_order(ivilayer, new_order, i);
337 	}
338 
339 	for (i = idx; i < surf_num; i++) {
340 		hmi_ctrl->interface->surface_set_transition(surfaces[i],
341 						IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
342 						duration);
343 		hmi_ctrl->interface->surface_set_visibility(surfaces[i], false);
344 	}
345 
346 	free(surfaces);
347 	free(new_order);
348 }
349 
350 static void
mode_fullscreen_someone(struct hmi_controller * hmi_ctrl,struct ivi_layout_surface ** pp_surface,int32_t surface_length,struct wl_list * layer_list)351 mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
352 			struct ivi_layout_surface **pp_surface,
353 			int32_t surface_length,
354 			struct wl_list *layer_list)
355 {
356 	struct hmi_controller_layer *layer = wl_container_of(layer_list->prev, layer, link);
357 	const int32_t  surface_width  = layer->width;
358 	const int32_t  surface_height = layer->height;
359 	struct ivi_layout_surface *ivisurf  = NULL;
360 	int32_t i = 0;
361 	const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
362 	int32_t surf_num = 0;
363 	struct ivi_layout_surface **surfaces;
364 
365 	surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
366 
367 	for (i = 0; i < surface_length; i++) {
368 		ivisurf = pp_surface[i];
369 
370 		/* skip ui widgets */
371 		if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
372 			continue;
373 
374 		surfaces[surf_num++] = ivisurf;
375 	}
376 	hmi_ctrl->interface->layer_set_render_order(layer->ivilayer, surfaces, surf_num);
377 
378 	for (i = 0; i < surf_num; i++) {
379 		ivisurf = surfaces[i];
380 
381 		if ((i > 0) && (i < hmi_ctrl->screen_num)) {
382 			layer = wl_container_of(layer->link.prev, layer, link);
383 			hmi_ctrl->interface->layer_set_render_order(layer->ivilayer, &ivisurf, 1);
384 		}
385 
386 		hmi_ctrl->interface->surface_set_transition(ivisurf,
387 					IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
388 					duration);
389 		hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
390 		hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf, 0, 0,
391 							     surface_width,
392 							     surface_height);
393 	}
394 
395 	free(surfaces);
396 }
397 
398 static void
mode_random_replace(struct hmi_controller * hmi_ctrl,struct ivi_layout_surface ** pp_surface,int32_t surface_length,struct wl_list * layer_list)399 mode_random_replace(struct hmi_controller *hmi_ctrl,
400 		    struct ivi_layout_surface **pp_surface,
401 		    int32_t surface_length,
402 		    struct wl_list *layer_list)
403 {
404 	struct hmi_controller_layer *application_layer = NULL;
405 	struct hmi_controller_layer **layers = NULL;
406 	int32_t surface_width  = 0;
407 	int32_t surface_height = 0;
408 	int32_t surface_x = 0;
409 	int32_t surface_y = 0;
410 	struct ivi_layout_surface *ivisurf  = NULL;
411 	const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
412 	int32_t i = 0;
413 	int32_t layer_idx = 0;
414 
415 	layers = MEM_ALLOC(sizeof(*layers) * hmi_ctrl->screen_num);
416 
417 	wl_list_for_each(application_layer, layer_list, link) {
418 		layers[layer_idx] = application_layer;
419 		layer_idx++;
420 	}
421 
422 	for (i = 0; i < surface_length; i++) {
423 		ivisurf = pp_surface[i];
424 
425 		/* skip ui widgets */
426 		if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
427 			continue;
428 
429 		/* surface determined at random a layer that belongs */
430 		layer_idx = rand() % hmi_ctrl->screen_num;
431 
432 		hmi_ctrl->interface->surface_set_transition(ivisurf,
433 					IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
434 					duration);
435 
436 		hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
437 
438 		surface_width  = (int32_t)(layers[layer_idx]->width * 0.25f);
439 		surface_height = (int32_t)(layers[layer_idx]->height * 0.25f);
440 		surface_x = rand() % (layers[layer_idx]->width - surface_width);
441 		surface_y = rand() % (layers[layer_idx]->height - surface_height);
442 
443 		hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
444 							     surface_x,
445 							     surface_y,
446 							     surface_width,
447 							     surface_height);
448 
449 		hmi_ctrl->interface->layer_add_surface(layers[layer_idx]->ivilayer, ivisurf);
450 	}
451 
452 	free(layers);
453 }
454 
455 static int32_t
has_application_surface(struct hmi_controller * hmi_ctrl,struct ivi_layout_surface ** pp_surface,int32_t surface_length)456 has_application_surface(struct hmi_controller *hmi_ctrl,
457 			struct ivi_layout_surface **pp_surface,
458 			int32_t surface_length)
459 {
460 	struct ivi_layout_surface *ivisurf  = NULL;
461 	int32_t i = 0;
462 
463 	for (i = 0; i < surface_length; i++) {
464 		ivisurf = pp_surface[i];
465 
466 		/* skip ui widgets */
467 		if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
468 			continue;
469 
470 		return 1;
471 	}
472 
473 	return 0;
474 }
475 
476 /**
477  * Supports 4 example to layout of application ivi_surfaces;
478  * tiling, side by side, fullscreen, and random.
479  */
480 static void
switch_mode(struct hmi_controller * hmi_ctrl,enum ivi_hmi_controller_layout_mode layout_mode)481 switch_mode(struct hmi_controller *hmi_ctrl,
482 	    enum ivi_hmi_controller_layout_mode layout_mode)
483 {
484 	struct wl_list *layer = &hmi_ctrl->application_layer_list;
485 	struct ivi_layout_surface **pp_surface = NULL;
486 	int32_t surface_length = 0;
487 	int32_t ret = 0;
488 
489 	if (!hmi_ctrl->is_initialized)
490 		return;
491 
492 	hmi_ctrl->layout_mode = layout_mode;
493 
494 	ret = hmi_ctrl->interface->get_surfaces(&surface_length, &pp_surface);
495 	assert(!ret);
496 
497 	if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
498 		free(pp_surface);
499 		pp_surface = NULL;
500 		return;
501 	}
502 
503 	switch (layout_mode) {
504 	case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
505 		mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
506 					 layer);
507 		break;
508 	case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
509 		mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
510 					     surface_length, layer);
511 		break;
512 	case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
513 		mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
514 					layer);
515 		break;
516 	case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
517 		mode_random_replace(hmi_ctrl, pp_surface, surface_length,
518 				    layer);
519 		break;
520 	}
521 
522 	hmi_ctrl->interface->commit_changes();
523 	free(pp_surface);
524 }
525 
526 /**
527  * Internal method for transition
528  */
529 static void
hmi_controller_fade_run(struct hmi_controller * hmi_ctrl,uint32_t is_fade_in,struct hmi_controller_fade * fade)530 hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
531 			struct hmi_controller_fade *fade)
532 {
533 	double tint = is_fade_in ? 1.0 : 0.0;
534 	struct link_layer *linklayer = NULL;
535 	const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
536 
537 	fade->is_fade_in = is_fade_in;
538 
539 	wl_list_for_each(linklayer, &fade->layer_list, link) {
540 		hmi_ctrl->interface->layer_set_transition(linklayer->layout_layer,
541 					IVI_LAYOUT_TRANSITION_LAYER_FADE,
542 					duration);
543 		hmi_ctrl->interface->layer_set_fade_info(linklayer->layout_layer,
544 					is_fade_in, 1.0 - tint, tint);
545 	}
546 }
547 
548 /**
549  * Internal method to create ivi_layer with hmi_controller_layer and
550  * add to a weston_output
551  */
552 static void
create_layer(struct weston_output * output,struct hmi_controller_layer * layer,struct hmi_controller * hmi_ctrl)553 create_layer(struct weston_output *output,
554 	     struct hmi_controller_layer *layer,
555 	     struct hmi_controller *hmi_ctrl)
556 {
557 	int32_t ret = 0;
558 
559 	layer->ivilayer =
560 		hmi_ctrl->interface->layer_create_with_dimension(layer->id_layer,
561 						       layer->width,
562 						       layer->height);
563 	assert(layer->ivilayer != NULL);
564 
565 	ret = hmi_ctrl->interface->screen_add_layer(output, layer->ivilayer);
566 	assert(!ret);
567 
568 	ret = hmi_ctrl->interface->layer_set_destination_rectangle(layer->ivilayer,
569 							 layer->x, layer->y,
570 							 layer->width,
571 							 layer->height);
572 	assert(!ret);
573 
574 	ret = hmi_ctrl->interface->layer_set_visibility(layer->ivilayer, true);
575 	assert(!ret);
576 }
577 
578 /**
579  * Internal set notification
580  */
581 static void
set_notification_remove_surface(struct wl_listener * listener,void * data)582 set_notification_remove_surface(struct wl_listener *listener, void *data)
583 {
584 	struct hmi_controller *hmi_ctrl =
585 			wl_container_of(listener, hmi_ctrl,
586 					surface_removed);
587 	(void)data;
588 
589 	switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
590 }
591 
592 static void
set_notification_configure_surface(struct wl_listener * listener,void * data)593 set_notification_configure_surface(struct wl_listener *listener, void *data)
594 {
595 	struct hmi_controller *hmi_ctrl =
596 			wl_container_of(listener, hmi_ctrl,
597 					surface_configured);
598 	struct ivi_layout_surface *ivisurf = data;
599 	struct hmi_controller_layer *layer_link = NULL;
600 	struct ivi_layout_layer *application_layer = NULL;
601 	struct weston_surface *surface;
602 	struct ivi_layout_surface **ivisurfs = NULL;
603 	int32_t length = 0;
604 	int32_t i;
605 
606 	/* return if the surface is not application content */
607 	if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
608 		return;
609 	}
610 
611 	/*
612 	 * if application changes size of wl_buffer. The source rectangle shall be
613 	 * fit to the size.
614 	 */
615 	surface = hmi_ctrl->interface->surface_get_weston_surface(ivisurf);
616 	if (surface) {
617 		hmi_ctrl->interface->surface_set_source_rectangle(
618 			ivisurf, 0, 0, surface->width,
619 			surface->height);
620 	}
621 
622 	/*
623 	 *  search if the surface is already added to layer.
624 	 *  If not yet, it is newly invoded application to go to switch_mode.
625 	 */
626 	wl_list_for_each_reverse(layer_link, &hmi_ctrl->application_layer_list, link) {
627 		application_layer = layer_link->ivilayer;
628 		hmi_ctrl->interface->get_surfaces_on_layer(application_layer,
629 							&length, &ivisurfs);
630 		for (i = 0; i < length; i++) {
631 			if (ivisurf == ivisurfs[i]) {
632 				/*
633 				 * if it is non new invoked application, just call
634 				 * commit_changes to apply source_rectangle.
635 				 */
636 				hmi_ctrl->interface->commit_changes();
637 				free(ivisurfs);
638 				return;
639 			}
640 		}
641 		free(ivisurfs);
642 		ivisurfs = NULL;
643 	}
644 
645 	switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
646 }
647 
648 static void
set_notification_configure_desktop_surface(struct wl_listener * listener,void * data)649 set_notification_configure_desktop_surface(struct wl_listener *listener, void *data)
650 {
651 	struct hmi_controller *hmi_ctrl =
652 			wl_container_of(listener, hmi_ctrl,
653 					desktop_surface_configured);
654 	struct ivi_layout_surface *ivisurf = data;
655 	struct hmi_controller_layer *layer_link =
656 					wl_container_of(hmi_ctrl->application_layer_list.prev,
657 							layer_link,
658 							link);
659 	struct ivi_layout_layer *application_layer = layer_link->ivilayer;
660 	struct weston_surface *surface;
661 	int32_t ret = 0;
662 
663 	/* skip ui widgets */
664 	if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
665 		return;
666 
667 	ret = hmi_ctrl->interface->layer_add_surface(application_layer, ivisurf);
668 	assert(!ret);
669 
670 	/*
671 	 * if application changes size of wl_buffer. The source rectangle shall be
672 	 * fit to the size.
673 	 */
674 	surface = hmi_ctrl->interface->surface_get_weston_surface(ivisurf);
675 	if (surface) {
676 		hmi_ctrl->interface->surface_set_source_rectangle(ivisurf, 0,
677 				0, surface->width, surface->height);
678 	}
679 
680 	hmi_ctrl->interface->commit_changes();
681 	switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
682 }
683 
684 /**
685  * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
686  * corresponding ivi_layer are defined in weston.ini. Default scene graph
687  * of ivi_layers are initialized in hmi_controller_create
688  */
689 static struct hmi_server_setting *
hmi_server_setting_create(struct weston_compositor * ec)690 hmi_server_setting_create(struct weston_compositor *ec)
691 {
692 	struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
693 	struct weston_config *config = wet_get_config(ec);
694 	struct weston_config_section *shell_section = NULL;
695 	char *ivi_ui_config;
696 
697 	shell_section = weston_config_get_section(config, "ivi-shell",
698 						  NULL, NULL);
699 
700 	weston_config_section_get_uint(shell_section, "base-layer-id",
701 				       &setting->base_layer_id, 1000);
702 
703 	weston_config_section_get_uint(shell_section,
704 				       "workspace-background-layer-id",
705 				       &setting->workspace_background_layer_id,
706 				       2000);
707 
708 	weston_config_section_get_uint(shell_section, "workspace-layer-id",
709 				       &setting->workspace_layer_id, 3000);
710 
711 	weston_config_section_get_uint(shell_section, "application-layer-id",
712 				       &setting->application_layer_id, 4000);
713 
714 	weston_config_section_get_uint(shell_section, "base-layer-id-offset",
715 				       &setting->base_layer_id_offset, 10000);
716 
717 	weston_config_section_get_uint(shell_section, "transition-duration",
718 				       &setting->transition_duration, 300);
719 
720 	setting->panel_height = 70;
721 
722 	weston_config_section_get_string(shell_section,
723 					 "ivi-shell-user-interface",
724 					 &ivi_ui_config, NULL);
725 	if (ivi_ui_config && ivi_ui_config[0] != '/') {
726 		setting->ivi_homescreen = wet_get_libexec_path(ivi_ui_config);
727 		if (setting->ivi_homescreen)
728 			free(ivi_ui_config);
729 		else
730 			setting->ivi_homescreen = ivi_ui_config;
731 	} else {
732 		setting->ivi_homescreen = ivi_ui_config;
733 	}
734 
735 	return setting;
736 }
737 
738 static void
hmi_controller_destroy(struct wl_listener * listener,void * data)739 hmi_controller_destroy(struct wl_listener *listener, void *data)
740 {
741 	struct link_layer *link = NULL;
742 	struct link_layer *next = NULL;
743 	struct hmi_controller_layer *ctrl_layer_link = NULL;
744 	struct hmi_controller_layer *ctrl_layer_next = NULL;
745 	struct hmi_controller *hmi_ctrl =
746 		container_of(listener, struct hmi_controller, destroy_listener);
747 
748 	wl_list_for_each_safe(link, next,
749 			      &hmi_ctrl->workspace_fade.layer_list, link) {
750 		wl_list_remove(&link->link);
751 		free(link);
752 	}
753 
754 	/* clear base_layer_list */
755 	wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
756 			      &hmi_ctrl->base_layer_list, link) {
757 		wl_list_remove(&ctrl_layer_link->link);
758 		free(ctrl_layer_link);
759 	}
760 
761 	/* clear application_layer_list */
762 	wl_list_for_each_safe(ctrl_layer_link, ctrl_layer_next,
763 			      &hmi_ctrl->application_layer_list, link) {
764 		wl_list_remove(&ctrl_layer_link->link);
765 		free(ctrl_layer_link);
766 	}
767 
768 	wl_array_release(&hmi_ctrl->ui_widgets);
769 	free(hmi_ctrl->hmi_setting);
770 	free(hmi_ctrl);
771 }
772 
773 /**
774  * This is a starting method called from module_init.
775  * This sets up scene graph of ivi_layers; base, application, workspace
776  * background, and workspace. These ivi_layers are created/added to
777  * ivi_screen in create_layer
778  *
779  * base: to group ivi_surfaces of panel and background
780  * application: to group ivi_surfaces of ivi_applications
781  * workspace background: to group a ivi_surface of background in workspace
782  * workspace: to group ivi_surfaces for launching ivi_applications
783  *
784  * ivi_layers of workspace background and workspace is set to invisible at
785  * first. The properties of it is updated with animation when
786  * ivi_hmi_controller_home is requested.
787  */
788 static struct hmi_controller *
hmi_controller_create(struct weston_compositor * ec)789 hmi_controller_create(struct weston_compositor *ec)
790 {
791 	struct link_layer *tmp_link_layer = NULL;
792 	int32_t panel_height = 0;
793 	struct hmi_controller *hmi_ctrl;
794 	const struct ivi_layout_interface *interface;
795 	struct hmi_controller_layer *base_layer = NULL;
796 	struct hmi_controller_layer *application_layer = NULL;
797 	struct weston_output *output;
798 	int32_t i;
799 
800 	interface = ivi_layout_get_api(ec);
801 
802 	if (!interface) {
803 		weston_log("Cannot use ivi_layout_interface.\n");
804 		return NULL;
805 	}
806 
807 	hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
808 	i = 0;
809 
810 	wl_array_init(&hmi_ctrl->ui_widgets);
811 	hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
812 	hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
813 	hmi_ctrl->compositor = ec;
814 	hmi_ctrl->screen_num = wl_list_length(&ec->output_list);
815 	hmi_ctrl->interface = interface;
816 
817 	/* init base ivi_layer*/
818 	wl_list_init(&hmi_ctrl->base_layer_list);
819 	wl_list_for_each(output, &ec->output_list, link) {
820 		base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
821 		base_layer->x = 0;
822 		base_layer->y = 0;
823 		base_layer->width = output->current_mode->width;
824 		base_layer->height = output->current_mode->height;
825 		base_layer->id_layer =
826 			hmi_ctrl->hmi_setting->base_layer_id +
827 						(i * hmi_ctrl->hmi_setting->base_layer_id_offset);
828 		wl_list_insert(&hmi_ctrl->base_layer_list, &base_layer->link);
829 
830 		create_layer(output, base_layer, hmi_ctrl);
831 		i++;
832 	}
833 
834 	i = 0;
835 	panel_height = hmi_ctrl->hmi_setting->panel_height;
836 
837 	/* init application ivi_layer */
838 	wl_list_init(&hmi_ctrl->application_layer_list);
839 	wl_list_for_each(output, &ec->output_list, link) {
840 		application_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
841 		application_layer->x = 0;
842 		application_layer->y = 0;
843 		application_layer->width = output->current_mode->width;
844 		application_layer->height = output->current_mode->height - panel_height;
845 		application_layer->id_layer =
846 			hmi_ctrl->hmi_setting->application_layer_id +
847 						(i * hmi_ctrl->hmi_setting->base_layer_id_offset);
848 		wl_list_insert(&hmi_ctrl->application_layer_list, &application_layer->link);
849 
850 		create_layer(output, application_layer, hmi_ctrl);
851 		i++;
852 	}
853 
854 	/* init workspace background ivi_layer */
855 	output = wl_container_of(ec->output_list.next, output, link);
856 	hmi_ctrl->workspace_background_output = output;
857 	hmi_ctrl->workspace_background_layer.x = 0;
858 	hmi_ctrl->workspace_background_layer.y = 0;
859 	hmi_ctrl->workspace_background_layer.width =
860 		output->current_mode->width;
861 	hmi_ctrl->workspace_background_layer.height =
862 		output->current_mode->height - panel_height;
863 
864 	hmi_ctrl->workspace_background_layer.id_layer =
865 		hmi_ctrl->hmi_setting->workspace_background_layer_id;
866 
867 	create_layer(output, &hmi_ctrl->workspace_background_layer, hmi_ctrl);
868 	hmi_ctrl->interface->layer_set_opacity(
869 		hmi_ctrl->workspace_background_layer.ivilayer, 0);
870 	hmi_ctrl->interface->layer_set_visibility(
871 		hmi_ctrl->workspace_background_layer.ivilayer, false);
872 
873 
874 	wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
875 	tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
876 	tmp_link_layer->layout_layer =
877 		hmi_ctrl->workspace_background_layer.ivilayer;
878 	wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
879 		       &tmp_link_layer->link);
880 
881 	hmi_ctrl->surface_removed.notify = set_notification_remove_surface;
882 	hmi_ctrl->interface->add_listener_remove_surface(&hmi_ctrl->surface_removed);
883 
884 	hmi_ctrl->surface_configured.notify = set_notification_configure_surface;
885 	hmi_ctrl->interface->add_listener_configure_surface(&hmi_ctrl->surface_configured);
886 
887 	hmi_ctrl->desktop_surface_configured.notify = set_notification_configure_desktop_surface;
888 	hmi_ctrl->interface->add_listener_configure_desktop_surface(&hmi_ctrl->desktop_surface_configured);
889 
890 	hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
891 	wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
892 		      &hmi_ctrl->destroy_listener);
893 
894 	return hmi_ctrl;
895 }
896 
897 /**
898  * Implementations of ivi-hmi-controller.xml
899  */
900 
901 /**
902  * A ivi_surface drawing background is identified by id_surface.
903  * Properties of the ivi_surface is set by using ivi_layout APIs according to
904  * the scene graph of UI defined in hmi_controller_create.
905  *
906  * UI ivi_layer is used to add this ivi_surface.
907  */
908 static void
ivi_hmi_controller_set_background(struct hmi_controller * hmi_ctrl,uint32_t id_surface)909 ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
910 				  uint32_t id_surface)
911 {
912 	struct ivi_layout_surface *ivisurf = NULL;
913 	struct hmi_controller_layer *base_layer = NULL;
914 	struct ivi_layout_layer   *ivilayer = NULL;
915 	int32_t dstx;
916 	int32_t dsty;
917 	int32_t width;
918 	int32_t height;
919 	int32_t ret = 0;
920 	int32_t i = 0;
921 
922 	wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
923 		uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
924 							sizeof(*add_surface_id));
925 		*add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
926 		dstx = base_layer->x;
927 		dsty = base_layer->y;
928 		width  = base_layer->width;
929 		height = base_layer->height;
930 		ivilayer = base_layer->ivilayer;
931 
932 		ivisurf = hmi_ctrl->interface->get_surface_from_id(*add_surface_id);
933 		assert(ivisurf != NULL);
934 
935 		ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
936 		assert(!ret);
937 
938 		ret = hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
939 						dstx, dsty, width, height);
940 		assert(!ret);
941 
942 		ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
943 		assert(!ret);
944 
945 		i++;
946 	}
947 }
948 
949 /**
950  * A ivi_surface drawing panel is identified by id_surface.
951  * Properties of the ivi_surface is set by using ivi_layout APIs according to
952  * the scene graph of UI defined in hmi_controller_create.
953  *
954  * UI ivi_layer is used to add this ivi_surface.
955  */
956 static void
ivi_hmi_controller_set_panel(struct hmi_controller * hmi_ctrl,uint32_t id_surface)957 ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
958 			     uint32_t id_surface)
959 {
960 	struct ivi_layout_surface *ivisurf  = NULL;
961 	struct hmi_controller_layer *base_layer;
962 	struct ivi_layout_layer   *ivilayer = NULL;
963 	int32_t width;
964 	int32_t ret = 0;
965 	int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
966 	const int32_t dstx = 0;
967 	int32_t dsty = 0;
968 	int32_t i = 0;
969 
970 	wl_list_for_each_reverse(base_layer, &hmi_ctrl->base_layer_list, link) {
971 		uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
972 							sizeof(*add_surface_id));
973 		*add_surface_id = id_surface + (i * hmi_ctrl->ui_setting.surface_id_offset);
974 
975 		ivilayer = base_layer->ivilayer;
976 		ivisurf = hmi_ctrl->interface->get_surface_from_id(*add_surface_id);
977 		assert(ivisurf != NULL);
978 
979 		ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
980 		assert(!ret);
981 
982 		dsty = base_layer->height - panel_height;
983 		width = base_layer->width;
984 
985 		ret = hmi_ctrl->interface->surface_set_destination_rectangle(
986 			ivisurf, dstx, dsty, width, panel_height);
987 		assert(!ret);
988 
989 		ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
990 		assert(!ret);
991 
992 		i++;
993 	}
994 }
995 
996 /**
997  * A ivi_surface drawing buttons in panel is identified by id_surface.
998  * It can set several buttons. Properties of the ivi_surface is set by
999  * using ivi_layout APIs according to the scene graph of UI defined in
1000  * hmi_controller_create. Additionally, the position of it is shifted to
1001  * right when new one is requested.
1002  *
1003  * UI ivi_layer is used to add these ivi_surfaces.
1004  */
1005 static void
ivi_hmi_controller_set_button(struct hmi_controller * hmi_ctrl,uint32_t id_surface,int32_t number)1006 ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
1007 			      uint32_t id_surface, int32_t number)
1008 {
1009 	struct ivi_layout_surface *ivisurf  = NULL;
1010 	struct hmi_controller_layer *base_layer =
1011 					wl_container_of(hmi_ctrl->base_layer_list.prev,
1012 							base_layer,
1013 							link);
1014 	struct ivi_layout_layer   *ivilayer = base_layer->ivilayer;
1015 	const int32_t width  = 48;
1016 	const int32_t height = 48;
1017 	int32_t ret = 0;
1018 	int32_t panel_height = 0;
1019 	int32_t dstx = 0;
1020 	int32_t dsty = 0;
1021 	uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1022 						sizeof(*add_surface_id));
1023 	*add_surface_id = id_surface;
1024 
1025 	ivisurf = hmi_ctrl->interface->get_surface_from_id(id_surface);
1026 	assert(ivisurf != NULL);
1027 
1028 	ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
1029 	assert(!ret);
1030 
1031 	panel_height = hmi_ctrl->hmi_setting->panel_height;
1032 
1033 	dstx = (60 * number) + 15;
1034 	dsty = (base_layer->height - panel_height) + 5;
1035 
1036 	ret = hmi_ctrl->interface->surface_set_destination_rectangle(
1037 		ivisurf,dstx, dsty, width, height);
1038 	assert(!ret);
1039 
1040 	ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
1041 	assert(!ret);
1042 }
1043 
1044 /**
1045  * A ivi_surface drawing home button in panel is identified by id_surface.
1046  * Properties of the ivi_surface is set by using ivi_layout APIs according to
1047  * the scene graph of UI defined in hmi_controller_create.
1048  *
1049  * UI ivi_layer is used to add these ivi_surfaces.
1050  */
1051 static void
ivi_hmi_controller_set_home_button(struct hmi_controller * hmi_ctrl,uint32_t id_surface)1052 ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
1053 				   uint32_t id_surface)
1054 {
1055 	struct ivi_layout_surface *ivisurf  = NULL;
1056 	struct hmi_controller_layer *base_layer =
1057 					wl_container_of(hmi_ctrl->base_layer_list.prev,
1058 							base_layer,
1059 							link);
1060 	struct ivi_layout_layer   *ivilayer = base_layer->ivilayer;
1061 	int32_t ret = 0;
1062 	int32_t size = 48;
1063 	int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
1064 	const int32_t dstx = (base_layer->width - size) / 2;
1065 	const int32_t dsty = (base_layer->height - panel_height) + 5;
1066 
1067 	uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1068 						sizeof(*add_surface_id));
1069 	*add_surface_id = id_surface;
1070 
1071 	ivisurf = hmi_ctrl->interface->get_surface_from_id(id_surface);
1072 	assert(ivisurf != NULL);
1073 
1074 	ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
1075 	assert(!ret);
1076 
1077 	ret = hmi_ctrl->interface->surface_set_destination_rectangle(
1078 			ivisurf, dstx, dsty, size, size);
1079 	assert(!ret);
1080 
1081 	ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
1082 	assert(!ret);
1083 }
1084 
1085 /**
1086  * A ivi_surface drawing background of workspace is identified by id_surface.
1087  * Properties of the ivi_surface is set by using ivi_layout APIs according to
1088  * the scene graph of UI defined in hmi_controller_create.
1089  *
1090  * A ivi_layer of workspace_background is used to add this ivi_surface.
1091  */
1092 static void
ivi_hmi_controller_set_workspacebackground(struct hmi_controller * hmi_ctrl,uint32_t id_surface)1093 ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
1094 					   uint32_t id_surface)
1095 {
1096 	struct ivi_layout_surface *ivisurf = NULL;
1097 	struct ivi_layout_layer   *ivilayer = NULL;
1098 	const int32_t width  = hmi_ctrl->workspace_background_layer.width;
1099 	const int32_t height = hmi_ctrl->workspace_background_layer.height;
1100 	int32_t ret = 0;
1101 
1102 	uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1103 						sizeof(*add_surface_id));
1104 	*add_surface_id = id_surface;
1105 	ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
1106 
1107 	ivisurf = hmi_ctrl->interface->get_surface_from_id(id_surface);
1108 	assert(ivisurf != NULL);
1109 
1110 	ret = hmi_ctrl->interface->layer_add_surface(ivilayer, ivisurf);
1111 	assert(!ret);
1112 
1113 	ret = hmi_ctrl->interface->surface_set_destination_rectangle(ivisurf,
1114 							   0, 0, width, height);
1115 	assert(!ret);
1116 
1117 	ret = hmi_ctrl->interface->surface_set_visibility(ivisurf, true);
1118 	assert(!ret);
1119 }
1120 
1121 /**
1122  * A list of ivi_surfaces drawing launchers in workspace is identified by
1123  * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
1124  * APIs according to the scene graph of UI defined in hmi_controller_create.
1125  *
1126  * The workspace can have several pages to group ivi_surfaces of launcher.
1127  * Each call of this interface increments a number of page to add a group
1128  * of ivi_surfaces
1129  */
1130 static void
ivi_hmi_controller_add_launchers(struct hmi_controller * hmi_ctrl,int32_t icon_size)1131 ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
1132 				 int32_t icon_size)
1133 {
1134 	int32_t minspace_x = 10;
1135 	int32_t minspace_y = minspace_x;
1136 
1137 	int32_t width  = hmi_ctrl->workspace_background_layer.width;
1138 	int32_t height = hmi_ctrl->workspace_background_layer.height;
1139 
1140 	int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
1141 	int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
1142 	float fcell_size_x = icon_size + space_x;
1143 
1144 	int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
1145 	int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
1146 	float fcell_size_y = icon_size + space_y;
1147 
1148 	struct weston_config *config = NULL;
1149 	struct weston_config_section *section = NULL;
1150 	const char *name = NULL;
1151 	int launcher_count = 0;
1152 	struct wl_array launchers;
1153 	int32_t nx = 0;
1154 	int32_t ny = 0;
1155 	int32_t prev = -1;
1156 	struct launcher_info *data = NULL;
1157 
1158 	uint32_t surfaceid = 0;
1159 	uint32_t workspaceid = 0;
1160 	struct launcher_info *info = NULL;
1161 
1162 	int32_t x = 0;
1163 	int32_t y = 0;
1164 	int32_t ret = 0;
1165 	struct ivi_layout_surface* layout_surface = NULL;
1166 	uint32_t *add_surface_id = NULL;
1167 
1168 	struct link_layer *tmp_link_layer = NULL;
1169 
1170 	if (0 == x_count)
1171 		x_count = 1;
1172 
1173 	if (0 == y_count)
1174 		y_count  = 1;
1175 
1176 	config = wet_get_config(hmi_ctrl->compositor);
1177 	if (!config)
1178 		return;
1179 
1180 	section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1181 	if (!section)
1182 		return;
1183 
1184 	wl_array_init(&launchers);
1185 
1186 	while (weston_config_next_section(config, &section, &name)) {
1187 		surfaceid = 0;
1188 		workspaceid = 0;
1189 		info = NULL;
1190 		if (0 != strcmp(name, "ivi-launcher"))
1191 			continue;
1192 
1193 		if (0 != weston_config_section_get_uint(section, "icon-id",
1194 							&surfaceid, 0))
1195 			continue;
1196 
1197 		if (0 != weston_config_section_get_uint(section,
1198 							"workspace-id",
1199 							&workspaceid, 0))
1200 			continue;
1201 
1202 		info = wl_array_add(&launchers, sizeof(*info));
1203 
1204 		if (info) {
1205 			info->surface_id = surfaceid;
1206 			info->workspace_id = workspaceid;
1207 			info->index = launcher_count;
1208 			++launcher_count;
1209 		}
1210 	}
1211 
1212 	qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
1213 	      compare_launcher_info);
1214 
1215 	wl_array_for_each(data, &launchers) {
1216 		add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
1217 					      sizeof(*add_surface_id));
1218 
1219 		*add_surface_id = data->surface_id;
1220 
1221 		if (0 > prev || (uint32_t)prev != data->workspace_id) {
1222 			nx = 0;
1223 			ny = 0;
1224 			prev = data->workspace_id;
1225 
1226 			if (0 <= prev)
1227 				hmi_ctrl->workspace_count++;
1228 		}
1229 
1230 		if (y_count == ny) {
1231 			ny = 0;
1232 			hmi_ctrl->workspace_count++;
1233 		}
1234 
1235 		x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
1236 		y = ny * fcell_size_y  + space_y;
1237 
1238 		layout_surface =
1239 			hmi_ctrl->interface->get_surface_from_id(data->surface_id);
1240 		assert(layout_surface);
1241 
1242 		ret = hmi_ctrl->interface->surface_set_destination_rectangle(
1243 				layout_surface, x, y, icon_size, icon_size);
1244 		assert(!ret);
1245 
1246 		nx++;
1247 
1248 		if (x_count == nx) {
1249 			ny++;
1250 			nx = 0;
1251 		}
1252 	}
1253 
1254 	/* init workspace ivi_layer */
1255 	hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
1256 	hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
1257 	hmi_ctrl->workspace_layer.width =
1258 		hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
1259 	hmi_ctrl->workspace_layer.height =
1260 		hmi_ctrl->workspace_background_layer.height;
1261 	hmi_ctrl->workspace_layer.id_layer =
1262 		hmi_ctrl->hmi_setting->workspace_layer_id;
1263 
1264 	create_layer(hmi_ctrl->workspace_background_output,
1265 		     &hmi_ctrl->workspace_layer, hmi_ctrl);
1266 	hmi_ctrl->interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
1267 	hmi_ctrl->interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
1268 					false);
1269 
1270 	tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
1271 	tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
1272 	wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
1273 		       &tmp_link_layer->link);
1274 
1275 	/* Add surface to layer */
1276 	wl_array_for_each(data, &launchers) {
1277 		layout_surface =
1278 			hmi_ctrl->interface->get_surface_from_id(data->surface_id);
1279 		assert(layout_surface);
1280 
1281 		ret = hmi_ctrl->interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
1282 								  layout_surface);
1283 		assert(!ret);
1284 
1285 		ret = hmi_ctrl->interface->surface_set_visibility(layout_surface, true);
1286 		assert(!ret);
1287 	}
1288 
1289 	wl_array_release(&launchers);
1290 	hmi_ctrl->interface->commit_changes();
1291 }
1292 
1293 static void
ivi_hmi_controller_UI_ready(struct wl_client * client,struct wl_resource * resource)1294 ivi_hmi_controller_UI_ready(struct wl_client *client,
1295 			    struct wl_resource *resource)
1296 {
1297 	struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1298 
1299 	ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
1300 	ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
1301 	ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
1302 	ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
1303 	ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
1304 	ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
1305 	ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
1306 	ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
1307 	hmi_ctrl->interface->commit_changes();
1308 
1309 	ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
1310 	hmi_ctrl->is_initialized = 1;
1311 }
1312 
1313 /**
1314  * Implementation of request and event of ivi_hmi_controller_workspace_control
1315  * and controlling workspace.
1316  *
1317  * When motion of input is detected in a ivi_surface of workspace background,
1318  * ivi_hmi_controller_workspace_control shall be invoked and to start
1319  * controlling of workspace. The workspace has several pages to show several
1320  * groups of applications.
1321  * The workspace is slid by using ivi-layout to select a page in layer_set_pos
1322  * according to motion. When motion finished, e.g. touch up detected, control is
1323  * terminated and event:ivi_hmi_controller_workspace_control is notified.
1324  */
1325 struct pointer_grab {
1326 	struct weston_pointer_grab grab;
1327 	struct ivi_layout_layer *layer;
1328 	struct wl_resource *resource;
1329 };
1330 
1331 struct touch_grab {
1332 	struct weston_touch_grab grab;
1333 	struct ivi_layout_layer *layer;
1334 	struct wl_resource *resource;
1335 };
1336 
1337 struct move_grab {
1338 	wl_fixed_t dst[2];
1339 	wl_fixed_t rgn[2][2];
1340 	double v[2];
1341 	struct timespec start_time;
1342 	struct timespec pre_time;
1343 	wl_fixed_t start_pos[2];
1344 	wl_fixed_t pos[2];
1345 	int32_t is_moved;
1346 };
1347 
1348 struct pointer_move_grab {
1349 	struct pointer_grab base;
1350 	struct move_grab move;
1351 };
1352 
1353 struct touch_move_grab {
1354 	struct touch_grab base;
1355 	struct move_grab move;
1356 	int32_t is_active;
1357 };
1358 
1359 static void
pointer_grab_start(struct pointer_grab * grab,struct ivi_layout_layer * layer,const struct weston_pointer_grab_interface * interface,struct weston_pointer * pointer)1360 pointer_grab_start(struct pointer_grab *grab,
1361 		   struct ivi_layout_layer *layer,
1362 		   const struct weston_pointer_grab_interface *interface,
1363 		   struct weston_pointer *pointer)
1364 {
1365 	grab->grab.interface = interface;
1366 	grab->layer = layer;
1367 	weston_pointer_start_grab(pointer, &grab->grab);
1368 }
1369 
1370 static void
touch_grab_start(struct touch_grab * grab,struct ivi_layout_layer * layer,const struct weston_touch_grab_interface * interface,struct weston_touch * touch)1371 touch_grab_start(struct touch_grab *grab,
1372 		 struct ivi_layout_layer *layer,
1373 		 const struct weston_touch_grab_interface *interface,
1374 		 struct weston_touch* touch)
1375 {
1376 	grab->grab.interface = interface;
1377 	grab->layer = layer;
1378 	weston_touch_start_grab(touch, &grab->grab);
1379 }
1380 
1381 static int32_t
clamp(int32_t val,int32_t min,int32_t max)1382 clamp(int32_t val, int32_t min, int32_t max)
1383 {
1384 	if (val < min)
1385 		return min;
1386 
1387 	if (max < val)
1388 		return max;
1389 
1390 	return val;
1391 }
1392 
1393 static void
move_workspace_grab_end(struct move_grab * move,struct wl_resource * resource,wl_fixed_t grab_x,struct ivi_layout_layer * layer)1394 move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
1395 			wl_fixed_t grab_x, struct ivi_layout_layer *layer)
1396 {
1397 	struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1398 	int32_t width = hmi_ctrl->workspace_background_layer.width;
1399 	const struct ivi_layout_layer_properties *prop;
1400 
1401 	struct timespec time = {0};
1402 	double grab_time = 0.0;
1403 	double  from_motion_time = 0.0;
1404 	double pointer_v = 0.0;
1405 	int32_t is_flick = 0;
1406 	int32_t pos_x = 0;
1407 	int32_t pos_y = 0;
1408 	int page_no = 0;
1409 	double end_pos = 0.0;
1410 	uint32_t duration = 0;
1411 
1412 	clock_gettime(CLOCK_MONOTONIC, &time);
1413 
1414 	grab_time = 1e+3 * (time.tv_sec  - move->start_time.tv_sec) +
1415 		    1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
1416 
1417 	from_motion_time = 1e+3 * (time.tv_sec  - move->pre_time.tv_sec) +
1418 			   1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
1419 
1420 	pointer_v = move->v[0];
1421 
1422 	is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
1423 	if (200 < from_motion_time)
1424 		pointer_v = 0.0;
1425 
1426 	prop = hmi_ctrl->interface->get_properties_of_layer(layer);
1427 	pos_x = prop->dest_x;
1428 	pos_y = prop->dest_y;
1429 
1430 	if (is_flick) {
1431 		int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
1432 		page_no = (-orgx + width / 2) / width;
1433 
1434 		if (pointer_v < 0.0)
1435 			page_no++;
1436 		else
1437 			page_no--;
1438 	} else {
1439 		page_no = (-pos_x + width / 2) / width;
1440 	}
1441 
1442 	page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
1443 	end_pos = -page_no * width;
1444 
1445 	duration = hmi_ctrl->hmi_setting->transition_duration;
1446 	ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
1447 	hmi_ctrl->interface->layer_set_transition(layer,
1448 					IVI_LAYOUT_TRANSITION_LAYER_MOVE,
1449 					duration);
1450 	hmi_ctrl->interface->layer_set_destination_rectangle(layer,
1451 				end_pos, pos_y,
1452 				hmi_ctrl->workspace_layer.width,
1453 				hmi_ctrl->workspace_layer.height);
1454 	hmi_ctrl->interface->commit_changes();
1455 }
1456 
1457 static void
pointer_move_workspace_grab_end(struct pointer_grab * grab)1458 pointer_move_workspace_grab_end(struct pointer_grab *grab)
1459 {
1460 	struct pointer_move_grab *pnt_move_grab =
1461 		(struct pointer_move_grab *)grab;
1462 	struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
1463 
1464 	move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
1465 				grab->grab.pointer->grab_x, layer);
1466 
1467 	weston_pointer_end_grab(grab->grab.pointer);
1468 }
1469 
1470 static void
touch_move_workspace_grab_end(struct touch_grab * grab)1471 touch_move_workspace_grab_end(struct touch_grab *grab)
1472 {
1473 	struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1474 	struct ivi_layout_layer *layer = tch_move_grab->base.layer;
1475 
1476 	move_workspace_grab_end(&tch_move_grab->move, grab->resource,
1477 				grab->grab.touch->grab_x, layer);
1478 
1479 	weston_touch_end_grab(grab->grab.touch);
1480 }
1481 
1482 static void
pointer_noop_grab_focus(struct weston_pointer_grab * grab)1483 pointer_noop_grab_focus(struct weston_pointer_grab *grab)
1484 {
1485 }
1486 
1487 static void
pointer_default_grab_axis(struct weston_pointer_grab * grab,const struct timespec * time,struct weston_pointer_axis_event * event)1488 pointer_default_grab_axis(struct weston_pointer_grab *grab,
1489 			  const struct timespec *time,
1490 			  struct weston_pointer_axis_event *event)
1491 {
1492 	weston_pointer_send_axis(grab->pointer, time, event);
1493 }
1494 
1495 static void
pointer_default_grab_axis_source(struct weston_pointer_grab * grab,uint32_t source)1496 pointer_default_grab_axis_source(struct weston_pointer_grab *grab,
1497 				 uint32_t source)
1498 {
1499 	weston_pointer_send_axis_source(grab->pointer, source);
1500 }
1501 
1502 static void
pointer_default_grab_frame(struct weston_pointer_grab * grab)1503 pointer_default_grab_frame(struct weston_pointer_grab *grab)
1504 {
1505 	weston_pointer_send_frame(grab->pointer);
1506 }
1507 
1508 static void
move_grab_update(struct move_grab * move,wl_fixed_t pointer[2])1509 move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
1510 {
1511 	struct timespec timestamp = {0};
1512 	int32_t ii = 0;
1513 	double dt = 0.0;
1514 
1515 	clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
1516 	dt = (1e+3 * (timestamp.tv_sec  - move->pre_time.tv_sec) +
1517 	      1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
1518 
1519 	if (dt < 1e-6)
1520 		dt = 1e-6;
1521 
1522 	move->pre_time = timestamp;
1523 
1524 	for (ii = 0; ii < 2; ii++) {
1525 		wl_fixed_t prepos = move->pos[ii];
1526 		move->pos[ii] = pointer[ii] + move->dst[ii];
1527 
1528 		if (move->pos[ii] < move->rgn[0][ii]) {
1529 			move->pos[ii] = move->rgn[0][ii];
1530 			move->dst[ii] = move->pos[ii] - pointer[ii];
1531 		} else if (move->rgn[1][ii] < move->pos[ii]) {
1532 			move->pos[ii] = move->rgn[1][ii];
1533 			move->dst[ii] = move->pos[ii] - pointer[ii];
1534 		}
1535 
1536 		move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
1537 
1538 		if (!move->is_moved &&
1539 		    0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
1540 			move->is_moved = 1;
1541 	}
1542 }
1543 
1544 static void
layer_set_pos(struct hmi_controller * hmi_ctrl,struct ivi_layout_layer * layer,wl_fixed_t pos_x,wl_fixed_t pos_y)1545 layer_set_pos(struct hmi_controller *hmi_ctrl, struct ivi_layout_layer *layer,
1546 	      wl_fixed_t pos_x, wl_fixed_t pos_y)
1547 {
1548 	const struct ivi_layout_layer_properties *prop;
1549 	int32_t layout_pos_x = 0;
1550 	int32_t layout_pos_y = 0;
1551 
1552 	prop = hmi_ctrl->interface->get_properties_of_layer(layer);
1553 
1554 	layout_pos_x = wl_fixed_to_int(pos_x);
1555 	layout_pos_y = wl_fixed_to_int(pos_y);
1556 	hmi_ctrl->interface->layer_set_destination_rectangle(layer,
1557 			layout_pos_x, layout_pos_y, prop->dest_width, prop->dest_height);
1558 	hmi_ctrl->interface->commit_changes();
1559 }
1560 
1561 static void
pointer_move_grab_motion(struct weston_pointer_grab * grab,const struct timespec * time,struct weston_pointer_motion_event * event)1562 pointer_move_grab_motion(struct weston_pointer_grab *grab,
1563 			 const struct timespec *time,
1564 			 struct weston_pointer_motion_event *event)
1565 {
1566 	struct pointer_move_grab *pnt_move_grab =
1567 		(struct pointer_move_grab *)grab;
1568 	struct hmi_controller *hmi_ctrl =
1569 			wl_resource_get_user_data(pnt_move_grab->base.resource);
1570 	wl_fixed_t pointer_pos[2];
1571 
1572 	weston_pointer_motion_to_abs(grab->pointer, event,
1573 				     &pointer_pos[0], &pointer_pos[1]);
1574 	move_grab_update(&pnt_move_grab->move, pointer_pos);
1575 	layer_set_pos(hmi_ctrl, pnt_move_grab->base.layer,
1576 		      pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
1577 	weston_pointer_move(pnt_move_grab->base.grab.pointer, event);
1578 }
1579 
1580 static void
touch_move_grab_motion(struct weston_touch_grab * grab,const struct timespec * time,int touch_id,wl_fixed_t x,wl_fixed_t y)1581 touch_move_grab_motion(struct weston_touch_grab *grab,
1582 		       const struct timespec *time, int touch_id,
1583 		       wl_fixed_t x, wl_fixed_t y)
1584 {
1585 	struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1586 	struct hmi_controller *hmi_ctrl =
1587 			wl_resource_get_user_data(tch_move_grab->base.resource);
1588 
1589 	if (!tch_move_grab->is_active)
1590 		return;
1591 
1592 	wl_fixed_t pointer_pos[2] = {
1593 		grab->touch->grab_x,
1594 		grab->touch->grab_y
1595 	};
1596 
1597 	move_grab_update(&tch_move_grab->move, pointer_pos);
1598 	layer_set_pos(hmi_ctrl, tch_move_grab->base.layer,
1599 		      tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
1600 }
1601 
1602 static void
pointer_move_workspace_grab_button(struct weston_pointer_grab * grab,const struct timespec * time,uint32_t button,uint32_t state_w)1603 pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
1604 				   const struct timespec *time, uint32_t button,
1605 				   uint32_t state_w)
1606 {
1607 	if (BTN_LEFT == button &&
1608 	    WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
1609 		struct pointer_grab *pg = (struct pointer_grab *)grab;
1610 
1611 		pointer_move_workspace_grab_end(pg);
1612 		free(grab);
1613 	}
1614 }
1615 
1616 static void
touch_nope_grab_down(struct weston_touch_grab * grab,const struct timespec * time,int touch_id,wl_fixed_t sx,wl_fixed_t sy)1617 touch_nope_grab_down(struct weston_touch_grab *grab,
1618 		     const struct timespec *time,
1619 		     int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1620 {
1621 }
1622 
1623 static void
touch_move_workspace_grab_up(struct weston_touch_grab * grab,const struct timespec * time,int touch_id)1624 touch_move_workspace_grab_up(struct weston_touch_grab *grab,
1625 			     const struct timespec *time,
1626 			     int touch_id)
1627 {
1628 	struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
1629 
1630 	if (0 == touch_id)
1631 		tch_move_grab->is_active = 0;
1632 
1633 	if (0 == grab->touch->num_tp) {
1634 		touch_move_workspace_grab_end(&tch_move_grab->base);
1635 		free(grab);
1636 	}
1637 }
1638 
1639 static void
pointer_move_workspace_grab_cancel(struct weston_pointer_grab * grab)1640 pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
1641 {
1642 	struct pointer_grab *pg = (struct pointer_grab *)grab;
1643 
1644 	pointer_move_workspace_grab_end(pg);
1645 	free(grab);
1646 }
1647 
1648 static void
touch_move_workspace_grab_frame(struct weston_touch_grab * grab)1649 touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
1650 {
1651 }
1652 
1653 static void
touch_move_workspace_grab_cancel(struct weston_touch_grab * grab)1654 touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
1655 {
1656 	struct touch_grab *tg = (struct touch_grab *)grab;
1657 
1658 	touch_move_workspace_grab_end(tg);
1659 	free(grab);
1660 }
1661 
1662 static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
1663 	pointer_noop_grab_focus,
1664 	pointer_move_grab_motion,
1665 	pointer_move_workspace_grab_button,
1666 	pointer_default_grab_axis,
1667 	pointer_default_grab_axis_source,
1668 	pointer_default_grab_frame,
1669 	pointer_move_workspace_grab_cancel
1670 };
1671 
1672 static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
1673 	touch_nope_grab_down,
1674 	touch_move_workspace_grab_up,
1675 	touch_move_grab_motion,
1676 	touch_move_workspace_grab_frame,
1677 	touch_move_workspace_grab_cancel
1678 };
1679 
1680 enum HMI_GRAB_DEVICE {
1681 	HMI_GRAB_DEVICE_NONE,
1682 	HMI_GRAB_DEVICE_POINTER,
1683 	HMI_GRAB_DEVICE_TOUCH
1684 };
1685 
1686 static enum HMI_GRAB_DEVICE
get_hmi_grab_device(struct weston_seat * seat,uint32_t serial)1687 get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
1688 {
1689 	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1690 	struct weston_touch *touch = weston_seat_get_touch(seat);
1691 
1692 	if (pointer &&
1693 	    pointer->focus &&
1694 	    pointer->button_count &&
1695 	    pointer->grab_serial == serial)
1696 		return HMI_GRAB_DEVICE_POINTER;
1697 
1698 	if (touch &&
1699 	    touch->focus &&
1700 	    touch->grab_serial == serial)
1701 		return HMI_GRAB_DEVICE_TOUCH;
1702 
1703 	return HMI_GRAB_DEVICE_NONE;
1704 }
1705 
1706 static void
move_grab_init(struct move_grab * move,wl_fixed_t start_pos[2],wl_fixed_t grab_pos[2],wl_fixed_t rgn[2][2],struct wl_resource * resource)1707 move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
1708 	       wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
1709 	       struct wl_resource* resource)
1710 {
1711 	clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
1712 	move->pre_time = move->start_time;
1713 	move->pos[0] = start_pos[0];
1714 	move->pos[1] = start_pos[1];
1715 	move->start_pos[0] = start_pos[0];
1716 	move->start_pos[1] = start_pos[1];
1717 	move->dst[0] = start_pos[0] - grab_pos[0];
1718 	move->dst[1] = start_pos[1] - grab_pos[1];
1719 	memcpy(move->rgn, rgn, sizeof(move->rgn));
1720 }
1721 
1722 static void
move_grab_init_workspace(struct move_grab * move,wl_fixed_t grab_x,wl_fixed_t grab_y,struct wl_resource * resource)1723 move_grab_init_workspace(struct move_grab* move,
1724 			 wl_fixed_t grab_x, wl_fixed_t grab_y,
1725 			 struct wl_resource *resource)
1726 {
1727 	struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1728 	struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
1729 	const struct ivi_layout_layer_properties *prop;
1730 	int32_t workspace_count = hmi_ctrl->workspace_count;
1731 	int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
1732 	int32_t layer_pos_x = 0;
1733 	int32_t layer_pos_y = 0;
1734 	wl_fixed_t start_pos[2] = {0};
1735 	wl_fixed_t rgn[2][2] = {{0}};
1736 	wl_fixed_t grab_pos[2] = { grab_x, grab_y };
1737 
1738 	prop = hmi_ctrl->interface->get_properties_of_layer(layer);
1739 	layer_pos_x = prop->dest_x;
1740 	layer_pos_y = prop->dest_y;
1741 
1742 	start_pos[0] = wl_fixed_from_int(layer_pos_x);
1743 	start_pos[1] = wl_fixed_from_int(layer_pos_y);
1744 
1745 	rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
1746 
1747 	rgn[0][1] = wl_fixed_from_int(0);
1748 	rgn[1][0] = wl_fixed_from_int(0);
1749 	rgn[1][1] = wl_fixed_from_int(0);
1750 
1751 	move_grab_init(move, start_pos, grab_pos, rgn, resource);
1752 }
1753 
1754 static struct pointer_move_grab *
create_workspace_pointer_move(struct weston_pointer * pointer,struct wl_resource * resource)1755 create_workspace_pointer_move(struct weston_pointer *pointer,
1756 			      struct wl_resource* resource)
1757 {
1758 	struct pointer_move_grab *pnt_move_grab =
1759 		MEM_ALLOC(sizeof(*pnt_move_grab));
1760 
1761 	pnt_move_grab->base.resource = resource;
1762 	move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
1763 				 pointer->grab_y, resource);
1764 
1765 	return pnt_move_grab;
1766 }
1767 
1768 static struct touch_move_grab *
create_workspace_touch_move(struct weston_touch * touch,struct wl_resource * resource)1769 create_workspace_touch_move(struct weston_touch *touch,
1770 			    struct wl_resource* resource)
1771 {
1772 	struct touch_move_grab *tch_move_grab =
1773 		MEM_ALLOC(sizeof(*tch_move_grab));
1774 
1775 	tch_move_grab->base.resource = resource;
1776 	tch_move_grab->is_active = 1;
1777 	move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
1778 				 touch->grab_y, resource);
1779 
1780 	return tch_move_grab;
1781 }
1782 
1783 static void
ivi_hmi_controller_workspace_control(struct wl_client * client,struct wl_resource * resource,struct wl_resource * seat_resource,uint32_t serial)1784 ivi_hmi_controller_workspace_control(struct wl_client *client,
1785 				     struct wl_resource *resource,
1786 				     struct wl_resource *seat_resource,
1787 				     uint32_t serial)
1788 {
1789 	struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1790 	struct ivi_layout_layer *layer = NULL;
1791 	struct pointer_move_grab *pnt_move_grab = NULL;
1792 	struct touch_move_grab *tch_move_grab = NULL;
1793 	struct weston_seat *seat = NULL;
1794 	struct weston_pointer *pointer;
1795 	struct weston_touch *touch;
1796 
1797 	enum HMI_GRAB_DEVICE device;
1798 
1799 	if (hmi_ctrl->workspace_count < 2)
1800 		return;
1801 
1802 	seat = wl_resource_get_user_data(seat_resource);
1803 	device = get_hmi_grab_device(seat, serial);
1804 
1805 	if (HMI_GRAB_DEVICE_POINTER != device &&
1806 	    HMI_GRAB_DEVICE_TOUCH != device)
1807 		return;
1808 
1809 	layer = hmi_ctrl->workspace_layer.ivilayer;
1810 
1811 	hmi_ctrl->interface->transition_move_layer_cancel(layer);
1812 
1813 	switch (device) {
1814 	case HMI_GRAB_DEVICE_POINTER:
1815 		pointer = weston_seat_get_pointer(seat);
1816 		pnt_move_grab = create_workspace_pointer_move(pointer,
1817 							      resource);
1818 
1819 		pointer_grab_start(&pnt_move_grab->base, layer,
1820 				   &pointer_move_grab_workspace_interface,
1821 				   pointer);
1822 		break;
1823 
1824 	case HMI_GRAB_DEVICE_TOUCH:
1825 		touch = weston_seat_get_touch(seat);
1826 		tch_move_grab = create_workspace_touch_move(touch,
1827 							    resource);
1828 
1829 		touch_grab_start(&tch_move_grab->base, layer,
1830 				 &touch_move_grab_workspace_interface,
1831 				 touch);
1832 		break;
1833 
1834 	default:
1835 		break;
1836 	}
1837 }
1838 
1839 /**
1840  * Implementation of switch_mode
1841  */
1842 static void
ivi_hmi_controller_switch_mode(struct wl_client * client,struct wl_resource * resource,uint32_t layout_mode)1843 ivi_hmi_controller_switch_mode(struct wl_client *client,
1844 			       struct wl_resource *resource,
1845 			       uint32_t  layout_mode)
1846 {
1847 	struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1848 
1849 	switch_mode(hmi_ctrl, layout_mode);
1850 }
1851 
1852 /**
1853  * Implementation of on/off displaying workspace and workspace background
1854  * ivi_layers.
1855  */
1856 static void
ivi_hmi_controller_home(struct wl_client * client,struct wl_resource * resource,uint32_t home)1857 ivi_hmi_controller_home(struct wl_client *client,
1858 			struct wl_resource *resource,
1859 			uint32_t home)
1860 {
1861 	struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
1862 	uint32_t is_fade_in;
1863 
1864 	if ((IVI_HMI_CONTROLLER_HOME_ON  == home &&
1865 	     !hmi_ctrl->workspace_fade.is_fade_in) ||
1866 	    (IVI_HMI_CONTROLLER_HOME_OFF == home &&
1867 	     hmi_ctrl->workspace_fade.is_fade_in)) {
1868 		is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
1869 		hmi_controller_fade_run(hmi_ctrl, is_fade_in,
1870 					&hmi_ctrl->workspace_fade);
1871 	}
1872 
1873 	hmi_ctrl->interface->commit_changes();
1874 }
1875 
1876 /**
1877  * binding ivi-hmi-controller implementation
1878  */
1879 static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
1880 	ivi_hmi_controller_UI_ready,
1881 	ivi_hmi_controller_workspace_control,
1882 	ivi_hmi_controller_switch_mode,
1883 	ivi_hmi_controller_home
1884 };
1885 
1886 static void
unbind_hmi_controller(struct wl_resource * resource)1887 unbind_hmi_controller(struct wl_resource *resource)
1888 {
1889 }
1890 
1891 static void
bind_hmi_controller(struct wl_client * client,void * data,uint32_t version,uint32_t id)1892 bind_hmi_controller(struct wl_client *client,
1893 		    void *data, uint32_t version, uint32_t id)
1894 {
1895 	struct wl_resource *resource = NULL;
1896 	struct hmi_controller *hmi_ctrl = data;
1897 
1898 	if (hmi_ctrl->user_interface != client) {
1899 		struct wl_resource *res = wl_client_get_object(client, 1);
1900 		wl_resource_post_error(res,
1901 				WL_DISPLAY_ERROR_INVALID_OBJECT,
1902 				"hmi-controller failed: permission denied");
1903 		return;
1904 	}
1905 
1906 	resource = wl_resource_create(
1907 		client, &ivi_hmi_controller_interface, 1, id);
1908 
1909 	wl_resource_set_implementation(
1910 		resource, &ivi_hmi_controller_implementation,
1911 		hmi_ctrl, unbind_hmi_controller);
1912 }
1913 
1914 static int32_t
initialize(struct hmi_controller * hmi_ctrl)1915 initialize(struct hmi_controller *hmi_ctrl)
1916 {
1917 	struct config_command {
1918 		char *key;
1919 		uint32_t *dest;
1920 	};
1921 
1922 	struct weston_config *config = wet_get_config(hmi_ctrl->compositor);
1923 	struct weston_config_section *section = NULL;
1924 	int result = 0;
1925 	int i = 0;
1926 
1927 	const struct config_command uint_commands[] = {
1928 		{ "background-id", &hmi_ctrl->ui_setting.background_id },
1929 		{ "panel-id", &hmi_ctrl->ui_setting.panel_id },
1930 		{ "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
1931 		{ "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
1932 		{ "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
1933 		{ "random-id", &hmi_ctrl->ui_setting.random_id },
1934 		{ "home-id", &hmi_ctrl->ui_setting.home_id },
1935 		{ "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
1936 		{ "surface-id-offset", &hmi_ctrl->ui_setting.surface_id_offset },
1937 		{ NULL, NULL }
1938 	};
1939 
1940 	section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
1941 
1942 	for (i = 0; -1 != result; ++i) {
1943 		const struct config_command *command = &uint_commands[i];
1944 
1945 		if (!command->key)
1946 			break;
1947 
1948 		if (weston_config_section_get_uint(
1949 					section, command->key, command->dest, 0) != 0)
1950 			result = -1;
1951 	}
1952 
1953 	if (-1 == result) {
1954 		weston_log("Failed to initialize hmi-controller\n");
1955 		return 0;
1956 	}
1957 
1958 	return 1;
1959 }
1960 
1961 static void
launch_hmi_client_process(void * data)1962 launch_hmi_client_process(void *data)
1963 {
1964 	struct hmi_controller *hmi_ctrl =
1965 		(struct hmi_controller *)data;
1966 
1967 	hmi_ctrl->user_interface =
1968 		weston_client_start(hmi_ctrl->compositor,
1969 				    hmi_ctrl->hmi_setting->ivi_homescreen);
1970 
1971 	free(hmi_ctrl->hmi_setting->ivi_homescreen);
1972 }
1973 
1974 /*****************************************************************************
1975  *  exported functions
1976  ****************************************************************************/
1977 WL_EXPORT int
wet_module_init(struct weston_compositor * ec,int * argc,char * argv[])1978 wet_module_init(struct weston_compositor *ec,
1979 		       int *argc, char *argv[])
1980 {
1981 	struct hmi_controller *hmi_ctrl = NULL;
1982 	struct wl_event_loop *loop = NULL;
1983 
1984 	/* ad hoc weston_compositor_add_destroy_listener_once() */
1985 	if (wl_signal_get(&ec->destroy_signal, hmi_controller_destroy))
1986 		return 0;
1987 
1988 	hmi_ctrl = hmi_controller_create(ec);
1989 	if (hmi_ctrl == NULL)
1990 		return -1;
1991 
1992 	if (!initialize(hmi_ctrl)) {
1993 		return -1;
1994 	}
1995 
1996 	if (wl_global_create(ec->wl_display,
1997 			     &ivi_hmi_controller_interface, 1,
1998 			     hmi_ctrl, bind_hmi_controller) == NULL) {
1999 		return -1;
2000 	}
2001 
2002 	loop = wl_display_get_event_loop(ec->wl_display);
2003 	wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
2004 
2005 	return 0;
2006 }
2007