2 * Copyright (C) 2013 DENSO CORPORATION
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * ivi-shell supports a type of shell for In-Vehicle Infotainment system.
25 * In-Vehicle Infotainment system traditionally manages surfaces with global
26 * identification. A protocol, ivi_application, supports such a feature
27 * by implementing a request, ivi_application::surface_creation defined in
28 * ivi_application.xml.
30 * The ivi-shell explicitly loads a module to add business logic like how to
31 * layout surfaces by using internal ivi-layout APIs.
40 #include <linux/input.h>
45 #include "ivi-shell.h"
46 #include "ivi-application-server-protocol.h"
47 #include "ivi-layout-private.h"
49 #include "../shared/os-compatibility.h"
51 /* Representation of ivi_surface protocol object. */
52 struct ivi_shell_surface
54 struct wl_resource* resource;
55 struct ivi_shell *shell;
56 struct ivi_layout_surface *layout_surface;
58 struct weston_surface *surface;
59 struct wl_listener surface_destroy_listener;
68 struct wl_listener configured_listener;
71 struct ivi_shell_setting
77 * Implementation of ivi_surface
81 surface_configure_notify(struct wl_listener *listener, void *data)
83 struct ivi_layout_surface *layout_surf =
84 (struct ivi_layout_surface *)data;
86 struct ivi_shell_surface *shell_surf =
87 container_of(listener,
88 struct ivi_shell_surface,
91 int32_t dest_width = 0;
92 int32_t dest_height = 0;
93 shell_surf->shell->ivi_layout->get_surface_dimension(layout_surf,
94 &dest_width, &dest_height);
96 if (shell_surf->resource)
97 ivi_surface_send_configure(shell_surf->resource,
98 dest_width, dest_height);
102 ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
104 static struct ivi_shell_surface *
105 get_ivi_shell_surface(struct weston_surface *surface)
107 if (surface->configure == ivi_shell_surface_configure)
108 return surface->configure_private;
114 ivi_shell_surface_configure(struct weston_surface *surface,
115 int32_t sx, int32_t sy)
117 struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(surface);
118 struct weston_view *view;
124 if (surface->width == 0 || surface->height == 0 || ivisurf == NULL)
127 view = ivisurf->shell->ivi_layout->get_weston_view(ivisurf->layout_surface);
131 if (ivisurf->width != surface->width ||
132 ivisurf->height != surface->height) {
133 ivisurf->width = surface->width;
134 ivisurf->height = surface->height;
136 weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
137 weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
139 weston_view_set_position(view,
140 view->geometry.x + to_x - from_x,
141 view->geometry.y + to_y - from_y);
142 weston_view_update_transform(view);
144 ivisurf->shell->ivi_layout->surface_configure(ivisurf->layout_surface,
145 surface->width, surface->height);
150 * The ivi_surface wl_resource destructor.
152 * Gets called via ivi_surface.destroy request or automatic wl_client clean-up.
155 shell_destroy_shell_surface(struct wl_resource *resource)
157 struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
158 if (ivisurf != NULL) {
159 ivisurf->resource = NULL;
163 /* Gets called through the weston_surface destroy signal. */
165 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
167 struct ivi_shell_surface *ivisurf =
168 container_of(listener, struct ivi_shell_surface,
169 surface_destroy_listener);
171 assert(ivisurf != NULL);
173 if (ivisurf->surface!=NULL) {
174 ivisurf->surface->configure = NULL;
175 ivisurf->surface->configure_private = NULL;
176 ivisurf->surface = NULL;
179 wl_list_remove(&ivisurf->surface_destroy_listener.link);
180 wl_list_remove(&ivisurf->link);
182 if (ivisurf->resource != NULL) {
183 wl_resource_set_user_data(ivisurf->resource, NULL);
184 ivisurf->resource = NULL;
190 /* Gets called, when a client sends ivi_surface.destroy request. */
192 surface_destroy(struct wl_client *client, struct wl_resource *resource)
195 * Fires the wl_resource destroy signal, and then calls
196 * ivi_surface wl_resource destructor: shell_destroy_shell_surface()
198 wl_resource_destroy(resource);
201 static const struct ivi_surface_interface surface_implementation = {
205 static struct shell_surface*
206 create_shell_surface(void *shell,
207 struct weston_surface *weston_surface,
208 const struct weston_shell_client *client)
210 struct ivi_shell_surface *ivisurf;
211 struct ivi_layout_surface *layout_surface;
212 static uint32_t id_surface = 0xffffffff; // FIXME
214 ivisurf = zalloc(sizeof *ivisurf);
215 if (ivisurf == NULL) {
216 weston_log("no memory\n");
220 layout_surface = ((struct ivi_shell*)shell)
221 ->ivi_layout->surface_create(weston_surface, id_surface);
223 wl_list_init(&ivisurf->link);
224 wl_list_insert(&((struct ivi_shell*)shell)->ivi_surface_list, &ivisurf->link);
226 ivisurf->shell = shell;
227 ivisurf->id_surface = id_surface;
229 ivisurf->resource = NULL;
232 ivisurf->layout_surface = layout_surface;
233 ivisurf->configured_listener.notify = surface_configure_notify;
234 ((struct ivi_shell*)shell)->ivi_layout->add_surface_configured_listener(
235 layout_surface, &ivisurf->configured_listener);
237 ivisurf->surface = weston_surface;
239 weston_surface->configure = ivi_shell_surface_configure;
240 weston_surface->configure_private = ivisurf;
247 static struct weston_view*
248 get_primary_view(void *shell,
249 struct shell_surface *shsurf)
255 set_toplevel(struct shell_surface *shsurf)
258 * non support for ivi-shell
259 * this shall not be done by client request.
264 set_transient(struct shell_surface *shsurf,
265 struct weston_surface *parent,
266 int x, int y, uint32_t flags)
269 * non support for ivi-shell
270 * this shall not be done by client request.
275 set_fullscreen(struct shell_surface *shsurf,
278 struct weston_output *output)
281 * non support for ivi-shell
282 * this shall not be done by client request.
287 set_xwayland(struct shell_surface *shsurf,
288 int x, int y, uint32_t flags)
291 * non support for ivi-shell
292 * this shall not be done by client request.
297 move(struct shell_surface *shsurf, struct weston_seat *ws)
300 * non support for ivi-shell
301 * this shall not be done by client request.
308 resize(struct shell_surface *shsurf, struct weston_seat *ws, uint32_t edges)
311 * non support for ivi-shell
312 * this shall not be done by client request.
319 set_title(struct shell_surface *shsurf, const char *title)
322 * title is not supported by ivi-shell
327 set_window_geometry(struct shell_surface *shsurf,
328 int32_t x, int32_t y, int32_t width, int32_t height)
331 * non support for ivi-shell
332 * this shall not be done by client request.
337 * Request handler for ivi_application.surface_create.
339 * Creates an ivi_surface protocol object associated with the given wl_surface.
340 * ivi_surface protocol object is represented by struct ivi_shell_surface.
342 * \param client The client.
343 * \param resource The ivi_application protocol object.
344 * \param id_surface The IVI surface ID.
345 * \param surface_resource The wl_surface protocol object.
346 * \param id The protocol object id for the new ivi_surface protocol object.
348 * The wl_surface is given the ivi_surface role and associated with a unique
349 * IVI ID which is used to identify the surface in a controller
353 application_surface_create(struct wl_client *client,
354 struct wl_resource *resource,
356 struct wl_resource *surface_resource,
359 struct ivi_shell *shell = wl_resource_get_user_data(resource);
360 struct ivi_shell_surface *ivisurf;
361 struct ivi_layout_surface *layout_surface;
362 struct weston_surface *weston_surface =
363 wl_resource_get_user_data(surface_resource);
364 struct wl_resource *res;
366 if (weston_surface->configure) {
367 wl_resource_post_error(resource,
368 IVI_APPLICATION_ERROR_ROLE,
369 "surface->configure already "
374 layout_surface = shell->ivi_layout->surface_create(weston_surface,
377 /* check if id_ivi is already used for wl_surface*/
378 if (layout_surface == NULL){
379 wl_resource_post_error(resource,
380 IVI_APPLICATION_ERROR_IVI_ID,
381 "surface_id is already assigned "
386 ivisurf = zalloc(sizeof *ivisurf);
387 if (ivisurf == NULL) {
388 wl_resource_post_no_memory(resource);
392 wl_list_init(&ivisurf->link);
393 wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
395 ivisurf->shell = shell;
396 ivisurf->id_surface = id_surface;
400 ivisurf->layout_surface = layout_surface;
401 ivisurf->configured_listener.notify = surface_configure_notify;
402 ivisurf->shell->ivi_layout->add_surface_configured_listener(layout_surface,
403 &ivisurf->configured_listener);
406 * The following code relies on wl_surface destruction triggering
407 * immediateweston_surface destruction
409 ivisurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
410 wl_signal_add(&weston_surface->destroy_signal,
411 &ivisurf->surface_destroy_listener);
413 ivisurf->surface = weston_surface;
415 weston_surface->configure = ivi_shell_surface_configure;
416 weston_surface->configure_private = ivisurf;
418 res = wl_resource_create(client, &ivi_surface_interface, 1, id);
420 wl_client_post_no_memory(client);
424 ivisurf->resource = res;
426 wl_resource_set_implementation(res, &surface_implementation,
427 ivisurf, shell_destroy_shell_surface);
430 static const struct ivi_application_interface application_implementation = {
431 application_surface_create
435 * Handle wl_registry.bind of ivi_application global singleton.
438 bind_ivi_application(struct wl_client *client,
439 void *data, uint32_t version, uint32_t id)
441 struct ivi_shell *shell = data;
442 struct wl_resource *resource;
444 resource = wl_resource_create(client, &ivi_application_interface,
447 wl_resource_set_implementation(resource,
448 &application_implementation,
453 get_default_view(struct weston_surface *surface)
455 struct ivi_shell_surface *shsurf;
456 struct weston_view *view;
458 if (!surface || wl_list_empty(&surface->views))
461 shsurf = get_ivi_shell_surface(surface);
462 if (shsurf && shsurf->layout_surface) {
463 view = shsurf->shell->ivi_layout->get_weston_view(shsurf->layout_surface);
468 wl_list_for_each(view, &surface->views, surface_link) {
469 if (weston_view_is_mapped(view))
473 return container_of(surface->views.next,
474 struct weston_view, surface_link);
478 * Called through the compositor's destroy signal.
481 shell_destroy(struct wl_listener *listener, void *data)
483 struct ivi_shell *shell =
484 container_of(listener, struct ivi_shell, destroy_listener);
485 struct ivi_shell_surface *ivisurf, *next;
487 input_panel_destroy(shell);
489 wl_list_for_each_safe(ivisurf, next, &shell->ivi_surface_list, link) {
490 wl_list_remove(&ivisurf->link);
498 init_ivi_shell(struct weston_compositor *compositor, struct ivi_shell *shell)
500 shell->compositor = compositor;
502 wl_list_init(&shell->ivi_surface_list);
504 weston_layer_init(&shell->input_panel_layer, NULL);
506 compositor->shell_interface.shell = shell;
507 compositor->shell_interface.create_shell_surface = create_shell_surface;
508 compositor->shell_interface.get_primary_view = get_primary_view;
509 compositor->shell_interface.set_toplevel = set_toplevel;
510 compositor->shell_interface.set_transient = set_transient;
511 compositor->shell_interface.set_fullscreen = set_fullscreen;
512 compositor->shell_interface.set_xwayland = set_xwayland;
513 compositor->shell_interface.move = move;
514 compositor->shell_interface.resize = resize;
515 compositor->shell_interface.set_title = set_title;
516 compositor->shell_interface.set_window_geometry = set_window_geometry;
520 ivi_shell_setting_create(struct ivi_shell_setting *dest,
521 struct weston_compositor *compositor)
524 struct weston_config *config = compositor->config;
525 struct weston_config_section *section;
530 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
532 if (weston_config_section_get_string(
533 section, "ivi-module", &dest->ivi_module, NULL) != 0)
542 * Initialization of ivi-shell.
545 ivi_load_modules(struct weston_compositor *compositor, const char *modules,
546 int *argc, char *argv[])
550 int (*module_init)(struct weston_compositor *compositor,
551 int *argc, char *argv[]);
558 end = strchrnul(p, ',');
559 snprintf(buffer, sizeof buffer, "%.*s", (int)(end - p), p);
561 module_init = weston_load_module(buffer, "module_init");
563 module_init(compositor, argc, argv);
574 module_init(struct weston_compositor *compositor,
575 int *argc, char *argv[])
577 struct ivi_shell *shell;
578 char ivi_layout_path[PATH_MAX];
580 struct ivi_shell_setting setting = { };
582 shell = zalloc(sizeof *shell);
586 init_ivi_shell(compositor, shell);
588 shell->destroy_listener.notify = shell_destroy;
589 wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener);
591 if (input_panel_setup(shell) < 0)
594 if (wl_global_create(compositor->wl_display,
595 &ivi_application_interface, 1,
596 shell, bind_ivi_application) == NULL)
599 if (ivi_shell_setting_create(&setting, compositor) != 0)
603 * load module:ivi-layout
604 * ivi_layout_interface is referred by ivi-shell to use ivi-layout.
605 * The reason why the following code is written newly without
606 * using weston_load_module is it doesn't open library with
607 * RTLD_GLOBAL option.
609 snprintf(ivi_layout_path, sizeof ivi_layout_path,
610 "%s/%s", MODULEDIR, "ivi-layout.so");
611 module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_NOLOAD);
613 weston_log("ivi-shell: Module '%s' already loaded\n",
619 weston_log("ivi-shell: Loading module '%s'\n", ivi_layout_path);
620 module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_GLOBAL);
622 weston_log("ivi-shell: Failed to load module: %s\n", dlerror());
626 shell->ivi_layout = dlsym(module,"ivi_layout_interface");
627 if (!shell->ivi_layout){
628 weston_log("ivi-shell: couldn't find ivi_layout_interface in '%s'\n", ivi_layout_path);
629 free(setting.ivi_module);
634 shell->ivi_layout->init_with_compositor(compositor);
636 /* Call module_init of ivi-modules which are defined in weston.ini */
637 if (ivi_load_modules(compositor, setting.ivi_module, argc, argv) < 0) {
638 free(setting.ivi_module);
643 free(setting.ivi_module);