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 <wayland-server.h>
47 #include "ivi-shell.h"
48 #include "ivi-shell-ext.h"
49 #include "ivi-application-server-protocol.h"
50 #include "ivi-layout-private.h"
52 #include "../shared/os-compatibility.h"
54 /* Representation of ivi_surface protocol object. */
55 struct ivi_shell_surface
57 struct wl_resource* resource;
58 struct ivi_shell *shell;
59 struct ivi_layout_surface *layout_surface;
61 struct weston_surface *surface;
62 struct wl_listener surface_destroy_listener;
71 struct wl_listener configured_listener;
74 struct ivi_shell_setting
79 static struct ivi_shell *
80 get_shell_instance(void)
82 static struct ivi_shell *shell = NULL;
85 shell = calloc(1, sizeof(*shell));
92 * Implementation of ivi_surface
96 surface_configure_notify(struct wl_listener *listener, void *data)
98 struct ivi_layout_surface *layout_surf =
99 (struct ivi_layout_surface *)data;
101 struct ivi_shell_surface *shell_surf =
102 container_of(listener,
103 struct ivi_shell_surface,
104 configured_listener);
106 int32_t dest_width = 0;
107 int32_t dest_height = 0;
108 shell_surf->shell->ivi_layout->get_surface_dimension(layout_surf,
109 &dest_width, &dest_height);
111 if (shell_surf->resource)
112 ivi_surface_send_configure(shell_surf->resource,
113 dest_width, dest_height);
117 ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
119 static struct ivi_shell_surface *
120 get_ivi_shell_surface(struct weston_surface *surface)
122 if (surface->configure == ivi_shell_surface_configure)
123 return surface->configure_private;
129 ivi_shell_surface_configure(struct weston_surface *surface,
130 int32_t sx, int32_t sy)
132 struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(surface);
133 struct weston_view *view;
139 if (surface->width == 0 || surface->height == 0 || ivisurf == NULL)
142 view = ivisurf->shell->ivi_layout->get_weston_view(ivisurf->layout_surface);
146 if (ivisurf->width != surface->width ||
147 ivisurf->height != surface->height) {
148 ivisurf->width = surface->width;
149 ivisurf->height = surface->height;
151 weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
152 weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
154 weston_view_set_position(view,
155 view->geometry.x + to_x - from_x,
156 view->geometry.y + to_y - from_y);
157 weston_view_update_transform(view);
159 ivisurf->shell->ivi_layout->surface_configure(ivisurf->layout_surface,
160 surface->width, surface->height);
165 * The ivi_surface wl_resource destructor.
167 * Gets called via ivi_surface.destroy request or automatic wl_client clean-up.
170 shell_destroy_shell_surface(struct wl_resource *resource)
172 struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
173 if (ivisurf != NULL) {
174 ivisurf->resource = NULL;
178 /* Gets called through the weston_surface destroy signal. */
180 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
182 struct ivi_shell_surface *ivisurf =
183 container_of(listener, struct ivi_shell_surface,
184 surface_destroy_listener);
186 assert(ivisurf != NULL);
188 if (ivisurf->surface!=NULL) {
189 ivisurf->surface->configure = NULL;
190 ivisurf->surface->configure_private = NULL;
191 ivisurf->surface = NULL;
194 wl_list_remove(&ivisurf->surface_destroy_listener.link);
195 wl_list_remove(&ivisurf->link);
197 if (ivisurf->resource != NULL) {
198 wl_resource_set_user_data(ivisurf->resource, NULL);
199 ivisurf->resource = NULL;
205 /* Gets called, when a client sends ivi_surface.destroy request. */
207 surface_destroy(struct wl_client *client, struct wl_resource *resource)
210 * Fires the wl_resource destroy signal, and then calls
211 * ivi_surface wl_resource destructor: shell_destroy_shell_surface()
213 wl_resource_destroy(resource);
216 static const struct ivi_surface_interface surface_implementation = {
220 static struct shell_surface*
221 create_shell_surface(void *shell,
222 struct weston_surface *weston_surface,
223 const struct weston_shell_client *client)
225 struct ivi_shell_surface *ivisurf;
226 struct ivi_layout_surface *layout_surface;
227 static uint32_t id_surface = 0xffffffff; // FIXME
229 ivisurf = zalloc(sizeof *ivisurf);
230 if (ivisurf == NULL) {
231 weston_log("no memory\n");
235 layout_surface = ((struct ivi_shell*)shell)
236 ->ivi_layout->surface_create(weston_surface, id_surface);
238 wl_list_init(&ivisurf->link);
239 wl_list_insert(&((struct ivi_shell*)shell)->ivi_surface_list, &ivisurf->link);
241 ivisurf->shell = shell;
242 ivisurf->id_surface = id_surface;
244 ivisurf->resource = NULL;
247 ivisurf->layout_surface = layout_surface;
248 ivisurf->configured_listener.notify = surface_configure_notify;
249 ((struct ivi_shell*)shell)->ivi_layout->add_surface_configured_listener(
250 layout_surface, &ivisurf->configured_listener);
252 ivisurf->surface = weston_surface;
254 weston_surface->configure = ivi_shell_surface_configure;
255 weston_surface->configure_private = ivisurf;
262 static struct weston_view*
263 get_primary_view(void *shell,
264 struct shell_surface *shsurf)
270 set_toplevel(struct shell_surface *shsurf)
273 * non support for ivi-shell
274 * this shall not be done by client request.
279 set_transient(struct shell_surface *shsurf,
280 struct weston_surface *parent,
281 int x, int y, uint32_t flags)
284 * non support for ivi-shell
285 * this shall not be done by client request.
290 set_fullscreen(struct shell_surface *shsurf,
293 struct weston_output *output)
296 * non support for ivi-shell
297 * this shall not be done by client request.
302 set_xwayland(struct shell_surface *shsurf,
303 int x, int y, uint32_t flags)
306 * non support for ivi-shell
307 * this shall not be done by client request.
312 move(struct shell_surface *shsurf, struct weston_seat *ws)
315 * non support for ivi-shell
316 * this shall not be done by client request.
323 resize(struct shell_surface *shsurf, struct weston_seat *ws, uint32_t edges)
326 * non support for ivi-shell
327 * this shall not be done by client request.
334 set_title(struct shell_surface *shsurf, const char *title)
337 * title is not supported by ivi-shell
342 set_window_geometry(struct shell_surface *shsurf,
343 int32_t x, int32_t y, int32_t width, int32_t height)
346 * non support for ivi-shell
347 * this shall not be done by client request.
352 * Request handler for ivi_application.surface_create.
354 * Creates an ivi_surface protocol object associated with the given wl_surface.
355 * ivi_surface protocol object is represented by struct ivi_shell_surface.
357 * \param client The client.
358 * \param resource The ivi_application protocol object.
359 * \param id_surface The IVI surface ID.
360 * \param surface_resource The wl_surface protocol object.
361 * \param id The protocol object id for the new ivi_surface protocol object.
363 * The wl_surface is given the ivi_surface role and associated with a unique
364 * IVI ID which is used to identify the surface in a controller
368 application_surface_create(struct wl_client *client,
369 struct wl_resource *resource,
371 struct wl_resource *surface_resource,
374 struct ivi_shell *shell = wl_resource_get_user_data(resource);
375 struct ivi_shell_surface *ivisurf;
376 struct ivi_layout_surface *layout_surface;
377 struct weston_surface *weston_surface =
378 wl_resource_get_user_data(surface_resource);
379 struct wl_resource *res;
381 if (weston_surface->configure) {
382 wl_resource_post_error(resource,
383 IVI_APPLICATION_ERROR_ROLE,
384 "surface->configure already "
389 layout_surface = shell->ivi_layout->surface_create(weston_surface,
392 /* check if id_ivi is already used for wl_surface*/
393 if (layout_surface == NULL){
394 wl_resource_post_error(resource,
395 IVI_APPLICATION_ERROR_IVI_ID,
396 "surface_id is already assigned "
401 ivisurf = zalloc(sizeof *ivisurf);
402 if (ivisurf == NULL) {
403 wl_resource_post_no_memory(resource);
407 wl_list_init(&ivisurf->link);
408 wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
410 ivisurf->shell = shell;
411 ivisurf->id_surface = id_surface;
415 ivisurf->layout_surface = layout_surface;
416 ivisurf->configured_listener.notify = surface_configure_notify;
417 ivisurf->shell->ivi_layout->add_surface_configured_listener(layout_surface,
418 &ivisurf->configured_listener);
421 * The following code relies on wl_surface destruction triggering
422 * immediateweston_surface destruction
424 ivisurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
425 wl_signal_add(&weston_surface->destroy_signal,
426 &ivisurf->surface_destroy_listener);
428 ivisurf->surface = weston_surface;
430 weston_surface->configure = ivi_shell_surface_configure;
431 weston_surface->configure_private = ivisurf;
433 res = wl_resource_create(client, &ivi_surface_interface, 1, id);
435 wl_client_post_no_memory(client);
439 ivisurf->resource = res;
441 wl_resource_set_implementation(res, &surface_implementation,
442 ivisurf, shell_destroy_shell_surface);
444 ivi_shell_surface_configure(weston_surface, 0,0);
447 static const struct ivi_application_interface application_implementation = {
448 application_surface_create
452 * Handle wl_registry.bind of ivi_application global singleton.
455 unbind_resource(struct wl_resource *resource)
457 wl_list_remove(wl_resource_get_link(resource));
461 bind_ivi_application(struct wl_client *client,
462 void *data, uint32_t version, uint32_t id)
464 struct ivi_shell *shell = data;
465 struct wl_resource *resource;
467 resource = wl_resource_create(client, &ivi_application_interface,
470 wl_resource_set_implementation(resource,
471 &application_implementation,
472 shell, unbind_resource);
474 wl_list_insert(&shell->client_list, wl_resource_get_link(resource));
478 get_default_view(struct weston_surface *surface)
480 struct ivi_shell_surface *shsurf;
481 struct weston_view *view;
483 if (!surface || wl_list_empty(&surface->views))
486 shsurf = get_ivi_shell_surface(surface);
487 if (shsurf && shsurf->layout_surface) {
488 view = shsurf->shell->ivi_layout->get_weston_view(shsurf->layout_surface);
493 wl_list_for_each(view, &surface->views, surface_link) {
494 if (weston_view_is_mapped(view))
498 return container_of(surface->views.next,
499 struct weston_view, surface_link);
503 * Called through the compositor's destroy signal.
506 shell_destroy(struct wl_listener *listener, void *data)
508 struct ivi_shell *shell =
509 container_of(listener, struct ivi_shell, destroy_listener);
510 struct ivi_shell_surface *ivisurf, *next;
512 input_panel_destroy(shell);
514 wl_list_for_each_safe(ivisurf, next, &shell->ivi_surface_list, link) {
515 wl_list_remove(&ivisurf->link);
523 init_ivi_shell(struct weston_compositor *compositor, struct ivi_shell *shell)
525 shell->compositor = compositor;
527 wl_list_init(&shell->ivi_surface_list);
528 wl_list_init(&shell->client_list);
530 weston_layer_init(&shell->input_panel_layer, NULL);
532 compositor->shell_interface.shell = shell;
533 compositor->shell_interface.create_shell_surface = create_shell_surface;
534 compositor->shell_interface.get_primary_view = get_primary_view;
535 compositor->shell_interface.set_toplevel = set_toplevel;
536 compositor->shell_interface.set_transient = set_transient;
537 compositor->shell_interface.set_fullscreen = set_fullscreen;
538 compositor->shell_interface.set_xwayland = set_xwayland;
539 compositor->shell_interface.move = move;
540 compositor->shell_interface.resize = resize;
541 compositor->shell_interface.set_title = set_title;
542 compositor->shell_interface.set_window_geometry = set_window_geometry;
546 ivi_shell_setting_create(struct ivi_shell_setting *dest,
547 struct weston_compositor *compositor)
550 struct weston_config *config = compositor->config;
551 struct weston_config_section *section;
556 section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
558 if (weston_config_section_get_string(
559 section, "ivi-module", &dest->ivi_module, NULL) != 0)
568 send_wl_shell_info(int32_t pid, const char *window_title, struct weston_surface *surface)
570 struct ivi_shell *shell = get_shell_instance();
571 struct wl_resource *resource;
572 uint32_t id_surface = 0;
573 struct ivi_shell_surface *ivisurf;
575 wl_list_for_each(ivisurf, &shell->ivi_surface_list, link) {
576 if (surface == ivisurf->surface) {
577 id_surface = ivisurf->id_surface;
582 wl_resource_for_each(resource, &shell->client_list) {
583 ivi_application_send_wl_shell_info(resource, pid, window_title, id_surface);
588 get_wl_shell_info(struct ivi_layout_surface *layout_surface, uint32_t id_surface,
589 int32_t *pid_ret, const char **window_title_ret)
591 struct ivi_shell *shell = get_shell_instance();
592 struct ivi_layout_interface *ivi_layout = shell->ivi_layout;
593 struct weston_surface *surface;
594 struct wl_array shsurflist;
595 struct shell_surface **shsurface;
601 *window_title_ret = "";
603 if (layout_surface != NULL && id_surface > 0) {
604 surface = ivi_layout->get_weston_surface(layout_surface);
606 if (surface != NULL && surface->resource != NULL && surface->resource->client != NULL) {
607 wl_client_get_credentials(surface->resource->client, &pid, &uid, &gid);
611 ivi_shell_get_shell_surfaces(&shsurflist);
613 wl_array_for_each(shsurface, &shsurflist) {
614 if (surface == shell_surface_get_surface(*shsurface)) {
615 *window_title_ret = shell_surface_get_title(*shsurface);
620 wl_array_release(&shsurflist);
626 click_to_activate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
629 if (seat->pointer->grab != &seat->pointer->default_grab) {
632 if (seat->pointer->focus == NULL) {
636 weston_surface_activate(seat->pointer->focus->surface, seat);
640 * Initialization of ivi-shell.
643 ivi_load_modules(struct weston_compositor *compositor, const char *modules,
644 int *argc, char *argv[])
648 int (*module_init)(struct weston_compositor *compositor,
649 int *argc, char *argv[]);
656 end = strchrnul(p, ',');
657 snprintf(buffer, sizeof buffer, "%.*s", (int)(end - p), p);
659 module_init = weston_load_module(buffer, "module_init");
661 module_init(compositor, argc, argv);
672 module_init(struct weston_compositor *compositor,
673 int *argc, char *argv[])
675 char ivi_layout_path[PATH_MAX];
677 struct ivi_shell_setting setting = { };
679 struct ivi_shell *shell = get_shell_instance();
683 init_ivi_shell(compositor, shell);
685 shell->destroy_listener.notify = shell_destroy;
686 wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener);
688 if (input_panel_setup(shell) < 0)
691 if (wl_global_create(compositor->wl_display,
692 &ivi_application_interface, 1,
693 shell, bind_ivi_application) == NULL)
696 if (ivi_shell_setting_create(&setting, compositor) != 0)
700 * load module:ivi-layout
701 * ivi_layout_interface is referred by ivi-shell to use ivi-layout.
702 * The reason why the following code is written newly without
703 * using weston_load_module is it doesn't open library with
704 * RTLD_GLOBAL option.
706 snprintf(ivi_layout_path, sizeof ivi_layout_path,
707 "%s/%s", MODULEDIR, "ivi-layout.so");
708 module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_NOLOAD);
710 weston_log("ivi-shell: Module '%s' already loaded\n",
716 weston_log("ivi-shell: Loading module '%s'\n", ivi_layout_path);
717 module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_GLOBAL);
719 weston_log("ivi-shell: Failed to load module: %s\n", dlerror());
723 shell->ivi_layout = dlsym(module,"ivi_layout_interface");
724 if (!shell->ivi_layout){
725 weston_log("ivi-shell: couldn't find ivi_layout_interface in '%s'\n", ivi_layout_path);
726 free(setting.ivi_module);
731 shell->ivi_layout->init_with_compositor(compositor);
733 /* Call module_init of ivi-modules which are defined in weston.ini */
734 if (ivi_load_modules(compositor, setting.ivi_module, argc, argv) < 0) {
735 free(setting.ivi_module);
740 weston_compositor_add_button_binding(compositor, BTN_LEFT, 0, click_to_activate_binding, shell);
742 free(setting.ivi_module);
744 /* Initialize ivi-shell-ext. wl_shell is supported here */
745 return init_ivi_shell_ext(compositor, argc, argv);