From 0ff5ac0f7b07d719d0e034f30900612be4f7499c Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Mon, 2 Dec 2024 11:05:49 -0600 Subject: [PATCH] desktop-shell: Add a placeholder curtain on new outputs Desktop-shell currently waits for the desktop-shell client to set up a background image. But the outputs are enabled before this happens, which forces a repaint. If the fade animation is enabled, there's a fade curtain in place, but if it's disabled the scene graph is empty at the repaint. This repaint with an empty scene graph can have very nasty consequences, especially if frame buffer compression is in use, as the buffer isn't rendered into and can be in an undefined state that confuses whatever video hardware is trying to decode the buffer. Add a temporary black curtain placeholder that ensures the scene graph has something in it before the client gets a chance to commit the real background. Signed-off-by: Derek Foreman --- desktop-shell/shell.c | 33 +++++++++++++++++++++++++++++++++ desktop-shell/shell.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 7fdb04866..9ffc771c9 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -2795,6 +2795,11 @@ background_committed(struct weston_surface *es, sh_output->background_view = weston_view_create(es); } + if (sh_output->temporary_curtain) { + weston_shell_utils_curtain_destroy(sh_output->temporary_curtain); + sh_output->temporary_curtain = NULL; + } + assert(sh_output->background_view); weston_view_set_position(sh_output->background_view, sh_output->output->pos); @@ -4573,6 +4578,10 @@ shell_output_destroy(struct shell_output *shell_output) wl_list_remove(&shell_output->background_surface_listener.link); shell_output->background_surface->committed_private = NULL; } + if (shell_output->temporary_curtain) { + weston_shell_utils_curtain_destroy(shell_output->temporary_curtain); + shell_output->temporary_curtain = NULL; + } wl_list_remove(&shell_output->destroy_listener.link); wl_list_remove(&shell_output->link); free(shell_output); @@ -4640,11 +4649,19 @@ handle_output_resized(struct wl_listener *listener, void *data) shell_resize_surface_to_output(shell, sh_output->panel_surface, output); } +static int +desktop_shell_temporary_curtain_get_label(struct weston_surface *surface, + char *buf, size_t len) +{ + return snprintf(buf, len, "desktop shell background placeholder"); +} + static void create_shell_output(struct desktop_shell *shell, struct weston_output *output) { struct shell_output *shell_output; + struct weston_curtain_params curtain_params = {}; shell_output = zalloc(sizeof *shell_output); if (shell_output == NULL) @@ -4660,6 +4677,22 @@ create_shell_output(struct desktop_shell *shell, if (wl_list_length(&shell->output_list) == 1) shell_for_each_layer(shell, shell_output_changed_move_layer, NULL); + + curtain_params.a = 1.0; + curtain_params.pos = output->pos; + curtain_params.width = output->width; + curtain_params.height = output->height; + curtain_params.capture_input = true; + curtain_params.get_label = desktop_shell_temporary_curtain_get_label; + shell_output->temporary_curtain = + weston_shell_utils_curtain_create(output->compositor, + &curtain_params); + weston_surface_set_role(shell_output->temporary_curtain->view->surface, + "desktop-shell-background-placeholder", NULL, 0); + shell_output->temporary_curtain->view->surface->output = output; + weston_view_move_to_layer(shell_output->temporary_curtain->view, + &shell->background_layer.view_list); + weston_view_set_output(shell_output->temporary_curtain->view, output); } static void diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h index fc34eb458..37b6ea303 100644 --- a/desktop-shell/shell.h +++ b/desktop-shell/shell.h @@ -74,6 +74,8 @@ struct shell_output { struct weston_surface *background_surface; struct weston_view *background_view; struct wl_listener background_surface_listener; + + struct weston_curtain *temporary_curtain; }; struct weston_desktop;