From c1bcce6a259fa658129e6356098c3985dc50b0a0 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 7 Dec 2017 15:30:18 +0200 Subject: [PATCH] clients/desktop-shell: preserve background/panel in clone mode In shared-CRTC clone mode there are several wl_output globals for one weston_output. Only one panel and background is needed per weston_output, so the extra wl_outputs do not get their own panel and background. When a head is unplugged, the corresponding wl_output is removed. If that was the wl_output associated with the background and panel surfaces, we must transfer the ownership to a remaining wl_output that was a clone to avoid losing the background and panel completely. The transfer relies on desktop-shell.so implementation to register background and panel surfaces with the weston_output, not the weston_head, so it does not actually matter the wl_output used to bind the surfaces is going away. Signed-off-by: Pekka Paalanen Reviewed-by: Daniel Stone --- clients/desktop-shell.c | 50 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index d75c8631..cabe851f 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -128,6 +128,8 @@ struct output { uint32_t server_output_id; struct wl_list link; + int x; + int y; struct panel *panel; struct background *background; }; @@ -1245,6 +1247,9 @@ output_handle_geometry(void *data, { struct output *output = data; + output->x = x; + output->y = y; + if (output->panel) window_set_buffer_transform(output->panel->window, transform); if (output->background) @@ -1328,6 +1333,49 @@ create_output(struct desktop *desktop, uint32_t id) output_init(output, desktop); } +static void +output_remove(struct desktop *desktop, struct output *output) +{ + struct output *cur; + struct output *rep = NULL; + + if (!output->background) { + output_destroy(output); + return; + } + + /* Find a wl_output that is a clone of the removed wl_output. + * We don't want to leave the clone without a background or panel. */ + wl_list_for_each(cur, &desktop->outputs, link) { + if (cur == output) + continue; + + /* XXX: Assumes size matches. */ + if (cur->x == output->x && cur->y == output->y) { + rep = cur; + break; + } + } + + if (rep) { + /* If found, hand over the background and panel so they don't + * get destroyed. */ + assert(!rep->background); + assert(!rep->panel); + + rep->background = output->background; + output->background = NULL; + rep->background->owner = rep; + + rep->panel = output->panel; + output->panel = NULL; + if (rep->panel) + rep->panel->owner = rep; + } + + output_destroy(output); +} + static void global_handler(struct display *display, uint32_t id, const char *interface, uint32_t version, void *data) @@ -1357,7 +1405,7 @@ global_handler_remove(struct display *display, uint32_t id, if (!strcmp(interface, "wl_output")) { wl_list_for_each(output, &desktop->outputs, link) { if (output->server_output_id == id) { - output_destroy(output); + output_remove(desktop, output); break; } }