X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fshell.c;h=c29d89eabf2416548536d961735f1be1bd8b25bf;hb=7ec377fb843d18ac29cd756b5833d94185706602;hp=cce4decfa1573e97703ff3272c3edf0ae24d6cd1;hpb=000b725db81ae79ffec0a7a84a2c4aab2778dc82;p=src%2Fagl-compositor.git diff --git a/src/shell.c b/src/shell.c index cce4dec..c29d89e 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1,5 +1,5 @@ /* - * Copyright © 2019, 2022 Collabora, Ltd. + * Copyright © 2019, 2022, 2024 Collabora, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -52,6 +52,9 @@ create_black_curtain_view(struct ivi_output *output); static uint32_t reverse_orientation(uint32_t orientation); +const char * +split_orientation_to_string(uint32_t orientation); + void agl_shell_desktop_advertise_application_id(struct ivi_compositor *ivi, struct ivi_surface *surface) @@ -651,8 +654,18 @@ ivi_check_pending_desktop_surface(struct ivi_surface *surface) // handle the currently active surface if (papp->ioutput->active) { + int width_prev_app = 0; + + if (papp_tile->width > 0) { + if (papp_tile->orientation == AGL_SHELL_TILE_ORIENTATION_TOP || + papp_tile->orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM) + width_prev_app = papp->ioutput->area.height - papp_tile->width; + else + width_prev_app = papp->ioutput->area.width - papp_tile->width; + } _ivi_set_shell_surface_split(papp->ioutput->active, NULL, - reverse_orientation(papp_tile->orientation), false); + reverse_orientation(papp_tile->orientation), + width_prev_app, false, false); } surface->role = IVI_SURFACE_ROLE_TILE; @@ -660,7 +673,8 @@ ivi_check_pending_desktop_surface(struct ivi_surface *surface) wl_list_insert(&surface->ivi->surfaces, &surface->link); _ivi_set_shell_surface_split(surface, papp->ioutput, - papp_tile->orientation, true); + papp_tile->orientation, papp_tile->width, + papp_tile->sticky, true); /* remove it from pending */ wl_list_remove(&papp->link); @@ -764,7 +778,7 @@ ivi_shell_finalize(struct ivi_compositor *ivi) wl_list_for_each(output, &ivi->outputs, link) { if (output->fullscreen_view.fs && output->fullscreen_view.fs->view) { - weston_surface_destroy(output->fullscreen_view.fs->view->surface); + weston_surface_unref(output->fullscreen_view.fs->view->surface); output->fullscreen_view.fs->view = NULL; } } @@ -789,9 +803,9 @@ ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource static struct wl_client * client_launch(struct weston_compositor *compositor, - struct weston_process *proc, + struct wet_process *proc, const char *path, - weston_process_cleanup_func_t cleanup) + wet_process_cleanup_func_t cleanup) { struct wl_client *client = NULL; struct custom_env child_env; @@ -896,14 +910,14 @@ client_launch(struct weston_compositor *compositor, } struct process_info { - struct weston_process proc; + struct wet_process proc; char *path; }; int sigchld_handler(int signal_number, void *data) { - struct weston_process *p; + struct wet_process *p; struct ivi_compositor *ivi = data; int status; pid_t pid; @@ -921,7 +935,7 @@ sigchld_handler(int signal_number, void *data) wl_list_remove(&p->link); wl_list_init(&p->link); - p->cleanup(p, status); + p->cleanup(p, status, NULL); } if (pid < 0 && errno != ECHILD) @@ -932,7 +946,7 @@ sigchld_handler(int signal_number, void *data) static void -process_handle_sigchld(struct weston_process *process, int status) +process_handle_sigchld(struct wet_process *process, int status, void *data) { struct process_info *pinfo = container_of(process, struct process_info, proc); @@ -1008,41 +1022,72 @@ destroy_black_curtain_view(struct wl_listener *listener, void *data) } +int +curtain_get_label(struct weston_surface *surface, char *buf, size_t len) +{ + return snprintf(buf, len, "%s", "black curtain"); +} + +static void +curtain_surface_committed(struct weston_surface *es, struct weston_coord_surface new_origin) +{ + +} + + static void create_black_curtain_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_compositor *ec = ivi->compositor; struct weston_output *woutput = output->output; + struct weston_buffer_reference *buffer_ref; if (!woutput) return; - surface = weston_surface_create(wc); + surface = weston_surface_create(ec); if (!surface) return; + view = weston_view_create(surface); - if (!view) { - weston_surface_destroy(surface); - return; - } + if (!view) + goto err_surface; + + buffer_ref = weston_buffer_create_solid_rgba(ec, 0.0, 0.0, 0.0, 1.0); + if (buffer_ref == NULL) + goto err_view; - weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1); + surface->committed = curtain_surface_committed; + surface->committed_private = NULL; weston_surface_set_size(surface, woutput->width, woutput->height); - weston_view_set_position(view, woutput->x, woutput->y); + + weston_surface_attach_solid(surface, buffer_ref, + woutput->width, woutput->height); + + weston_surface_set_label_func(surface, curtain_get_label); + weston_view_set_position(view, woutput->pos); output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface)); - if (!output->fullscreen_view.fs) { - weston_surface_destroy(surface); - return; - } + if (!output->fullscreen_view.fs) + goto err_view; + output->fullscreen_view.fs->view = view; + output->fullscreen_view.buffer_ref = buffer_ref; - output->fullscreen_view.fs_destroy.notify = destroy_black_curtain_view; + output->fullscreen_view.fs_destroy.notify = + destroy_black_curtain_view; wl_signal_add(&woutput->destroy_signal, &output->fullscreen_view.fs_destroy); + + return; + +err_view: + weston_view_destroy(view); +err_surface: + weston_surface_unref(surface); } bool @@ -1058,6 +1103,7 @@ void remove_black_curtain(struct ivi_output *output) { struct weston_view *view; + struct weston_surface *wsurface; if ((!output && !output->fullscreen_view.fs && @@ -1068,17 +1114,13 @@ remove_black_curtain(struct ivi_output *output) } view = output->fullscreen_view.fs->view; + wsurface = view->surface; 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_view_damage_below(view); + weston_surface_unmap(wsurface); + weston_view_move_to_layer(view, NULL); weston_log("Removed black curtain from output %s\n", output->output->name); } @@ -1086,29 +1128,23 @@ void insert_black_curtain(struct ivi_output *output) { struct weston_view *view; + struct weston_surface *wsurface; if ((!output && !output->fullscreen_view.fs && - !output->fullscreen_view.fs->view) || !output->output || - !output->fullscreen_view.fs) { + !output->fullscreen_view.fs->view) || + !output->output || !output->fullscreen_view.fs) { weston_log("Output %s doesn't have a surface installed!\n", output->name); return; } view = output->fullscreen_view.fs->view; + wsurface = view->surface; 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_view_damage_below(view); - + weston_surface_map(wsurface); + weston_view_move_to_layer(view, &output->ivi->fullscreen.view_list); weston_log("Added black curtain to output %s\n", output->output->name); } @@ -1719,13 +1755,16 @@ static void shell_set_app_position(struct wl_client *client, struct wl_resource *res, const char *app_id, int32_t x, int32_t y) { + struct weston_coord_global pos; struct ivi_compositor *ivi = wl_resource_get_user_data(res); struct ivi_surface *surf = ivi_find_app(ivi, app_id); if (!surf || !app_id || surf->role != IVI_SURFACE_ROLE_POPUP) return; - weston_view_set_position(surf->view, x, y); + pos.c.x = x; + pos.c.y = y; + weston_view_set_position(surf->view, pos); weston_compositor_schedule_repaint(ivi->compositor); } @@ -1766,6 +1805,27 @@ _ivi_set_pending_desktop_surface_split(struct wl_resource *output, } +const char * +split_orientation_to_string(uint32_t orientation) +{ + switch (orientation) { + case AGL_SHELL_TILE_ORIENTATION_LEFT: + return "tile_left"; + break; + case AGL_SHELL_TILE_ORIENTATION_RIGHT: + return "tile_right"; + break; + case AGL_SHELL_TILE_ORIENTATION_TOP: + return "title_top"; + break; + case AGL_SHELL_TILE_ORIENTATION_BOTTOM: + return "tile_bottom"; + break; + default: + return "none"; + } +} + static uint32_t reverse_orientation(uint32_t orientation) { @@ -1790,13 +1850,16 @@ reverse_orientation(uint32_t orientation) void _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *ioutput, - uint32_t orientation, bool to_activate) + uint32_t orientation, uint32_t width, int32_t sticky, + bool to_activate) { struct ivi_compositor *ivi = surface->ivi; + struct weston_view *ev = surface->view; struct weston_geometry geom = {}; struct ivi_output *output = NULL; + struct weston_coord_global pos; - int width, height; + int new_width, new_height; int x, y; geom = weston_desktop_surface_get_geometry(surface->dsurface); @@ -1805,19 +1868,51 @@ _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *iou if (!output) output = ioutput; - width = output->area.width; - height = output->area.height; - + // if we don't supply a width we automatically default to doing a half + // split, each window taking half of the current output switch (orientation) { case AGL_SHELL_TILE_ORIENTATION_LEFT: case AGL_SHELL_TILE_ORIENTATION_RIGHT: - width /= 2; + if (width == 0) { + new_width = output->area.width / 2; + new_height = output->area.height; + } else { + new_width = width; + new_height = output->area.height; + } break; case AGL_SHELL_TILE_ORIENTATION_TOP: case AGL_SHELL_TILE_ORIENTATION_BOTTOM: - height /= 2; + if (width == 0) { + new_width = output->area.width; + new_height = output->area.height / 2; + } else { + new_width = output->area.width; + new_height = width; + } break; case AGL_SHELL_TILE_ORIENTATION_NONE: + /* use the current_completed_output because the sticky window + * might have changed the output area */ + new_width = surface->current_completed_output->area_activation.width; + new_height = surface->current_completed_output->area_activation.height; + + if (new_width != output->area.width) + output->area.width = new_width; + + if (new_height != output->area.height) + output->area.height = new_height; + + weston_log("Adjusting activation area " + "to %dX%d\n", output->area.width, output->area.height); + + if (surface->sticky) { + surface->sticky = 0; + weston_log("Resetting sticky window\n"); + } + + surface->role = surface->prev_role; + weston_log("Resetting tile role to previous role\n"); break; default: /* nothing */ @@ -1829,12 +1924,12 @@ _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *iou y = output->area.y - geom.y; if (orientation == AGL_SHELL_TILE_ORIENTATION_RIGHT) - x += width; + x += output->area.width - new_width; else if (orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM) - y += height; + y += output->area.height - new_height; + if (to_activate) { - struct weston_view *ev = surface->view; struct ivi_shell_seat *ivi_seat = NULL; struct weston_seat *wseat = get_ivi_shell_weston_first_seat(ivi); @@ -1867,16 +1962,38 @@ _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *iou ivi_shell_activate_surface(surface, ivi_seat, WESTON_ACTIVATE_FLAG_NONE); } - weston_view_set_position(surface->view, x, y); - weston_desktop_surface_set_size(surface->dsurface, width, height); + pos.c.x = x; + pos.c.y = y; + + weston_view_set_position(surface->view, pos); + weston_desktop_surface_set_size(surface->dsurface, new_width, new_height); weston_desktop_surface_set_orientation(surface->dsurface, orientation); surface->orientation = orientation; weston_compositor_schedule_repaint(ivi->compositor); - weston_log("%s() Setting to x=%d, y=%d, width=%d, height=%d, orientation=%d\n", - __func__, x, y, width, height, orientation); + if (sticky) + surface->sticky = sticky; + + if (orientation != AGL_SHELL_TILE_ORIENTATION_NONE) { + surface->prev_role = surface->role; + surface->role = IVI_SURFACE_ROLE_TILE; + weston_log("Found split orientation different that none, " + "setting surface role to orientation tile\n"); + } + + if (surface->sticky) { + if (orientation == AGL_SHELL_TILE_ORIENTATION_LEFT || + orientation == AGL_SHELL_TILE_ORIENTATION_RIGHT) + output->area.width -= new_width; + if (orientation == AGL_SHELL_TILE_ORIENTATION_TOP || + orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM) + output->area.height -= new_height; + + weston_log("Found sticky window, adjusting activation area " + "to %dX%d\n", output->area.width, output->area.height); + } } static int @@ -1921,24 +2038,51 @@ void shell_set_app_split(struct wl_client *client, struct wl_resource *res, return; } - if (output->previous_active) { + if (output->previous_active && output->background != output->previous_active) { + int width_prev_app = 0; struct weston_view *ev = output->previous_active->view; + const char *prev_app_id = + weston_desktop_surface_get_app_id(output->previous_active->dsurface); + + if (orientation != AGL_SHELL_TILE_ORIENTATION_NONE) { + if (!weston_view_is_mapped(ev)) + weston_view_update_transform(ev); + else + weston_layer_entry_remove(&ev->layer_link); + + ev->is_mapped = true; + ev->surface->is_mapped = true; + output->previous_active->mapped = true; + + weston_view_set_output(ev, woutput); + weston_layer_entry_insert(&ivi->normal.view_list, + &ev->layer_link); + } else { + ev->is_mapped = false; + ev->surface->is_mapped = false; - if (!weston_view_is_mapped(ev)) - weston_view_update_transform(ev); - else weston_layer_entry_remove(&ev->layer_link); - ev->is_mapped = true; - ev->surface->is_mapped = true; - output->previous_active->mapped = true; + weston_view_geometry_dirty(ev); + weston_surface_damage(ev->surface); + } - weston_view_set_output(ev, woutput); + /* a 0 width means we have no explicit width set-up */ + if (width > 0) { + if (orientation == AGL_SHELL_TILE_ORIENTATION_TOP || + orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM) + width_prev_app = output->area.height - width; + else + width_prev_app = output->area.width - width; + } - weston_layer_entry_insert(&ivi->normal.view_list, &ev->layer_link); + weston_log("Setting previous application '%s' to orientation '%s' width %d, not sticky\n", + prev_app_id, split_orientation_to_string(reverse_orientation(orientation)), + width_prev_app); _ivi_set_shell_surface_split(output->previous_active, NULL, - reverse_orientation(orientation), false); + reverse_orientation(orientation), + width_prev_app, false, false); if (orientation == AGL_SHELL_TILE_ORIENTATION_NONE && output->active == surf) { @@ -1946,7 +2090,10 @@ void shell_set_app_split(struct wl_client *client, struct wl_resource *res, } } - _ivi_set_shell_surface_split(surf, NULL, orientation, false); + weston_log("Setting application '%s' to orientation '%s' width %d, %s\n", + app_id, split_orientation_to_string(orientation), + width, sticky == 1 ? "sticky" : "not sticky"); + _ivi_set_shell_surface_split(surf, NULL, orientation, width, sticky, false); } static void