X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fshell.c;h=cc7b33b4a8c2e0b2ba223d714c193ea6d9effd31;hb=786f91bd280b83049e5f60b3e8e88f81ab80e94c;hp=cac8fa2c7651ebff7295448a7681cd7c8181b773;hpb=aa4ba5d283d641da25722af7a966c31d61a9686b;p=src%2Fagl-compositor.git diff --git a/src/shell.c b/src/shell.c index cac8fa2..cc7b33b 100644 --- a/src/shell.c +++ b/src/shell.c @@ -33,149 +33,60 @@ #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); + +static void +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); -} -/* TODO: Replace this with some callback or similar, to have - * adjustable window management policy. - */ -void -ivi_reflow_outputs(struct ivi_compositor *ivi) -{ - struct ivi_surface *surface; - struct ivi_output *output; - int i = 0; - - if (wl_list_empty(&ivi->outputs)) - return; - - output = wl_container_of(ivi->outputs.next, output, link); - - wl_list_for_each(surface, &ivi->surfaces, link) { - struct weston_desktop_surface *dsurface = surface->dsurface; - - int32_t w = output->area.width / 4; - int32_t h = output->area.height / 2; - int32_t x = output->output->x + output->area.x + w * (i % 4); - int32_t y = output->output->y + output->area.y + h * (i / 4); - - if (surface->old_geom.width == -1) { - weston_desktop_surface_set_size(dsurface, w, h); - continue; - } else { - ivi_layout_set_mapped(surface); - ivi_layout_set_position(surface, x, y, w, h); - } - - if (++i == 8) { - if (output->link.next == &ivi->outputs) - break; - - output = wl_container_of(output->link.next, - output, link); - i = 0; - } + /* 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); } - - ivi_layout_commit(ivi); -} - -void -ivi_layout_set_mapped(struct ivi_surface *surface) -{ - surface->pending.flags |= IVI_SURFACE_PROP_MAP; -} - -void -ivi_layout_set_position(struct ivi_surface *surface, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - surface->pending.flags |= IVI_SURFACE_PROP_POSITION; - surface->pending.x = x; - surface->pending.y = y; - surface->pending.width = width; - surface->pending.height = height; } void -ivi_layout_commit(struct ivi_compositor *ivi) +ivi_shell_init_black_fs(struct ivi_compositor *ivi) { - struct ivi_surface *surface; - - wl_list_for_each(surface, &ivi->surfaces, link) { - struct weston_desktop_surface *dsurface = surface->dsurface; - struct weston_surface *wsurface = - weston_desktop_surface_get_surface(dsurface); - struct weston_geometry geom; - struct weston_view *view; - - /* - * TODO: Hoist view into ivi_struct. It doesn't need ot be part - * of the tagged union. - */ - switch (surface->role) { - case IVI_SURFACE_ROLE_DESKTOP: - view = surface->desktop.view; - break; - case IVI_SURFACE_ROLE_BACKGROUND: - view = surface->bg.view; - break; - case IVI_SURFACE_ROLE_PANEL: - view = surface->panel.view; - break; - default: - continue; - } - - if (surface->pending.flags & IVI_SURFACE_PROP_MAP) { - view = weston_desktop_surface_create_view(dsurface); - wsurface->is_mapped = true; - - surface->desktop.view = view; - weston_layer_entry_insert(&ivi->normal.view_list, - &view->layer_link); - weston_view_update_transform(view); - weston_view_set_mask_infinite(view); - weston_view_schedule_repaint(view); - } - - geom = weston_desktop_surface_get_geometry(dsurface); - - if (surface->pending.flags & IVI_SURFACE_PROP_POSITION) { - weston_desktop_surface_set_size(dsurface, - surface->pending.width, - surface->pending.height); - weston_view_set_position(view, - surface->pending.x - geom.x, - surface->pending.y - geom.y); - } + struct ivi_output *out; - surface->pending.flags = 0; + wl_list_for_each(out, &ivi->outputs, link) { + create_black_surface_view(out); + insert_black_surface(out); } } int ivi_shell_init(struct ivi_compositor *ivi) { + weston_layer_init(&ivi->hidden, ivi->compositor); 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->fullscreen, ivi->compositor); + weston_layer_set_position(&ivi->hidden, + WESTON_LAYER_POSITION_HIDDEN); weston_layer_set_position(&ivi->background, WESTON_LAYER_POSITION_BACKGROUND); weston_layer_set_position(&ivi->normal, @@ -188,6 +99,18 @@ ivi_shell_init(struct ivi_compositor *ivi) 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) { @@ -283,6 +206,87 @@ ivi_launch_shell_client(struct ivi_compositor *ivi) return 0; } +static void +destroy_black_view(struct wl_listener *listener, void *data) +{ + struct fullscreen_view *fs = + wl_container_of(listener, fs, fs_destroy); + + + 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); + } +} + + +static void +create_black_surface_view(struct ivi_output *output) +{ + struct weston_surface *surface = NULL; + struct weston_view *view; + struct ivi_compositor *ivi = output->ivi; + struct weston_compositor *wc= ivi->compositor; + struct weston_output *woutput = output->output; + + surface = weston_surface_create(wc); + view = weston_view_create(surface); + + assert(view || surface); + + weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1); + weston_surface_set_size(surface, woutput->width, woutput->height); + weston_view_set_position(view, woutput->x, woutput->y); + + output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface)); + output->fullscreen_view.fs->view = view; + + output->fullscreen_view.fs_destroy.notify = destroy_black_view; + wl_signal_add(&woutput->destroy_signal, + &output->fullscreen_view.fs_destroy); +} + +static void +remove_black_surface(struct ivi_output *output) +{ + struct weston_view *view = output->fullscreen_view.fs->view; + + assert(view->is_mapped == true || + view->surface->is_mapped == true); + + view->is_mapped = false; + view->surface->is_mapped = false; + + weston_layer_entry_remove(&view->layer_link); + weston_view_update_transform(view); + + weston_output_damage(output->output); +} + +static void +insert_black_surface(struct ivi_output *output) +{ + struct weston_view *view = output->fullscreen_view.fs->view; + + if (view->is_mapped || view->surface->is_mapped) + return; + + weston_layer_entry_remove(&view->layer_link); + weston_layer_entry_insert(&output->ivi->fullscreen.view_list, + &view->layer_link); + + view->is_mapped = true; + view->surface->is_mapped = true; + + weston_view_update_transform(view); + weston_output_damage(output->output); +} + static void shell_ready(struct wl_client *client, struct wl_resource *shell_res) { @@ -295,47 +299,10 @@ shell_ready(struct wl_client *client, struct wl_resource *shell_res) return; ivi->shell_client.ready = true; - /* TODO: Create a black screen and remove it here */ wl_list_for_each(output, &ivi->outputs, link) { - struct weston_desktop_surface *dsurf; - struct weston_geometry geom; - - output->area.x = 0; - output->area.y = 0; - output->area.width = output->output->width; - output->area.height = output->output->height; - - if (output->top) { - dsurf = output->top->dsurface; - geom = weston_desktop_surface_get_geometry(dsurf); - - output->area.y += geom.height; - output->area.height -= geom.height; - } - if (output->bottom) { - dsurf = output->bottom->dsurface; - geom = weston_desktop_surface_get_geometry(dsurf); - - output->area.height -= geom.height; - } - if (output->left) { - dsurf = output->left->dsurface; - geom = weston_desktop_surface_get_geometry(dsurf); - - output->area.x += geom.width; - output->area.width -= geom.width; - } - if (output->right) { - dsurf = output->right->dsurface; - geom = weston_desktop_surface_get_geometry(dsurf); - - output->area.width -= geom.width; - } - - weston_log("Usable area: %dx%d+%d,%d\n", - output->area.width, output->area.height, - output->area.x, output->area.y); + remove_black_surface(output); + ivi_layout_init(ivi, output); } wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) { @@ -474,15 +441,82 @@ shell_set_panel(struct wl_client *client, weston_desktop_surface_set_size(dsurface, width, height); } +static void +shell_activate_app(struct wl_client *client, + struct wl_resource *shell_res, + const char *app_id, + 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); +} + static const struct agl_shell_interface agl_shell_implementation = { .ready = shell_ready, .set_background = shell_set_background, .set_panel = shell_set_panel, + .activate_app = shell_activate_app, +}; + +static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = { + .activate_app = shell_activate_app, }; static void unbind_agl_shell(struct wl_resource *resource) { + struct ivi_compositor *ivi; + struct ivi_output *output; + struct ivi_surface *surf, *surf_tmp; + + 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; + output->active->view->surface->is_mapped = false; + + weston_layer_entry_remove(&output->active->view->layer_link); + output->active = NULL; + } + + insert_black_surface(output); + } + + wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) { + wl_list_remove(&surf->link); + wl_list_init(&surf->link); + } + + wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) { + wl_list_remove(&surf->link); + wl_list_init(&surf->link); + } + + wl_list_init(&ivi->surfaces); + wl_list_init(&ivi->pending_surfaces); + + ivi->shell_client.ready = false; + ivi->shell_client.resource = NULL; + ivi->shell_client.client = NULL; } static void @@ -518,6 +552,45 @@ 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); + 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) { @@ -529,5 +602,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; }