Update GENIVI Audio Manager to 7.4 for CES2017 demo.
[AGL/meta-agl.git] / meta-agl-bsp / meta-ti / recipes-arago / weston / weston / 0008-ivi-shell-Add-simple-IVI-shell-layout-controller.patch
1 From c89c2d63db3cbe83fb1ddd983e4b0ffe87fab296 Mon Sep 17 00:00:00 2001
2 From: Volodymyr Riazantsev <volodymyr.riazantsev@globallogic.com>
3 Date: Fri, 1 Jul 2016 00:28:50 -0400
4 Subject: [PATCH 8/8] ivi-shell: Add simple IVI shell layout controller
5
6 Simple IVI shell layout controller.
7 Assign only one application to primary display.
8 Second and rest application will go to secondary display if it's
9 present.
10
11 Signed-off-by: Volodymyr Riazantsev <volodymyr.riazantsev@globallogic.com>
12 Signed-off-by: Karthik Ramanan <a0393906@ti.com>
13 ---
14  Makefile.am                          |  12 +-
15  ivi-shell/ivi-layout-controller-ti.c | 532 +++++++++++++++++++++++++++++++++++
16  2 files changed, 543 insertions(+), 1 deletion(-)
17  create mode 100644 ivi-shell/ivi-layout-controller-ti.c
18
19 diff --git a/Makefile.am b/Makefile.am
20 index 55aed6d..a9fe3c8 100644
21 --- a/Makefile.am
22 +++ b/Makefile.am
23 @@ -868,7 +868,8 @@ if ENABLE_IVI_SHELL
24  
25  module_LTLIBRARIES +=                          \
26         $(ivi_shell)                            \
27 -       $(hmi_controller)
28 +       $(hmi_controller)                       \
29 +       $(layout_controller)
30  
31  ivi_shell = ivi-shell.la
32  ivi_shell_la_LDFLAGS = -module -avoid-version
33 @@ -903,6 +904,15 @@ nodist_hmi_controller_la_SOURCES =                 \
34  
35  BUILT_SOURCES += $(nodist_hmi_controller_la_SOURCES)
36  
37 +layout_controller = layout-controller.la
38 +layout_controller_la_LDFLAGS = -module -avoid-version
39 +layout_controller_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la
40 +layout_controller_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS)
41 +layout_controller_la_SOURCES =                         \
42 +       ivi-shell/ivi-layout-export.h                   \
43 +       ivi-shell/ivi-layout-controller-ti.c            \
44 +       shared/helpers.h
45 +
46  endif
47  
48  
49 diff --git a/ivi-shell/ivi-layout-controller-ti.c b/ivi-shell/ivi-layout-controller-ti.c
50 new file mode 100644
51 index 0000000..b7cf436
52 --- /dev/null
53 +++ b/ivi-shell/ivi-layout-controller-ti.c
54 @@ -0,0 +1,532 @@
55 +/*
56 + * Copyright (C) 2016 GlobalLogic Inc
57 + *
58 + * Permission is hereby granted, free of charge, to any person obtaining
59 + * a copy of this software and associated documentation files (the
60 + * "Software"), to deal in the Software without restriction, including
61 + * without limitation the rights to use, copy, modify, merge, publish,
62 + * distribute, sublicense, and/or sell copies of the Software, and to
63 + * permit persons to whom the Software is furnished to do so, subject to
64 + * the following conditions:
65 + *
66 + * The above copyright notice and this permission notice (including the
67 + * next paragraph) shall be included in all copies or substantial
68 + * portions of the Software.
69 + *
70 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
71 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
72 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
73 + * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
74 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
75 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
76 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
77 + * SOFTWARE.
78 + */
79 +
80 +#include <stdlib.h>
81 +#include <string.h>
82 +#include <assert.h>
83 +
84 +#include "ivi-layout-export.h"
85 +
86 +#ifndef container_of
87 +#define container_of(ptr, type, member) ({                              \
88 +        const __typeof__( ((type *)0)->member ) *__mptr = (ptr);        \
89 +        (type *)( (char *)__mptr - offsetof(type,member) );})
90 +#endif
91 +
92 +#ifndef BIT
93 +#define BIT(bit)       (1 << (bit))
94 +#endif
95 +
96 +#define __MODULE__ "layout-controller"
97 +#define DL_ERR BIT(0)
98 +#define DL_WRN BIT(1)
99 +#define DL_DBG BIT(2)
100 +#define DL_ALL (~0)
101 +
102 +static unsigned debug_level = DL_ALL;
103 +
104 +#define __print_log(__dl__, ... ) \
105 +if (__dl__ & debug_level) \
106 +               fprintf(__dl__ == DL_ERR ? stderr : stdout," ["__MODULE__"]:" __VA_ARGS__);
107 +
108 +#define pr_err(...) __print_log(DL_ERR, "E: " __VA_ARGS__)
109 +#define pr_dbg(...) __print_log(DL_DBG, "D: " __VA_ARGS__)
110 +#define pr_wrn(...) __print_log(DL_WRN, "W: " __VA_ARGS__)
111 +#define TRACE() __print_log(DL_DBG, "TR: %s - %d\n", __func__, __LINE__)
112 +
113 +
114 +#define WINDOWS_TITLE_HEIGHT 30
115 +#define DEFAULT_SURFACE_ID_FOR_WL_SHELL_APP 0x80000000
116 +
117 +/*****************************************************************************
118 + *  structure, globals
119 + ****************************************************************************/
120 +struct hmi_controller_layer {
121 +       struct ivi_layout_layer *ivilayer;
122 +       uint32_t id_layer;
123 +       int32_t x;
124 +       int32_t y;
125 +       int32_t width;
126 +       int32_t height;
127 +       int32_t num_surfaces;
128 +       pid_t pid;
129 +       struct wl_list link;
130 +       struct wl_list screen_link;
131 +       struct wl_list surfaces_list;
132 +};
133 +
134 +struct hmi_controller_surface {
135 +       void               *controller;
136 +       void               *ivisurf;
137 +       struct wl_list     link;
138 +       struct wl_listener destroy_listener;
139 +};
140 +
141 +struct hmi_controller_screen {
142 +       struct ivi_layout_screen *iviscrn;
143 +       struct wl_list layers_list;
144 +};
145 +
146 +struct hmi_server_setting {
147 +       uint32_t    base_layer_id;
148 +       int32_t     panel_height;
149 +       char       *ivi_homescreen;
150 +};
151 +
152 +struct hmi_controller {
153 +       int32_t                             current_layer;
154 +       int32_t                             current_screen;
155 +       int32_t                             screens_count;
156 +       int32_t                             workspace_count;
157 +
158 +       struct hmi_server_setting          *hmi_setting;
159 +       struct hmi_controller_screen        screens[4];
160 +       struct hmi_controller_layer         application_layer;
161 +       struct weston_compositor           *compositor;
162 +       struct wl_listener                  destroy_listener;
163 +       struct wl_client                   *user_interface;
164 +       struct wl_list                      layers_list;
165 +};
166 +
167 +const struct ivi_controller_interface *ivi_controller_interface;
168 +
169 +static void
170 +hmi_ctrl_surface_destroy(struct wl_listener *listener, void *data);
171 +
172 +int
173 +controller_module_init(struct weston_compositor *ec,
174 +                      int *argc, char *argv[],
175 +                      const struct ivi_controller_interface *interface,
176 +                      size_t interface_version);
177 +
178 +/*****************************************************************************
179 + *  local functions
180 + ****************************************************************************/
181 +static void *
182 +fail_on_null(void *p, size_t size, char *file, int32_t line)
183 +{
184 +       if (size && !p) {
185 +               weston_log("%s(%d) %zd: out of memory\n", file, line, size);
186 +               exit(EXIT_FAILURE);
187 +       }
188 +
189 +       return p;
190 +}
191 +
192 +static void *
193 +mem_alloc(size_t size, char *file, int32_t line)
194 +{
195 +       return fail_on_null(calloc(1, size), size, file, line);
196 +}
197 +
198 +#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
199 +
200 +/**
201 + * Internal method to create ivi_layer with hmi_controller_layer and
202 + * add to a ivi_screen
203 + */
204 +static void
205 +create_layer(struct ivi_layout_screen *iviscrn,
206 +            struct hmi_controller_layer *layer)
207 +{
208 +       int32_t ret = 0;
209 +
210 +       layer->ivilayer =
211 +               ivi_controller_interface->layer_create_with_dimension(layer->id_layer,
212 +                                                      layer->width,
213 +                                                      layer->height);
214 +       assert(layer->ivilayer != NULL);
215 +
216 +       ret = ivi_controller_interface->screen_add_layer(iviscrn, layer->ivilayer);
217 +
218 +       assert(!ret);
219 +
220 +       ret = ivi_controller_interface->layer_set_destination_rectangle(layer->ivilayer,
221 +                                                        layer->x, layer->y,
222 +                                                        layer->width,
223 +                                                        layer->height);
224 +       assert(!ret);
225 +
226 +       ret = ivi_controller_interface->layer_set_visibility(layer->ivilayer, true);
227 +
228 +       assert(!ret);
229 +
230 +       ivi_controller_interface->commit_changes();
231 +
232 +}
233 +
234 +static struct hmi_controller_layer
235 +*get_layer_for_surface(struct hmi_controller *hmi_ctrl
236 +                       , struct ivi_layout_surface *ivisurf
237 +                       , bool create)
238 +{
239 +       struct hmi_controller_layer *layer;
240 +       struct weston_surface *surface;
241 +       int32_t i = 0;
242 +       struct wl_client *client;
243 +       struct ivi_layout_screen *iviscrn  = NULL;
244 +       struct weston_output *output = NULL;
245 +       pid_t pid;
246 +       uid_t uid;
247 +       gid_t gid;
248 +
249 +       surface = ivi_controller_interface->surface_get_weston_surface(ivisurf);
250 +
251 +       if (!surface)
252 +               goto exit;
253 +
254 +       client = wl_resource_get_client(surface->resource);
255 +
256 +       wl_client_get_credentials(client, &pid, &uid, &gid);
257 +
258 +       wl_list_for_each(layer, &hmi_ctrl->layers_list, link) {
259 +               if (layer->pid == pid) {
260 +                       pr_dbg("Existed layer for PID=%d was found\n", pid);
261 +                       return layer;
262 +               }
263 +       }
264 +
265 +       if (!(create && hmi_ctrl->screens_count))
266 +               goto exit;
267 +
268 +       pr_dbg("Existed layer for PID=%d was not found. Creating new\n", pid);
269 +
270 +       for(;; i++) {
271 +               if (wl_list_empty(&hmi_ctrl->screens[i].layers_list) ||
272 +                               (i == (hmi_ctrl->screens_count - 1)))
273 +                       break;
274 +       };
275 +
276 +       iviscrn = hmi_ctrl->screens[i].iviscrn;
277 +
278 +       layer = calloc(1, sizeof *layer);
279 +
280 +       output = ivi_controller_interface->screen_get_output(iviscrn);
281 +
282 +       wl_list_init(&layer->link);
283 +       wl_list_init(&layer->screen_link);
284 +       wl_list_init(&layer->surfaces_list);
285 +
286 +       layer->width = output->width;
287 +       layer->height = output->height + WINDOWS_TITLE_HEIGHT;
288 +       layer->id_layer = hmi_ctrl->hmi_setting->base_layer_id++;
289 +       layer->pid = pid;
290 +
291 +       create_layer(iviscrn, layer);
292 +
293 +       wl_list_insert(&hmi_ctrl->layers_list, &layer->link);
294 +       wl_list_insert(&hmi_ctrl->screens[i].layers_list, &layer->screen_link);
295 +
296 +       return layer;
297 +
298 +exit:
299 +       return NULL;
300 +}
301 +
302 +static void
303 +set_notification_create_surface(struct ivi_layout_surface *ivisurf,
304 +                               void *userdata)
305 +{
306 +       struct hmi_controller *hmi_ctrl = userdata;
307 +       struct hmi_controller_layer *hmi_ctrl_layer = NULL;
308 +       struct hmi_controller_surface *hmi_ctrl_surf = NULL;
309 +       struct ivi_layout_layer *dest_layer;
310 +       struct weston_surface *surface;
311 +
312 +       wl_list_for_each(hmi_ctrl_layer, &hmi_ctrl->layers_list, link) {
313 +               wl_list_for_each(hmi_ctrl_surf, &hmi_ctrl_layer->surfaces_list, link) {
314 +                       if (hmi_ctrl_surf->ivisurf == ivisurf) {
315 +                               pr_dbg("Surface was already configured. Skip add to list\n");
316 +                               return;
317 +                       }
318 +               }
319 +       }
320 +
321 +       pr_dbg("Surface create: add to list and get the layer\n");
322 +
323 +       hmi_ctrl_layer = get_layer_for_surface(hmi_ctrl, ivisurf, true);
324 +       dest_layer = hmi_ctrl_layer->ivilayer;
325 +
326 +       ivi_controller_interface->layer_add_surface(dest_layer, ivisurf);
327 +
328 +       hmi_ctrl_surf = calloc(1, sizeof(*hmi_ctrl_surf));
329 +       hmi_ctrl_surf->ivisurf = ivisurf;
330 +       wl_list_init(&hmi_ctrl_surf->link);
331 +       wl_list_insert(&hmi_ctrl_layer->surfaces_list, &hmi_ctrl_surf->link);
332 +
333 +
334 +       /*
335 +        * Set destroy signal for surface
336 +        * HACK: We trying to track surfaces were created by wl_shell_emulator
337 +        */
338 +       if (ivi_controller_interface->get_id_of_surface(ivisurf) >=
339 +                       DEFAULT_SURFACE_ID_FOR_WL_SHELL_APP) {
340 +               surface = ivi_controller_interface->surface_get_weston_surface(ivisurf);
341 +               hmi_ctrl_surf->destroy_listener.notify = hmi_ctrl_surface_destroy;
342 +               wl_signal_add(&surface->destroy_signal, &hmi_ctrl_surf->destroy_listener);
343 +               hmi_ctrl_surf->controller = userdata;
344 +       }
345 +}
346 +
347 +static void
348 +set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
349 +                               void *userdata)
350 +{
351 +       struct hmi_controller *hmi_ctrl = userdata;
352 +       struct hmi_controller_layer *hmi_ctrl_layer = NULL;
353 +       struct hmi_controller_surface *surf = NULL;
354 +       struct ivi_layout_layer *dest_layer;
355 +
356 +       wl_list_for_each(hmi_ctrl_layer, &hmi_ctrl->layers_list, link) {
357 +               wl_list_for_each(surf, &hmi_ctrl_layer->surfaces_list, link) {
358 +                       if (surf->ivisurf == ivisurf) {
359 +                               pr_dbg("Surface remove: surface was found\n");
360 +                               goto remove;
361 +                       }
362 +               }
363 +       }
364 +
365 +       goto exit;
366 +
367 +remove:
368 +       dest_layer = hmi_ctrl_layer->ivilayer;
369 +
370 +       wl_list_remove(&surf->link);
371 +
372 +       ivi_controller_interface->layer_remove_surface(dest_layer, ivisurf);
373 +
374 +       if (wl_list_empty(&hmi_ctrl_layer->surfaces_list)) {
375 +               wl_list_remove(&hmi_ctrl_layer->link);
376 +               wl_list_remove(&hmi_ctrl_layer->screen_link);
377 +               ivi_controller_interface->layer_destroy(dest_layer);
378 +               free(hmi_ctrl_layer);
379 +       }
380 +
381 +       free(surf);
382 +
383 +exit:
384 +       ivi_controller_interface->commit_changes();
385 +}
386 +
387 +static void
388 +hmi_ctrl_surface_destroy(struct wl_listener *listener, void *data)
389 +{
390 +       struct hmi_controller_surface *hmi_ctrl_surface =
391 +               container_of(listener, struct hmi_controller_surface,
392 +                       destroy_listener);
393 +
394 +       pr_dbg("Try to remove surface by direct notification\n");
395 +
396 +       ivi_controller_interface->surface_destroy(hmi_ctrl_surface->ivisurf);
397 +}
398 +
399 +static void
400 +set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
401 +                                  void *userdata)
402 +{
403 +       struct hmi_controller *hmi_ctrl = userdata;
404 +       struct hmi_controller_layer *hmi_ctrl_layer = NULL;
405 +       struct weston_surface *surface;
406 +       struct hmi_controller_surface *hmi_ctrl_surf = NULL;
407 +
408 +       wl_list_for_each(hmi_ctrl_layer, &hmi_ctrl->layers_list, link) {
409 +               wl_list_for_each(hmi_ctrl_surf, &hmi_ctrl_layer->surfaces_list, link) {
410 +                       if (hmi_ctrl_surf->ivisurf == ivisurf) {
411 +                               pr_dbg("Surface was already configured. Skip add to list\n");
412 +                               goto found;
413 +                       }
414 +               }
415 +       }
416 +
417 +       hmi_ctrl_layer = NULL;
418 +found:
419 +       surface = ivi_controller_interface->surface_get_weston_surface(ivisurf);
420 +
421 +       if (surface) {
422 +
423 +               ivi_controller_interface->surface_set_source_rectangle(
424 +                       ivisurf, 0, WINDOWS_TITLE_HEIGHT, surface->width,
425 +                       surface->height);
426 +
427 +#if 0
428 +               ivi_controller_interface->surface_set_destination_rectangle(
429 +                       ivisurf, 0, 0, surface->width, surface->height);
430 +#else
431 +               if (hmi_ctrl_layer) {
432 +                       ivi_controller_interface->surface_set_destination_rectangle(
433 +                               ivisurf, 0, 0, hmi_ctrl_layer->width, hmi_ctrl_layer->height);
434 +               } else {
435 +                       ivi_controller_interface->surface_set_destination_rectangle(
436 +                               ivisurf, 0, 0, surface->width, surface->height);
437 +               }
438 +#endif
439 +               ivi_controller_interface->surface_set_visibility(ivisurf, true);
440 +               ivi_controller_interface->commit_changes();
441 +       }
442 +}
443 +
444 +static struct hmi_server_setting *
445 +hmi_server_setting_create(struct weston_compositor *ec)
446 +{
447 +       struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
448 +       struct weston_config *config = ec->config;
449 +       struct weston_config_section *shell_section = NULL;
450 +
451 +       shell_section = weston_config_get_section(config, "ivi-shell",
452 +                                                 NULL, NULL);
453 +
454 +       weston_config_section_get_uint(shell_section, "base-layer-id",
455 +                                      &setting->base_layer_id, 1000);
456 +
457 +       setting->panel_height = 30;
458 +
459 +       return setting;
460 +}
461 +
462 +static void
463 +hmi_controller_destroy(struct wl_listener *listener, void *data)
464 +{
465 +       struct hmi_controller *hmi_ctrl =
466 +               container_of(listener, struct hmi_controller, destroy_listener);
467 +
468 +       free(hmi_ctrl->hmi_setting);
469 +       free(hmi_ctrl);
470 +}
471 +
472 +static struct hmi_controller *
473 +hmi_controller_create(struct weston_compositor *ec)
474 +{
475 +       struct ivi_layout_screen **pp_screen = NULL;
476 +       struct ivi_layout_screen *iviscrn  = NULL;
477 +       int32_t screen_length  = 0;
478 +       struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
479 +       int i, j = 0;
480 +
481 +       hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
482 +       hmi_ctrl->compositor = ec;
483 +
484 +       ivi_controller_interface->get_screens(&screen_length, &pp_screen);
485 +
486 +       for (i = screen_length; i-- ; j++) {
487 +
488 +               iviscrn = pp_screen[i];
489 +               hmi_ctrl->screens[j].iviscrn = iviscrn;
490 +               wl_list_init(&hmi_ctrl->screens[i].layers_list);
491 +
492 +               hmi_ctrl->screens_count++;
493 +       }
494 +
495 +       ivi_controller_interface->add_notification_create_surface(
496 +               set_notification_create_surface, hmi_ctrl);
497 +       ivi_controller_interface->add_notification_remove_surface(
498 +               set_notification_remove_surface, hmi_ctrl);
499 +       ivi_controller_interface->add_notification_configure_surface(
500 +               set_notification_configure_surface, hmi_ctrl);
501 +
502 +       hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
503 +       wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
504 +                     &hmi_ctrl->destroy_listener);
505 +
506 +       wl_list_init(&hmi_ctrl->layers_list);
507 +
508 +       free(pp_screen);
509 +       pp_screen = NULL;
510 +
511 +       return hmi_ctrl;
512 +}
513 +
514 +WL_EXPORT const struct wl_interface ivi_hmi_controller_interface = {
515 +       "ivi_layout_controller", 1,
516 +       0, NULL,
517 +       0, NULL,
518 +};
519 +
520 +static void
521 +bind_hmi_controller(struct wl_client *client,
522 +                   void *data, uint32_t version, uint32_t id)
523 +{
524 +       struct hmi_controller *hmi_ctrl = data;
525 +
526 +       if (hmi_ctrl->user_interface != client) {
527 +               struct wl_resource *res = wl_client_get_object(client, 1);
528 +               wl_resource_post_error(res,
529 +                               WL_DISPLAY_ERROR_INVALID_OBJECT,
530 +                               "hmi-controller failed: permission denied");
531 +               return;
532 +       }
533 +
534 +       wl_resource_create(client, &ivi_hmi_controller_interface, 1, id);
535 +}
536 +
537 +static int32_t
538 +initialize(struct hmi_controller *hmi_ctrl)
539 +{
540 +       struct config_command {
541 +               char *key;
542 +               uint32_t *dest;
543 +       };
544 +
545 +       struct weston_config *config = hmi_ctrl->compositor->config;
546 +
547 +       weston_config_get_section(config, "ivi-shell", NULL, NULL);
548 +
549 +       return 1;
550 +}
551 +
552 +/*****************************************************************************
553 + *  exported functions
554 + ****************************************************************************/
555 +WL_EXPORT int
556 +controller_module_init(struct weston_compositor *ec,
557 +                      int *argc, char *argv[],
558 +                      const struct ivi_controller_interface *interface,
559 +                      size_t interface_version)
560 +{
561 +       struct hmi_controller *hmi_ctrl = NULL;
562 +
563 +
564 +       if (interface_version < sizeof(struct ivi_controller_interface)) {
565 +               weston_log("ivi-layout-controller-ti: version mismatch of controller interface");
566 +               return -1;
567 +       }
568 +
569 +       ivi_controller_interface = interface;
570 +
571 +       hmi_ctrl = hmi_controller_create(ec);
572 +
573 +       if (!initialize(hmi_ctrl)) {
574 +               return -1;
575 +       }
576 +
577 +       if (wl_global_create(ec->wl_display,
578 +                            &ivi_hmi_controller_interface, 1,
579 +                            hmi_ctrl, bind_hmi_controller) == NULL) {
580 +               return -1;
581 +       }
582 +
583 +       weston_log("ivi-layout-controller-ti: Successfully started.");
584 +
585 +       return 0;
586 +}
587 -- 
588 2.4.5
589