X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fshell.c;h=aa63b86edc90bc85f4e385aba5db17916e3593af;hb=401773a463992f926086b178caff14dd55dbd148;hp=16b41467e2bd0104c59cdc2a8cebe1c2d6ef7de5;hpb=b43a012824af0165f3716c7986888213420885aa;p=src%2Fagl-compositor.git diff --git a/src/shell.c b/src/shell.c index 16b4146..aa63b86 100644 --- a/src/shell.c +++ b/src/shell.c @@ -33,12 +33,13 @@ #include #include #include -#include -#include +#include +#include #include "shared/os-compatibility.h" #include "agl-shell-server-protocol.h" +#include "agl-shell-desktop-server-protocol.h" static void create_black_surface_view(struct ivi_output *output); @@ -49,10 +50,78 @@ insert_black_surface(struct ivi_output *output); void ivi_set_desktop_surface(struct ivi_surface *surface) { + struct desktop_client *dclient; + 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); + + /* 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); + agl_shell_desktop_send_application(dclient->resource, app_id); + } +} + +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); +} + +static void +ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput, + int x, int y, 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; + + wl_list_insert(&ivi->popup_pending_apps, &p_popup->link); +} + +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); +} + +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); + + 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; + + ivi_remove_pending_desktop_surface_popup(p_popup); + return true; + } + } + + return false; } void @@ -73,6 +142,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, @@ -83,12 +153,26 @@ 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); + agl_shell_desktop_send_application(resource, app_id); + } +} + static void client_exec(const char *command, int fd) { @@ -285,7 +369,13 @@ shell_ready(struct wl_client *client, struct wl_resource *shell_res) wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) { wl_list_remove(&surface->link); - ivi_set_desktop_surface(surface); + + if (ivi_check_pending_desktop_surface_popup(surface)) { + ivi_set_desktop_surface_popup(surface); + } else { + ivi_set_desktop_surface(surface); + ivi_layout_desktop_committed(surface); + } } } @@ -419,6 +509,29 @@ shell_set_panel(struct wl_client *client, weston_desktop_surface_set_size(dsurface, width, height); } + +static 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); + + /* FIXME: should queue it here and see when binding agl-shell-desktop + * if there are any to be sent */ + if (!surf) + 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, @@ -432,6 +545,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, @@ -439,6 +580,27 @@ 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, 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); + + /* temporary store the app_id such that, when created to be check against */ + if (role == AGL_SHELL_DESKTOP_APP_ROLE_POPUP) + ivi_set_pending_desktop_surface_popup(output, x, y, app_id); +} + +static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = { + .activate_app = shell_desktop_activate_app, + .set_app_property = shell_desktop_set_app_property, + .deactivate_app = shell_deactivate_app, +}; + static void unbind_agl_shell(struct wl_resource *resource) { @@ -526,6 +688,46 @@ bind_agl_shell(struct wl_client *client, ivi->shell_client.resource = resource; } +static void +unbind_agl_shell_desktop(struct wl_resource *resource) +{ + struct desktop_client *dclient = wl_resource_get_user_data(resource); + + wl_list_remove(&dclient->link); + free(dclient); +} + +static void +bind_agl_shell_desktop(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +{ + struct ivi_compositor *ivi = data; + struct wl_resource *resource; + struct desktop_client *dclient = zalloc(sizeof(*dclient)); + + if (!dclient) { + wl_client_post_no_memory(client); + return; + } + + resource = wl_resource_create(client, &agl_shell_desktop_interface, + version, id); + dclient->ivi = ivi; + if (!resource) { + wl_client_post_no_memory(client); + return; + } + + wl_resource_set_implementation(resource, &agl_shell_desktop_implementation, + dclient, unbind_agl_shell_desktop); + + dclient->resource = resource; + wl_list_insert(&ivi->desktop_clients, &dclient->link); + + /* advertise xdg surfaces */ + ivi_shell_advertise_xdg_surfaces(ivi, resource); +} + int ivi_shell_create_global(struct ivi_compositor *ivi) { @@ -537,5 +739,13 @@ ivi_shell_create_global(struct ivi_compositor *ivi) return -1; } + ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display, + &agl_shell_desktop_interface, 1, + ivi, bind_agl_shell_desktop); + if (!ivi->agl_shell_desktop) { + weston_log("Failed to create wayland global (agl_shell_desktop).\n"); + return -1; + } + return 0; }