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-shell-ext.h"
47 #include "ivi-application-server-protocol.h"
48 #include "ivi-layout-private.h"
50 #include "../shared/os-compatibility.h"
52 /* Representation of ivi_surface protocol object. */
53 struct ivi_shell_surface
55 struct wl_resource* resource;
56 struct ivi_shell *shell;
57 struct ivi_layout_surface *layout_surface;
59 struct weston_surface *surface;
60 struct wl_listener surface_destroy_listener;
69 struct wl_listener configured_listener;
72 struct ivi_shell_setting
77 static struct ivi_shell *
78 get_shell_instance(void)
80 static struct ivi_shell *shell = NULL;
83 shell = calloc(1, sizeof(*shell));
90 * Implementation of ivi_surface
94 surface_configure_notify(struct wl_listener *listener, void *data)
96 struct ivi_layout_surface *layout_surf =
97 (struct ivi_layout_surface *)data;
99 struct ivi_shell_surface *shell_surf =
100 container_of(listener,
101 struct ivi_shell_surface,
102 configured_listener);
104 int32_t dest_width = 0;
105 int32_t dest_height = 0;
106 shell_surf->shell->ivi_layout->get_surface_dimension(layout_surf,
107 &dest_width, &dest_height);
109 if (shell_surf->resource)
110 ivi_surface_send_configure(shell_surf->resource,
111 dest_width, dest_height);
115 ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
117 static struct ivi_shell_surface *
118 get_ivi_shell_surface(struct weston_surface *surface)
120 if (surface->configure == ivi_shell_surface_configure)
121 return surface->configure_private;
127 ivi_shell_surface_configure(struct weston_surface *surface,
128 int32_t sx, int32_t sy)
130 struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(surface);
131 struct weston_view *view;
137 if (surface->width == 0 || surface->height == 0 || ivisurf == NULL)
140 view = ivisurf->shell->ivi_layout->get_weston_view(ivisurf->layout_surface);
144 if (ivisurf->width != surface->width ||
145 ivisurf->height != surface->height) {
146 ivisurf->width = surface->width;
147 ivisurf->height = surface->height;
149 weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
150 weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
152 weston_view_set_position(view,
153 view->geometry.x + to_x - from_x,
154 view->geometry.y + to_y - from_y);
155 weston_view_update_transform(view);
157 ivisurf->shell->ivi_layout->surface_configure(ivisurf->layout_surface,
158 surface->width, surface->height);
163 * The ivi_surface wl_resource destructor.
165 * Gets called via ivi_surface.destroy request or automatic wl_client clean-up.
168 shell_destroy_shell_surface(struct wl_resource *resource)
170 struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
171 if (ivisurf != NULL) {
172 ivisurf->resource = NULL;
176 /* Gets called through the weston_surface destroy signal. */
178 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
180 struct ivi_shell_surface *ivisurf =
181 container_of(listener, struct ivi_shell_surface,
182 surface_destroy_listener);
184 assert(ivisurf != NULL);
186 if (ivisurf->surface!=NULL) {
187 ivisurf->surface->configure = NULL;
188 ivisurf->surface->configure_private = NULL;
189 ivisurf->surface = NULL;
192 wl_list_remove(&ivisurf->surface_destroy_listener.link);
193 wl_list_remove(&ivisurf->link);
195 if (ivisurf->resource != NULL) {
196 wl_resource_set_user_data(ivisurf->resource, NULL);
197 ivisurf->resource = NULL;
203 /* Gets called, when a client sends ivi_surface.destroy request. */
205 surface_destroy(struct wl_client *client, struct wl_resource *resource)
208 * Fires the wl_resource destroy signal, and then calls
209 * ivi_surface wl_resource destructor: shell_destroy_shell_surface()
211 wl_resource_destroy(resource);
214 static const struct ivi_surface_interface surface_implementation = {
218 static struct shell_surface*
219 create_shell_surface(void *shell,
220 struct weston_surface *weston_surface,
221 const struct weston_shell_client *client)
223 struct ivi_shell_surface *ivisurf;
224 struct ivi_layout_surface *layout_surface;
225 static uint32_t id_surface = 0xffffffff; // FIXME
227 ivisurf = zalloc(sizeof *ivisurf);
228 if (ivisurf == NULL) {
229 weston_log("no memory\n");
233 layout_surface = ((struct ivi_shell*)shell)
234 ->ivi_layout->surface_create(weston_surface, id_surface);
236 wl_list_init(&ivisurf->link);
237 wl_list_insert(&((struct ivi_shell*)shell)->ivi_surface_list, &ivisurf->link);
239 ivisurf->shell = shell;
240 ivisurf->id_surface = id_surface;
242 ivisurf->resource = NULL;
245 ivisurf->layout_surface = layout_surface;
246 ivisurf->configured_listener.notify = surface_configure_notify;
247 ((struct ivi_shell*)shell)->ivi_layout->add_surface_configured_listener(
248 layout_surface, &ivisurf->configured_listener);
250 ivisurf->surface = weston_surface;
252 weston_surface->configure = ivi_shell_surface_configure;
253 weston_surface->configure_private = ivisurf;
260 static struct weston_view*
261 get_primary_view(void *shell,
262 struct shell_surface *shsurf)
268 set_toplevel(struct shell_surface *shsurf)
271 * non support for ivi-shell
272 * this shall not be done by client request.
277 set_transient(struct shell_surface *shsurf,
278 struct weston_surface *parent,
279 int x, int y, uint32_t flags)
282 * non support for ivi-shell
283 * this shall not be done by client request.
288 set_fullscreen(struct shell_surface *shsurf,
291 struct weston_output *output)
294 * non support for ivi-shell
295 * this shall not be done by client request.
300 set_xwayland(struct shell_surface *shsurf,
301 int x, int y, uint32_t flags)
304 * non support for ivi-shell
305 * this shall not be done by client request.
310 move(struct shell_surface *shsurf, struct weston_seat *ws)
313 * non support for ivi-shell
314 * this shall not be done by client request.
321 resize(struct shell_surface *shsurf, struct weston_seat *ws, uint32_t edges)
324 * non support for ivi-shell
325 * this shall not be done by client request.
332 set_title(struct shell_surface *shsurf, const char *title)
335 * title is not supported by ivi-shell
340 set_window_geometry(struct shell_surface *shsurf,
341 int32_t x, int32_t y, int32_t width, int32_t height)
344 * non support for ivi-shell
345 * this shall not be done by client request.
350 * Request handler for ivi_application.surface_create.
352 * Creates an ivi_surface protocol object associated with the given wl_surface.
353 * ivi_surface protocol object is represented by struct ivi_shell_surface.
355 * \param client The client.
356 * \param resource The ivi_application protocol object.
357 * \param id_surface The IVI surface ID.
358 * \param surface_resource The wl_surface protocol object.
359 * \param id The protocol object id for the new ivi_surface protocol object.
361 * The wl_surface is given the ivi_surface role and associated with a unique
362 * IVI ID which is used to identify the surface in a controller
366 application_surface_create(struct wl_client *client,
367 struct wl_resource *resource,
369 struct wl_resource *surface_resource,
372 struct ivi_shell *shell = wl_resource_get_user_data(resource);
373 struct ivi_shell_surface *ivisurf;
374 struct ivi_layout_surface *layout_surface;
375 struct weston_surface *weston_surface =
376 wl_resource_get_user_data(surface_resource);
377 struct wl_resource *res;
379 if (weston_surface->configure) {
380 wl_resource_post_error(resource,
381 IVI_APPLICATION_ERROR_ROLE,
382 "surface->configure already "
387 layout_surface = shell->ivi_layout->surface_create(weston_surface,
390 /* check if id_ivi is already used for wl_surface*/
391 if (layout_surface == NULL){
392 wl_resource_post_error(resource,
393 IVI_APPLICATION_ERROR_IVI_ID,
394 "surface_id is already assigned "
399 ivisurf = zalloc(sizeof *ivisurf);
400 if (ivisurf == NULL) {
401 wl_resource_post_no_memory(resource);
405 wl_list_init(&ivisurf->link);
406 wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
408 ivisurf->shell = shell;
409 ivisurf->id_surface = id_surface;
413 ivisurf->layout_surface = layout_surface;
414 ivisurf->configured_listener.notify = surface_configure_notify;
415 ivisurf->shell->ivi_layout->add_surface_configured_listener(layout_surface,
416 &ivisurf->configured_listener);
419 * The following code relies on wl_surface destruction triggering
420 * immediateweston_surface destruction
422 ivisurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
423 wl_signal_add(&weston_surface->destroy_signal,
424 &ivisurf->surface_destroy_listener);
426 ivisurf->surface = weston_surface;
428 weston_surface->configure = ivi_shell_surface_configure;
429 weston_surface->configure_private = ivisurf;
431 res = wl_resource_create(client, &ivi_surface_interface, 1, id);
433 wl_client_post_no_memory(client);
437 ivisurf->resource = res;
439 wl_resource_set_implementation(res, &surface_implementation,
440 ivisurf, shell_destroy_shell_surface);
443 static const struct ivi_application_interface application_implementation = {
444 application_surface_create
448 * Handle wl_registry.bind of ivi_application global singleton.
451 unbind_resource(struct wl_resource *resource)
453 wl_list_remove(wl_resource_get_link(resource));
457 bind_ivi_application(struct wl_client *client,
458 void *data, uint32_t version, uint32_t id)
460 struct ivi_shell *shell = data;
461 struct wl_resource *resource;
463 resource = wl_resource_create(client, &ivi_application_interface,
466 wl_resource_set_implementation(resource,
467 &application_implementation,
468 shell, unbind_resource);
470 wl_list_insert(&shell->client_list, wl_resource_get_link(resource));
474 get_default_view(struct weston_surface *surface)
476 struct ivi_shell_surface *shsurf;
477 struct weston_view *view;
479 if (!surface || wl_list_empty(&surface->views))
482 shsurf = get_ivi_shell_surface(surface);
483 if (shsurf && shsurf->layout_surface) {
484 view = shsurf->shell->ivi_layout->get_weston_view(shsurf->layout_surface);
489 wl_list_for_each(view, &surface->views, surface_link) {
490 if (weston_view_is_mapped(view))
494 return container_of(surface->views.next,
495 struct weston_view, surface_link);
499 * Called through the compositor's destroy signal.
502 shell_destroy(struct wl_listener *listener, void *data)
504 struct ivi_shell *shell =
505 container_of(listener, struct ivi_shell, destroy_listener);
506 struct ivi_shell_surface *ivisurf, *next;
508 input_panel_destroy(shell);
510 wl_list_for_each_safe(ivisurf, next, &shell->ivi_surface_list, link) {
511 wl_list_remove(&ivisurf->link);
519 init_ivi_shell(struct weston_compositor *compositor, struct ivi_shell *shell)
521 shell->compositor = compositor;
523 wl_list_init(&shell->ivi_surface_list);
524 wl_list_init(&shell->client_list);
526 weston_layer_init(&shell->input_panel_layer, NULL);
528 compositor->shell_interface.shell = shell;
529 compositor->shell_interface.create_shell_surface = create_shell_surface;
530 compositor->shell_interface.get_primary_view = get_primary_view;
531 compositor->shell_interface.set_toplevel = set_toplevel;
532 compositor->shell_interface.set_transient = set_transient;
533 compositor->shell_interface.set_fullscreen = set_fullscreen;
534 compositor->shell_interface.set_xwayland = set_xwayland;
535 compositor->shell_interface.move = move;
536 compositor->shell_interface.resize = resize;
537 compositor->shell_interface.set_title = set_title;
538 compositor->shell_interface.set_window_geometry = set_window_geometry;
542 ivi_shell_setting_create(struct ivi_shell_setting *dest,
543 struct weston_compositor *compositor)
546 struct weston_config *config = compositor->config;
547 struct weston_config_section *section;
552 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
554 if (weston_config_section_get_string(
555 section, "ivi-module", &dest->ivi_module, NULL) != 0)
564 send_wl_shell_info(int32_t pid, const char *window_title, struct weston_surface *surface)
566 struct ivi_shell *shell = get_shell_instance();
567 struct wl_resource *resource;
568 uint32_t id_surface = 0;
569 struct ivi_shell_surface *ivisurf;
571 wl_list_for_each(ivisurf, &shell->ivi_surface_list, link) {
572 if (surface == ivisurf->surface) {
573 id_surface = ivisurf->id_surface;
578 wl_resource_for_each(resource, &shell->client_list) {
579 ivi_application_send_wl_shell_info(resource, pid, window_title, id_surface);
584 * Initialization of ivi-shell.
587 ivi_load_modules(struct weston_compositor *compositor, const char *modules,
588 int *argc, char *argv[])
592 int (*module_init)(struct weston_compositor *compositor,
593 int *argc, char *argv[]);
600 end = strchrnul(p, ',');
601 snprintf(buffer, sizeof buffer, "%.*s", (int)(end - p), p);
603 module_init = weston_load_module(buffer, "module_init");
605 module_init(compositor, argc, argv);
616 module_init(struct weston_compositor *compositor,
617 int *argc, char *argv[])
619 char ivi_layout_path[PATH_MAX];
621 struct ivi_shell_setting setting = { };
623 struct ivi_shell *shell = get_shell_instance();
627 init_ivi_shell(compositor, shell);
629 shell->destroy_listener.notify = shell_destroy;
630 wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener);
632 if (input_panel_setup(shell) < 0)
635 if (wl_global_create(compositor->wl_display,
636 &ivi_application_interface, 1,
637 shell, bind_ivi_application) == NULL)
640 if (ivi_shell_setting_create(&setting, compositor) != 0)
644 * load module:ivi-layout
645 * ivi_layout_interface is referred by ivi-shell to use ivi-layout.
646 * The reason why the following code is written newly without
647 * using weston_load_module is it doesn't open library with
648 * RTLD_GLOBAL option.
650 snprintf(ivi_layout_path, sizeof ivi_layout_path,
651 "%s/%s", MODULEDIR, "ivi-layout.so");
652 module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_NOLOAD);
654 weston_log("ivi-shell: Module '%s' already loaded\n",
660 weston_log("ivi-shell: Loading module '%s'\n", ivi_layout_path);
661 module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_GLOBAL);
663 weston_log("ivi-shell: Failed to load module: %s\n", dlerror());
667 shell->ivi_layout = dlsym(module,"ivi_layout_interface");
668 if (!shell->ivi_layout){
669 weston_log("ivi-shell: couldn't find ivi_layout_interface in '%s'\n", ivi_layout_path);
670 free(setting.ivi_module);
675 shell->ivi_layout->init_with_compositor(compositor);
677 /* Call module_init of ivi-modules which are defined in weston.ini */
678 if (ivi_load_modules(compositor, setting.ivi_module, argc, argv) < 0) {
679 free(setting.ivi_module);
684 free(setting.ivi_module);
686 /* Initialize ivi-shell-ext. wl_shell is supported here */
687 return init_ivi_shell_ext(compositor, argc, argv);