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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2758>
This commit is contained in:
Carlos Garnacho 2022-12-16 12:55:15 +01:00
parent 07e1f87e3b
commit 82b2b76882
3 changed files with 30 additions and 1 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}