From 82b2b7688246668b4e050f0a9650ae1bcfbbaa89 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 16 Dec 2022 12:55:15 +0100 Subject: [PATCH] core: Add infrastructure to keep window frames' opaque regions These frames client will use a visual with alpha information, and report the opaque frame shapes through the _NET_WM_OPAQUE_REGION window property. We can use this information in the Mutter side for accurate opaque shapes, despite X11 windows with frames now being seen as possibly transparent. Part-of: --- src/core/frame.c | 20 ++++++++++++++++++++ src/core/frame.h | 5 +++++ src/x11/window-props.c | 6 +++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/core/frame.c b/src/core/frame.c index 470f5d174..760d89701 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -26,6 +26,7 @@ #include "core/frame.h" #include "backends/x11/meta-backend-x11.h" +#include "compositor/compositor-private.h" #include "core/bell.h" #include "core/keybindings-private.h" #include "meta/meta-x11-errors.h" @@ -232,6 +233,8 @@ meta_window_destroy_frame (MetaWindow *window) window->frame_bounds = NULL; } + g_clear_pointer (&window->opaque_region, cairo_region_destroy); + /* Move keybindings to window instead of frame */ meta_window_grab_keys (window); @@ -600,3 +603,20 @@ meta_frame_get_sync_counter (MetaFrame *frame) { return &frame->sync_counter; } + +void +meta_frame_set_opaque_region (MetaFrame *frame, + cairo_region_t *region) +{ + MetaWindow *window = frame->window; + + if (cairo_region_equal (frame->opaque_region, region)) + return; + + g_clear_pointer (&frame->opaque_region, cairo_region_destroy); + + if (region != NULL) + frame->opaque_region = cairo_region_reference (region); + + meta_compositor_window_shape_changed (window->display->compositor, window); +} diff --git a/src/core/frame.h b/src/core/frame.h index 023e2f4e4..2f292d2d2 100644 --- a/src/core/frame.h +++ b/src/core/frame.h @@ -41,6 +41,8 @@ struct _MetaFrame MetaFrameBorders cached_borders; /* valid if borders_cached is set */ + cairo_region_t *opaque_region; + MetaSyncCounter sync_counter; /* position of client, size of frame */ @@ -81,4 +83,7 @@ GSubprocess * meta_frame_launch_client (MetaX11Display *x11_display, MetaSyncCounter * meta_frame_get_sync_counter (MetaFrame *frame); +void meta_frame_set_opaque_region (MetaFrame *frame, + cairo_region_t *region); + #endif diff --git a/src/x11/window-props.c b/src/x11/window-props.c index 60910cebe..26a110785 100644 --- a/src/x11/window-props.c +++ b/src/x11/window-props.c @@ -710,7 +710,11 @@ reload_opaque_region (MetaWindow *window, } out: - meta_window_set_opaque_region (window, opaque_region); + if (value->source_xwindow == window->xwindow) + meta_window_set_opaque_region (window, opaque_region); + else if (window->frame && value->source_xwindow == window->frame->xwindow) + meta_frame_set_opaque_region (window->frame, opaque_region); + cairo_region_destroy (opaque_region); }