From 2b6651327e91c72a68a98dbd51c60ac1615e0d13 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 16 Dec 2022 13:06:22 +0100 Subject: [PATCH] compositor: Observe frame opaque region when updating shapes Apply either frame or client window opaque regions (or both as an union). For client windows without an alpha channel, the frame shape already contains the client area. If the client window does have an alpha channel, the client rectangle is cleared to let the client's opaque region take care of it. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2555 Part-of: --- src/compositor/meta-window-actor-x11.c | 56 +++++++++++++++++--------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c index 71fde8d38..8f538f3df 100644 --- a/src/compositor/meta-window-actor-x11.c +++ b/src/compositor/meta-window-actor-x11.c @@ -990,35 +990,53 @@ update_opaque_region (MetaWindowActorX11 *actor_x11) MetaWindow *window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); gboolean is_maybe_transparent; - cairo_region_t *opaque_region; + cairo_region_t *opaque_region = NULL; MetaSurfaceActor *surface; is_maybe_transparent = is_actor_maybe_transparent (actor_x11); - if (is_maybe_transparent && window->opaque_region) + if (is_maybe_transparent && + (window->opaque_region || + (window->frame && window->frame->opaque_region))) { cairo_rectangle_int_t client_area; + if (window->frame && window->frame->opaque_region) + opaque_region = cairo_region_copy (window->frame->opaque_region); + get_client_area_rect (actor_x11, &client_area); - /* The opaque region is defined to be a part of the - * window which ARGB32 will always paint with opaque - * pixels. For these regions, we want to avoid painting - * windows and shadows beneath them. - * - * If the client gives bad coordinates where it does not - * fully paint, the behavior is defined by the specification - * to be undefined, and considered a client bug. In mutter's - * case, graphical glitches will occur. - */ - opaque_region = cairo_region_copy (window->opaque_region); - cairo_region_translate (opaque_region, client_area.x, client_area.y); + if (opaque_region && meta_window_x11_has_alpha_channel (window)) + cairo_region_subtract_rectangle (opaque_region, &client_area); + + if (window->opaque_region) + { + cairo_region_t *client_opaque_region; + + /* The opaque region is defined to be a part of the + * window which ARGB32 will always paint with opaque + * pixels. For these regions, we want to avoid painting + * windows and shadows beneath them. + * + * If the client gives bad coordinates where it does not + * fully paint, the behavior is defined by the specification + * to be undefined, and considered a client bug. In mutter's + * case, graphical glitches will occur. + */ + client_opaque_region = cairo_region_copy (window->opaque_region); + cairo_region_translate (client_opaque_region, + client_area.x, client_area.y); + + if (opaque_region) + cairo_region_union (opaque_region, client_opaque_region); + else + opaque_region = cairo_region_reference (client_opaque_region); + + cairo_region_destroy (client_opaque_region); + } + cairo_region_intersect (opaque_region, actor_x11->shape_region); } - else if (is_maybe_transparent) - { - opaque_region = NULL; - } - else + else if (!is_maybe_transparent) { opaque_region = cairo_region_reference (actor_x11->shape_region); }