From ed50cbbfe4e58e1c424d906a33d3e592207c41bf Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Tue, 19 Dec 2023 23:30:58 +0100 Subject: [PATCH] window-actor/wayland: Update scanout candidate check In a following commit we will start supporting scaled and croped surfaces, thus, in preparation, update the logic to three common cases: 1. only one surface, fullscreen (most apps) 2. a content surface and a black background surface which the client does not want to unmap, fullscreen 3. top-level subsurface covers the whole window and is opaque (Firefox) The remaining currently supported cases should be fairly uncommen and and harder to compute. Note that we already check that the window cover the stage view in MetaCompositorView. Part-of: --- src/compositor/meta-window-actor-wayland.c | 55 +++++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c index 805578f0a..b19e361fd 100644 --- a/src/compositor/meta-window-actor-wayland.c +++ b/src/compositor/meta-window-actor-wayland.c @@ -25,6 +25,8 @@ #include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-window-actor-wayland.h" #include "meta/meta-window-actor.h" +#include "wayland/meta-wayland-buffer.h" +#include "wayland/meta-wayland-single-pixel-buffer.h" #include "wayland/meta-wayland-surface-private.h" #include "wayland/meta-window-wayland.h" @@ -348,8 +350,10 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) ClutterActor *child_actor; ClutterActorIter iter; MetaSurfaceActor *topmost_surface_actor = NULL; - MetaWindow *window; int n_mapped_surfaces = 0; + MetaWindow *window; + ClutterActorBox window_box; + ClutterActorBox surface_box; if (clutter_actor_get_last_child (CLUTTER_ACTOR (self)) != surface_container) { @@ -376,15 +380,52 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) } window = meta_window_actor_get_meta_window (actor); - if (!meta_surface_actor_is_opaque (topmost_surface_actor) && - !(meta_window_is_fullscreen (window) && n_mapped_surfaces == 1)) + if (meta_window_is_fullscreen (window) && n_mapped_surfaces == 1) + return topmost_surface_actor; + + if (meta_window_is_fullscreen (window) && n_mapped_surfaces == 2) { - meta_topic (META_DEBUG_RENDER, - "Window-actor is not opaque"); - return NULL; + MetaSurfaceActorWayland *bg_surface_actor = NULL; + MetaWaylandSurface *bg_surface; + MetaWaylandBuffer *buffer; + + clutter_actor_iter_init (&iter, surface_container); + while (clutter_actor_iter_next (&iter, &child_actor)) + { + if (!clutter_actor_is_mapped (child_actor)) + continue; + + bg_surface_actor = META_SURFACE_ACTOR_WAYLAND (child_actor); + break; + } + g_assert (bg_surface_actor); + + bg_surface = meta_surface_actor_wayland_get_surface (bg_surface_actor); + buffer = meta_wayland_surface_get_buffer (bg_surface); + if (buffer->type == META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL) + { + MetaWaylandSinglePixelBuffer *sp_buffer; + + sp_buffer = meta_wayland_single_pixel_buffer_from_buffer (buffer); + if (sp_buffer && + meta_wayland_single_pixel_buffer_is_opaque_black (sp_buffer)) + return topmost_surface_actor; + } } - return topmost_surface_actor; + if (meta_surface_actor_is_opaque (topmost_surface_actor) && + clutter_actor_get_paint_box (CLUTTER_ACTOR (actor), &window_box) && + clutter_actor_get_paint_box (CLUTTER_ACTOR (topmost_surface_actor), + &surface_box) && + G_APPROX_VALUE (window_box.x1, surface_box.x1, CLUTTER_COORDINATE_EPSILON) && + G_APPROX_VALUE (window_box.y1, surface_box.y1, CLUTTER_COORDINATE_EPSILON) && + G_APPROX_VALUE (window_box.x2, surface_box.x2, CLUTTER_COORDINATE_EPSILON) && + G_APPROX_VALUE (window_box.y2, surface_box.y2, CLUTTER_COORDINATE_EPSILON)) + return topmost_surface_actor; + + meta_topic (META_DEBUG_RENDER, + "Could not find suitable scanout candidate for window-actor"); + return NULL; } static void