X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fshell.c;h=5a8cc42215f7d257c1ed00f7971ef2288387b8a0;hb=bdd8dd718496dc8e4330209c46c196442bcf7d3e;hp=9100ad797dd73d14b2bc865c9a7bab1558197b2e;hpb=a35a7f2e5cc20bd40ece91918e753c709e2ee10b;p=src%2Fagl-compositor.git diff --git a/src/shell.c b/src/shell.c index 9100ad7..5a8cc42 100644 --- a/src/shell.c +++ b/src/shell.c @@ -24,6 +24,7 @@ */ #include "ivi-compositor.h" +#include "policy.h" #include #include @@ -41,19 +42,460 @@ #include "agl-shell-server-protocol.h" #include "agl-shell-desktop-server-protocol.h" +#ifdef HAVE_WALTHAM +#include +#endif + static void create_black_surface_view(struct ivi_output *output); -static void -insert_black_surface(struct ivi_output *output); +void +agl_shell_desktop_advertise_application_id(struct ivi_compositor *ivi, + struct ivi_surface *surface) +{ + struct desktop_client *dclient; + static bool display_adv = false; + + if (surface->advertised_on_launch) + return; + + /* advertise to all desktop clients the new surface */ + wl_list_for_each(dclient, &ivi->desktop_clients, link) { + const char *app_id = + weston_desktop_surface_get_app_id(surface->dsurface); + if (app_id == NULL) { + if (!display_adv) { + weston_log("WARNING app_is is null, unable to advertise\n"); + display_adv = true; + } + return; + } + agl_shell_desktop_send_application(dclient->resource, app_id); + surface->advertised_on_launch = true; + } +} void ivi_set_desktop_surface(struct ivi_surface *surface) { + struct ivi_compositor *ivi = surface->ivi; assert(surface->role == IVI_SURFACE_ROLE_NONE); surface->role = IVI_SURFACE_ROLE_DESKTOP; wl_list_insert(&surface->ivi->surfaces, &surface->link); + + agl_shell_desktop_advertise_application_id(ivi, surface); +} + +static void +ivi_set_desktop_surface_popup(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + assert(surface->role == IVI_SURFACE_ROLE_NONE); + + surface->role = IVI_SURFACE_ROLE_POPUP; + wl_list_insert(&ivi->surfaces, &surface->link); + + agl_shell_desktop_advertise_application_id(ivi, surface); +} + +static void +ivi_set_desktop_surface_fullscreen(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + assert(surface->role == IVI_SURFACE_ROLE_NONE); + + surface->role = IVI_SURFACE_ROLE_FULLSCREEN; + wl_list_insert(&ivi->surfaces, &surface->link); + + agl_shell_desktop_advertise_application_id(ivi, surface); +} + +#ifdef HAVE_WALTHAM +void +ivi_destroy_waltham_destroy(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + const struct weston_transmitter_api *api = + ivi->waltham_transmitter_api; + + if (!api) + return; + + if (surface->waltham_surface.transmitter_surface) + api->surface_destroy(surface->waltham_surface.transmitter_surface); +} + +static void +ivi_output_notify_waltham_plugin(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + const struct weston_transmitter_api *api = ivi->waltham_transmitter_api; + struct weston_transmitter *transmitter; + struct weston_transmitter_remote *trans_remote; + struct weston_surface *weston_surface; + struct weston_output *woutput = surface->remote.output->output; + const char *app_id; + + if (!api) + return; + + transmitter = api->transmitter_get(ivi->compositor); + if (!transmitter) + return; + + trans_remote = api->get_transmitter_remote(woutput->name, transmitter); + if (!trans_remote) { + weston_log("Could not find a valie weston_transmitter_remote " + "that matches the output %s\n", woutput->name); + return; + } + + app_id = weston_desktop_surface_get_app_id(surface->dsurface); + weston_surface = + weston_desktop_surface_get_surface(surface->dsurface); + + weston_log("Forwarding app_id %s to remote %s\n", app_id, woutput->name); + + /* this will have the effect of informing the remote side to create a + * surface with the name app_id. W/ xdg-shell the following happens: + * + * compositor (server): + * surface_push_to_remote(): + * waltham-transmitter plug-in + * -> wthp_ivi_app_id_surface_create() + * + * client -- on the receiver side: + * -> wthp_ivi_app_id_surface_create() + * -> wth_receiver_weston_main() + * -> wl_compositor_create_surface() + * -> xdg_wm_base_get_xdg_surface + * -> xdg_toplevel_set_app_id() + * -> gst_init() + * -> gst_parse_launch() + * + * wth_receiver_weston_main() will be invoked from the handler of + * wthp_ivi_app_id_surface_create() and is responsible for setting-up + * the gstreamer pipeline as well. + */ + surface->waltham_surface.transmitter_surface = + api->surface_push_to_remote(weston_surface, app_id, trans_remote, NULL); +} + +#else +void +ivi_destroy_waltham_destroy(struct ivi_surface *surface) +{ +} +static void +ivi_output_notify_waltham_plugin(struct ivi_surface *surface) +{ +} +#endif + +static void +ivi_set_desktop_surface_remote(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + struct weston_view *view; + struct ivi_output *output = surface->remote.output; + + assert(surface->role == IVI_SURFACE_ROLE_NONE); + + /* remote type are the same as desktop just that client can tell + * the compositor to start on another output */ + surface->role = IVI_SURFACE_ROLE_REMOTE; + + /* if thew black surface view is mapped on the mean we need + * to remove it in order to start showing the 'remote' surface + * just being added */ + view = output->fullscreen_view.fs->view; + if (view->is_mapped || view->surface->is_mapped) + remove_black_surface(output); + + if (output->type == OUTPUT_WALTHAM) + ivi_output_notify_waltham_plugin(surface); + + wl_list_insert(&ivi->surfaces, &surface->link); +} + + +static void +ivi_set_desktop_surface_split(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + assert(surface->role == IVI_SURFACE_ROLE_NONE); + + if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL) + surface->role = IVI_SURFACE_ROLE_SPLIT_V; + else + surface->role = IVI_SURFACE_ROLE_SPLIT_H; + + wl_list_insert(&ivi->surfaces, &surface->link); + + agl_shell_desktop_advertise_application_id(ivi, surface); +} + +static void +ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput, + int x, int y, int bx, int by, int width, int height, + const char *app_id) +{ + struct ivi_compositor *ivi = ioutput->ivi; + size_t len_app_id = strlen(app_id); + + struct pending_popup *p_popup = zalloc(sizeof(*p_popup)); + + p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1)); + memcpy(p_popup->app_id, app_id, len_app_id); + p_popup->ioutput = ioutput; + p_popup->x = x; + p_popup->y = y; + + p_popup->bb.x = bx; + p_popup->bb.y = by; + p_popup->bb.width = width; + p_popup->bb.height = height; + + wl_list_insert(&ivi->popup_pending_apps, &p_popup->link); +} + +static void +ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput, + const char *app_id) +{ + struct ivi_compositor *ivi = ioutput->ivi; + size_t len_app_id = strlen(app_id); + + struct pending_fullscreen *fs = zalloc(sizeof(*fs)); + + fs->app_id = zalloc(sizeof(char) * (len_app_id + 1)); + memcpy(fs->app_id, app_id, len_app_id); + + fs->ioutput = ioutput; + + wl_list_insert(&ivi->fullscreen_pending_apps, &fs->link); +} + +static void +ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput, + const char *app_id, uint32_t orientation) +{ + struct ivi_compositor *ivi = ioutput->ivi; + struct ivi_surface *surf; + size_t len_app_id = strlen(app_id); + struct pending_split *split; + + if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL && + orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL) + return; + + /* more than one is un-supported, do note we need to do + * conversion for surface roles instead of using the protocol ones */ + wl_list_for_each(surf, &ivi->surfaces, link) + if (surf->role == IVI_SURFACE_ROLE_SPLIT_V || + surf->role == IVI_SURFACE_ROLE_SPLIT_H) + return; + + split = zalloc(sizeof(*split)); + split->app_id = zalloc(sizeof(char) * (len_app_id + 1)); + memcpy(split->app_id, app_id, len_app_id); + + split->ioutput = ioutput; + split->orientation = orientation; + + wl_list_insert(&ivi->split_pending_apps, &split->link); +} + +void +ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput, + const char *app_id) +{ + struct ivi_compositor *ivi = ioutput->ivi; + size_t len_app_id = strlen(app_id); + + struct pending_remote *remote = zalloc(sizeof(*remote)); + + remote->app_id = zalloc(sizeof(char) * (len_app_id + 1)); + memcpy(remote->app_id, app_id, len_app_id); + + remote->ioutput = ioutput; + + wl_list_insert(&ivi->remote_pending_apps, &remote->link); +} + + +static void +ivi_remove_pending_desktop_surface_split(struct pending_split *split) +{ + free(split->app_id); + wl_list_remove(&split->link); + free(split); +} + +static void +ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs) +{ + free(fs->app_id); + wl_list_remove(&fs->link); + free(fs); +} + +static void +ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup) +{ + free(p_popup->app_id); + wl_list_remove(&p_popup->link); + free(p_popup); +} + +static void +ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote) +{ + free(remote->app_id); + wl_list_remove(&remote->link); + free(remote); +} + +static bool +ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + struct pending_popup *p_popup, *next_p_popup; + const char *_app_id = + weston_desktop_surface_get_app_id(surface->dsurface); + + if (wl_list_empty(&ivi->popup_pending_apps) || !_app_id) + return false; + + wl_list_for_each_safe(p_popup, next_p_popup, + &ivi->popup_pending_apps, link) { + if (!strcmp(_app_id, p_popup->app_id)) { + surface->popup.output = p_popup->ioutput; + surface->popup.x = p_popup->x; + surface->popup.y = p_popup->y; + + surface->popup.bb.x = p_popup->bb.x; + surface->popup.bb.y = p_popup->bb.y; + surface->popup.bb.width = p_popup->bb.width; + surface->popup.bb.height = p_popup->bb.height; + + ivi_remove_pending_desktop_surface_popup(p_popup); + return true; + } + } + + return false; +} + +static bool +ivi_check_pending_desktop_surface_split(struct ivi_surface *surface) +{ + struct pending_split *split_surf, *next_split_surf; + struct ivi_compositor *ivi = surface->ivi; + const char *_app_id = + weston_desktop_surface_get_app_id(surface->dsurface); + + if (wl_list_empty(&ivi->split_pending_apps) || !_app_id) + return false; + + wl_list_for_each_safe(split_surf, next_split_surf, + &ivi->split_pending_apps, link) { + if (!strcmp(_app_id, split_surf->app_id)) { + surface->split.output = split_surf->ioutput; + surface->split.orientation = split_surf->orientation; + ivi_remove_pending_desktop_surface_split(split_surf); + return true; + } + } + + return false; +} + +static bool +ivi_check_pending_desktop_surface_fullscreen(struct ivi_surface *surface) +{ + struct pending_fullscreen *fs_surf, *next_fs_surf; + struct ivi_compositor *ivi = surface->ivi; + const char *_app_id = + weston_desktop_surface_get_app_id(surface->dsurface); + + if (wl_list_empty(&ivi->fullscreen_pending_apps) || !_app_id) + return false; + + wl_list_for_each_safe(fs_surf, next_fs_surf, + &ivi->fullscreen_pending_apps, link) { + if (!strcmp(_app_id, fs_surf->app_id)) { + surface->fullscreen.output = fs_surf->ioutput; + ivi_remove_pending_desktop_surface_fullscreen(fs_surf); + return true; + } + } + + return false; +} + +static bool +ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface) +{ + struct pending_remote *remote_surf, *next_remote_surf; + struct ivi_compositor *ivi = surface->ivi; + const char *_app_id = + weston_desktop_surface_get_app_id(surface->dsurface); + + if (wl_list_empty(&ivi->remote_pending_apps) || !_app_id) + return false; + + wl_list_for_each_safe(remote_surf, next_remote_surf, + &ivi->remote_pending_apps, link) { + if (!strcmp(_app_id, remote_surf->app_id)) { + surface->remote.output = remote_surf->ioutput; + ivi_remove_pending_desktop_surface_remote(remote_surf); + return true; + } + } + + return false; +} + + +void +ivi_check_pending_desktop_surface(struct ivi_surface *surface) +{ + bool ret = false; + + ret = ivi_check_pending_desktop_surface_popup(surface); + if (ret) { + ivi_set_desktop_surface_popup(surface); + ivi_layout_popup_committed(surface); + return; + } + + ret = ivi_check_pending_desktop_surface_split(surface); + if (ret) { + ivi_set_desktop_surface_split(surface); + ivi_layout_split_committed(surface); + return; + } + + ret = ivi_check_pending_desktop_surface_fullscreen(surface); + if (ret) { + ivi_set_desktop_surface_fullscreen(surface); + ivi_layout_fullscreen_committed(surface); + return; + } + + ret = ivi_check_pending_desktop_surface_remote(surface); + if (ret) { + ivi_set_desktop_surface_remote(surface); + ivi_layout_desktop_committed(surface); + return; + } + + /* if we end up here means we have a regular desktop app and + * try to activate it */ + ivi_set_desktop_surface(surface); + ivi_layout_desktop_committed(surface); } void @@ -74,6 +516,7 @@ ivi_shell_init(struct ivi_compositor *ivi) weston_layer_init(&ivi->background, ivi->compositor); weston_layer_init(&ivi->normal, ivi->compositor); weston_layer_init(&ivi->panel, ivi->compositor); + weston_layer_init(&ivi->popup, ivi->compositor); weston_layer_init(&ivi->fullscreen, ivi->compositor); weston_layer_set_position(&ivi->hidden, @@ -84,12 +527,30 @@ ivi_shell_init(struct ivi_compositor *ivi) WESTON_LAYER_POSITION_NORMAL); weston_layer_set_position(&ivi->panel, WESTON_LAYER_POSITION_UI); + weston_layer_set_position(&ivi->popup, + WESTON_LAYER_POSITION_TOP_UI); weston_layer_set_position(&ivi->fullscreen, WESTON_LAYER_POSITION_FULLSCREEN); return 0; } +static void +ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource) +{ + struct ivi_surface *surface; + + wl_list_for_each(surface, &ivi->surfaces, link) { + const char *app_id = + weston_desktop_surface_get_app_id(surface->dsurface); + if (app_id == NULL) { + weston_log("WARNING app_is is null, unable to advertise\n"); + return; + } + agl_shell_desktop_send_application(resource, app_id); + } +} + static void client_exec(const char *command, int fd) { @@ -193,13 +654,8 @@ destroy_black_view(struct wl_listener *listener, void *data) if (fs && fs->fs) { - if (fs->fs->view && fs->fs->view->surface) { - weston_surface_destroy(fs->fs->view->surface); - fs->fs->view = NULL; - } - - free(fs->fs); wl_list_remove(&fs->fs_destroy.link); + free(fs->fs); } } @@ -213,6 +669,9 @@ create_black_surface_view(struct ivi_output *output) struct weston_compositor *wc= ivi->compositor; struct weston_output *woutput = output->output; + if (!woutput) + return; + surface = weston_surface_create(wc); view = weston_view_create(surface); @@ -230,11 +689,19 @@ create_black_surface_view(struct ivi_output *output) &output->fullscreen_view.fs_destroy); } -static void +void remove_black_surface(struct ivi_output *output) { - struct weston_view *view = output->fullscreen_view.fs->view; + struct weston_view *view; + + if (!output && + !output->fullscreen_view.fs && + !output->fullscreen_view.fs->view) { + weston_log("Output %s doesn't have a surface installed!\n", output->name); + return; + } + view = output->fullscreen_view.fs->view; assert(view->is_mapped == true || view->surface->is_mapped == true); @@ -247,11 +714,19 @@ remove_black_surface(struct ivi_output *output) weston_output_damage(output->output); } -static void +void insert_black_surface(struct ivi_output *output) { - struct weston_view *view = output->fullscreen_view.fs->view; + struct weston_view *view; + if ((!output && + !output->fullscreen_view.fs && + !output->fullscreen_view.fs->view) || !output->output) { + weston_log("Output %s doesn't have a surface installed!\n", output->name); + return; + } + + view = output->fullscreen_view.fs->view; if (view->is_mapped || view->surface->is_mapped) return; @@ -280,13 +755,16 @@ shell_ready(struct wl_client *client, struct wl_resource *shell_res) ivi->shell_client.ready = true; wl_list_for_each(output, &ivi->outputs, link) { - remove_black_surface(output); + if (output->background) + remove_black_surface(output); ivi_layout_init(ivi, output); } wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) { wl_list_remove(&surface->link); - ivi_set_desktop_surface(surface); + wl_list_init(&surface->link); + ivi_check_pending_desktop_surface(surface); + surface->checked_pending = true; } } @@ -326,6 +804,7 @@ shell_set_background(struct wl_client *client, return; } + surface->checked_pending = true; surface->role = IVI_SURFACE_ROLE_BACKGROUND; surface->bg.output = output; wl_list_remove(&surface->link); @@ -398,6 +877,7 @@ shell_set_panel(struct wl_client *client, return; } + surface->checked_pending = true; surface->role = IVI_SURFACE_ROLE_PANEL; surface->panel.output = output; surface->panel.edge = edge; @@ -420,6 +900,37 @@ shell_set_panel(struct wl_client *client, weston_desktop_surface_set_size(dsurface, width, height); } +void +shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id, + const char *data, uint32_t app_state) +{ + struct desktop_client *dclient; + uint32_t app_role; + struct ivi_surface *surf = ivi_find_app(ivi, app_id); + struct ivi_policy *policy = ivi->policy; + + /* FIXME: should queue it here and see when binding agl-shell-desktop + * if there are any to be sent */ + if (!surf) + return; + + if (!app_id) + return; + + if (policy && policy->api.surface_advertise_state_change && + !policy->api.surface_advertise_state_change(surf, surf->ivi)) { + return; + } + + app_role = surf->role; + if (app_role == IVI_SURFACE_ROLE_POPUP) + app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP; + + wl_list_for_each(dclient, &ivi->desktop_clients, link) + agl_shell_desktop_send_state_app(dclient->resource, app_id, + data, app_state, app_role); +} + static void shell_activate_app(struct wl_client *client, struct wl_resource *shell_res, @@ -433,6 +944,34 @@ shell_activate_app(struct wl_client *client, ivi_layout_activate(output, app_id); } +static void +shell_desktop_activate_app(struct wl_client *client, + struct wl_resource *shell_res, + const char *app_id, const char *data, + struct wl_resource *output_res) +{ + struct weston_head *head = weston_head_from_resource(output_res); + struct weston_output *woutput = weston_head_get_output(head); + struct ivi_output *output = to_ivi_output(woutput); + + ivi_layout_activate(output, app_id); + shell_advertise_app_state(output->ivi, app_id, + data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED); +} + +static void +shell_deactivate_app(struct wl_client *client, + struct wl_resource *shell_res, + const char *app_id) +{ + struct desktop_client *dclient = wl_resource_get_user_data(shell_res); + struct ivi_compositor *ivi = dclient->ivi; + + ivi_layout_deactivate(ivi, app_id); + shell_advertise_app_state(ivi, app_id, + NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED); +} + static const struct agl_shell_interface agl_shell_implementation = { .ready = shell_ready, .set_background = shell_set_background, @@ -440,8 +979,42 @@ static const struct agl_shell_interface agl_shell_implementation = { .activate_app = shell_activate_app, }; +static void +shell_desktop_set_app_property(struct wl_client *client, + struct wl_resource *shell_res, + const char *app_id, uint32_t role, + int x, int y, int bx, int by, + int width, int height, + struct wl_resource *output_res) +{ + struct weston_head *head = weston_head_from_resource(output_res); + struct weston_output *woutput = weston_head_get_output(head); + struct ivi_output *output = to_ivi_output(woutput); + + switch (role) { + case AGL_SHELL_DESKTOP_APP_ROLE_POPUP: + ivi_set_pending_desktop_surface_popup(output, x, y, bx, by, + width, height, app_id); + break; + case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN: + ivi_set_pending_desktop_surface_fullscreen(output, app_id); + break; + case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL: + case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL: + ivi_set_pending_desktop_surface_split(output, app_id, role); + break; + case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE: + ivi_set_pending_desktop_surface_remote(output, app_id); + break; + default: + break; + } +} + static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = { - .activate_app = shell_activate_app, + .activate_app = shell_desktop_activate_app, + .set_app_property = shell_desktop_set_app_property, + .deactivate_app = shell_deactivate_app, }; static void @@ -453,21 +1026,6 @@ unbind_agl_shell(struct wl_resource *resource) ivi = wl_resource_get_user_data(resource); wl_list_for_each(output, &ivi->outputs, link) { - free(output->background); - output->background = NULL; - - free(output->top); - output->top = NULL; - - free(output->bottom); - output->bottom = NULL; - - free(output->left); - output->left = NULL; - - free(output->right); - output->right = NULL; - /* reset the active surf if there's one present */ if (output->active) { output->active->view->is_mapped = false; @@ -504,6 +1062,17 @@ bind_agl_shell(struct wl_client *client, { struct ivi_compositor *ivi = data; struct wl_resource *resource; + struct ivi_policy *policy; + void *interface; + + policy = ivi->policy; + interface = (void *) &agl_shell_interface; + if (policy && policy->api.shell_bind_interface && + !policy->api.shell_bind_interface(client, interface)) { + wl_client_post_implementation_error(client, + "client not authorized to use agl_shell"); + return; + } resource = wl_resource_create(client, &agl_shell_interface, 1, id); @@ -546,8 +1115,20 @@ bind_agl_shell_desktop(struct wl_client *client, { struct ivi_compositor *ivi = data; struct wl_resource *resource; - struct desktop_client *dclient = zalloc(sizeof(*dclient)); + struct ivi_policy *policy; + struct desktop_client *dclient; + void *interface; + + policy = ivi->policy; + interface = (void *) &agl_shell_desktop_interface; + if (policy && policy->api.shell_bind_interface && + !policy->api.shell_bind_interface(client, interface)) { + wl_client_post_implementation_error(client, + "client not authorized to use agl_shell_desktop"); + return; + } + dclient = zalloc(sizeof(*dclient)); if (!dclient) { wl_client_post_no_memory(client); return; @@ -555,6 +1136,7 @@ bind_agl_shell_desktop(struct wl_client *client, resource = wl_resource_create(client, &agl_shell_desktop_interface, version, id); + dclient->ivi = ivi; if (!resource) { wl_client_post_no_memory(client); return; @@ -565,6 +1147,9 @@ bind_agl_shell_desktop(struct wl_client *client, dclient->resource = resource; wl_list_insert(&ivi->desktop_clients, &dclient->link); + + /* advertise xdg surfaces */ + ivi_shell_advertise_xdg_surfaces(ivi, resource); } int