[metacity] xrender: save shaded window as cairo surface
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity] xrender: save shaded window as cairo surface
- Date: Tue, 1 Oct 2019 18:46:09 +0000 (UTC)
commit 95733dac0d1dbc751b43e75ea9fef77e8475be9a
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Tue Oct 1 17:10:39 2019 +0300
xrender: save shaded window as cairo surface
src/compositor/meta-compositor-xrender.c | 388 ++++++++++++-------------------
1 file changed, 145 insertions(+), 243 deletions(-)
---
diff --git a/src/compositor/meta-compositor-xrender.c b/src/compositor/meta-compositor-xrender.c
index e06f4816..766238c6 100644
--- a/src/compositor/meta-compositor-xrender.c
+++ b/src/compositor/meta-compositor-xrender.c
@@ -123,21 +123,12 @@ typedef struct _MetaCompWindow
XserverRegion border_clip;
- /* When the window is shaded we will store few data of the original unshaded
- * window so we can still see what the window looked like when it is needed
- * for _get_window_surface function.
+ /* When the window is shaded back_pixmap will be replaced with the pixmap
+ * for the shaded window. This is a copy of the original unshaded window
+ * so that we can still see what the window looked like when it is needed
+ * for the _get_window_surface function.
*/
- struct {
- Pixmap back_pixmap;
- Pixmap mask_pixmap;
-
- int x;
- int y;
- int width;
- int height;
-
- XserverRegion client_region;
- } shaded;
+ cairo_surface_t *shaded_surface;
} MetaCompWindow;
struct _MetaCompositorXRender
@@ -1796,24 +1787,6 @@ free_win (MetaCompWindow *cw,
cw->extents = None;
}
- if (cw->shaded.back_pixmap && destroy)
- {
- XFreePixmap (xdisplay, cw->shaded.back_pixmap);
- cw->shaded.back_pixmap = None;
- }
-
- if (cw->shaded.mask_pixmap && destroy)
- {
- XFreePixmap (xdisplay, cw->shaded.mask_pixmap);
- cw->shaded.mask_pixmap = None;
- }
-
- if (cw->shaded.client_region && destroy)
- {
- XFixesDestroyRegion (xdisplay, cw->shaded.client_region);
- cw->shaded.client_region = None;
- }
-
if (destroy)
{
if (cw->damage != None)
@@ -1822,6 +1795,12 @@ free_win (MetaCompWindow *cw,
cw->damage = None;
}
+ if (cw->shaded_surface != NULL)
+ {
+ cairo_surface_destroy (cw->shaded_surface);
+ cw->shaded_surface = NULL;
+ }
+
g_free (cw);
}
@@ -1864,24 +1843,6 @@ map_win (MetaCompositorXRender *xrender,
XFixesDestroyRegion (xdisplay, cw->client_region);
cw->client_region = None;
}
-
- if (cw->shaded.back_pixmap)
- {
- XFreePixmap (xdisplay, cw->shaded.back_pixmap);
- cw->shaded.back_pixmap = None;
- }
-
- if (cw->shaded.mask_pixmap)
- {
- XFreePixmap (xdisplay, cw->shaded.mask_pixmap);
- cw->shaded.mask_pixmap = None;
- }
-
- if (cw->shaded.client_region)
- {
- XFixesDestroyRegion (xdisplay, cw->shaded.client_region);
- cw->shaded.client_region = None;
- }
}
static void
@@ -2048,24 +2009,6 @@ notify_decorated_cb (MetaWindow *window,
cw->border_clip = None;
}
- if (cw->shaded.back_pixmap != None)
- {
- XFreePixmap (xrender->xdisplay, cw->shaded.back_pixmap);
- cw->shaded.back_pixmap = None;
- }
-
- if (cw->shaded.mask_pixmap != None)
- {
- XFreePixmap (xrender->xdisplay, cw->shaded.mask_pixmap);
- cw->shaded.mask_pixmap = None;
- }
-
- if (cw->shaded.client_region != None)
- {
- XFixesDestroyRegion (xrender->xdisplay, cw->shaded.client_region);
- cw->shaded.client_region = None;
- }
-
cw->damage = XDamageCreate (xrender->xdisplay,
meta_window_get_toplevel_xwindow (window),
XDamageReportNonEmpty);
@@ -2080,6 +2023,125 @@ notify_decorated_cb (MetaWindow *window,
add_repair (xrender);
}
+static cairo_surface_t *
+get_window_surface (MetaCompWindow *cw)
+{
+ MetaFrame *frame;
+ MetaDisplay *display;
+ Display *xdisplay;
+ XserverRegion xclient_region;
+ cairo_region_t *client_region;
+ cairo_surface_t *back_surface;
+ cairo_surface_t *window_surface;
+ cairo_t *cr;
+
+ frame = meta_window_get_frame (cw->window);
+ display = meta_window_get_display (cw->window);
+ xdisplay = meta_display_get_xdisplay (display);
+
+ if (cw->back_pixmap == None)
+ return NULL;
+
+ if (frame != NULL && cw->mask_pixmap == None)
+ return NULL;
+
+ xclient_region = None;
+ if (cw->client_region != None)
+ {
+ xclient_region = XFixesCreateRegion (xdisplay, NULL, 0);
+ XFixesCopyRegion (xdisplay, xclient_region, cw->client_region);
+ XFixesTranslateRegion (xdisplay, xclient_region, -cw->rect.x, -cw->rect.y);
+ }
+
+ if (frame != NULL && xclient_region == None)
+ return NULL;
+
+ client_region = xserver_region_to_cairo_region (xdisplay, xclient_region);
+ XFixesDestroyRegion (xdisplay, xclient_region);
+
+ if (frame != NULL && client_region == NULL)
+ return NULL;
+
+ back_surface = cairo_xlib_surface_create (xdisplay, cw->back_pixmap,
+ get_toplevel_xvisual (cw->window),
+ cw->rect.width, cw->rect.height);
+
+ window_surface = cairo_surface_create_similar (back_surface,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ cw->rect.width,
+ cw->rect.height);
+
+ cr = cairo_create (window_surface);
+ cairo_set_source_surface (cr, back_surface, 0, 0);
+ cairo_paint (cr);
+
+ if (frame != NULL)
+ {
+ cairo_region_t *region;
+ Screen *xscreen;
+ XRenderPictFormat *format;
+ cairo_surface_t *mask;
+
+ region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+ .width = cw->rect.width,
+ .height = cw->rect.height
+ });
+
+ cairo_region_subtract (region, client_region);
+
+ xscreen = DefaultScreenOfDisplay (xdisplay);
+ format = XRenderFindStandardFormat (xdisplay, PictStandardA8);
+ mask = cairo_xlib_surface_create_with_xrender_format (xdisplay,
+ cw->mask_pixmap,
+ xscreen, format,
+ cw->rect.width,
+ cw->rect.height);
+
+ gdk_cairo_region (cr, region);
+ cairo_clip (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_set_source_surface (cr, back_surface, 0, 0);
+ cairo_mask_surface (cr, mask, 0, 0);
+ cairo_fill (cr);
+
+ cairo_surface_destroy (mask);
+ cairo_region_destroy (region);
+ }
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (back_surface);
+ cairo_region_destroy (client_region);
+
+ return window_surface;
+}
+
+static void
+notify_shaded_cb (MetaWindow *window,
+ GParamSpec *pspec,
+ MetaCompositorXRender *xrender)
+{
+ MetaCompWindow *cw;
+
+ cw = find_comp_window_by_window (xrender, window);
+
+ if (cw == NULL)
+ return;
+
+ if (cw->shaded_surface != NULL)
+ {
+ cairo_surface_destroy (cw->shaded_surface);
+ cw->shaded_surface = NULL;
+ }
+
+ if (meta_window_is_shaded (cw->window))
+ cw->shaded_surface = get_window_surface (cw);
+}
+
/* event processors must all be called with an error trap in place */
static void
process_property_notify (MetaCompositorXRender *xrender,
@@ -2394,6 +2456,10 @@ meta_compositor_xrender_add_window (MetaCompositor *compositor,
G_CALLBACK (notify_decorated_cb),
xrender, 0);
+ g_signal_connect_object (window, "notify::shaded",
+ G_CALLBACK (notify_shaded_cb),
+ xrender, 0);
+
cw->back_pixmap = None;
cw->mask_pixmap = None;
@@ -2431,13 +2497,7 @@ meta_compositor_xrender_add_window (MetaCompositor *compositor,
cw->border_clip = None;
- cw->shaded.back_pixmap = None;
- cw->shaded.mask_pixmap = None;
- cw->shaded.x = 0;
- cw->shaded.y = 0;
- cw->shaded.width = 0;
- cw->shaded.height = 0;
- cw->shaded.client_region = None;
+ cw->shaded_surface = NULL;
determine_mode (xrender, cw);
cw->needs_shadow = window_has_shadow (xrender, cw);
@@ -2660,123 +2720,22 @@ static cairo_surface_t *
meta_compositor_xrender_get_window_surface (MetaCompositor *compositor,
MetaWindow *window)
{
- MetaFrame *frame;
MetaCompWindow *cw;
- MetaDisplay *display;
- Display *xdisplay;
- gboolean shaded;
- Pixmap back_pixmap;
- Pixmap mask_pixmap;
- int width;
- int height;
- XserverRegion xclient_region;
- cairo_region_t *client_region;
- cairo_surface_t *back_surface;
- cairo_surface_t *window_surface;
- cairo_t *cr;
- frame = meta_window_get_frame (window);
cw = find_comp_window_by_window (META_COMPOSITOR_XRENDER (compositor), window);
if (cw == NULL)
return NULL;
- display = meta_compositor_get_display (compositor);
- xdisplay = meta_display_get_xdisplay (display);
- shaded = meta_window_is_shaded (window);
-
- back_pixmap = shaded ? cw->shaded.back_pixmap : cw->back_pixmap;
- if (back_pixmap == None)
- return NULL;
-
- mask_pixmap = shaded ? cw->shaded.mask_pixmap : cw->mask_pixmap;
- if (frame != NULL && mask_pixmap == None)
- return NULL;
-
- xclient_region = None;
- if (shaded)
- {
- if (cw->shaded.client_region != None)
- {
- xclient_region = XFixesCreateRegion (xdisplay, NULL, 0);
- XFixesCopyRegion (xdisplay, xclient_region, cw->shaded.client_region);
- XFixesTranslateRegion (xdisplay, xclient_region,
- -cw->shaded.x, -cw->shaded.y);
- }
- }
- else
- {
- if (cw->client_region != None)
- {
- xclient_region = XFixesCreateRegion (xdisplay, NULL, 0);
- XFixesCopyRegion (xdisplay, xclient_region, cw->client_region);
- XFixesTranslateRegion (xdisplay, xclient_region,
- -cw->rect.x, -cw->rect.y);
- }
- }
-
- if (frame != NULL && xclient_region == None)
- return NULL;
-
- client_region = xserver_region_to_cairo_region (xdisplay, xclient_region);
- XFixesDestroyRegion (xdisplay, xclient_region);
-
- if (frame != NULL && client_region == NULL)
- return NULL;
-
- width = shaded ? cw->shaded.width : cw->rect.width;
- height = shaded ? cw->shaded.height : cw->rect.height;
-
- back_surface = cairo_xlib_surface_create (xdisplay, back_pixmap,
- get_toplevel_xvisual (cw->window),
- width, height);
-
- window_surface = cairo_surface_create_similar (back_surface,
- CAIRO_CONTENT_COLOR_ALPHA,
- width, height);
-
- cr = cairo_create (window_surface);
- cairo_set_source_surface (cr, back_surface, 0, 0);
- cairo_paint (cr);
-
- if (frame != NULL)
+ if (meta_window_is_shaded (window))
{
- cairo_rectangle_int_t rect = { 0, 0, width, height};
- cairo_region_t *region;
- Screen *xscreen;
- XRenderPictFormat *format;
- cairo_surface_t *mask;
-
- region = cairo_region_create_rectangle (&rect);
- cairo_region_subtract (region, client_region);
-
- xscreen = DefaultScreenOfDisplay (xdisplay);
- format = XRenderFindStandardFormat (xdisplay, PictStandardA8);
- mask = cairo_xlib_surface_create_with_xrender_format (xdisplay, mask_pixmap,
- xscreen, format,
- width, height);
-
- gdk_cairo_region (cr, region);
- cairo_clip (cr);
-
- cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
- cairo_set_source_rgba (cr, 0, 0, 0, 0);
- cairo_paint (cr);
-
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_set_source_surface (cr, back_surface, 0, 0);
- cairo_mask_surface (cr, mask, 0, 0);
- cairo_fill (cr);
-
- cairo_surface_destroy (mask);
- cairo_region_destroy (region);
+ if (cw->shaded_surface != NULL)
+ return cairo_surface_reference (cw->shaded_surface);
+ else
+ return NULL;
}
- cairo_destroy (cr);
- cairo_surface_destroy (back_surface);
- cairo_region_destroy (client_region);
-
- return window_surface;
+ return get_window_surface (cw);
}
static void
@@ -2852,73 +2811,16 @@ meta_compositor_xrender_sync_window_geometry (MetaCompositor *compositor,
if (cw->rect.width != old_rect.width || cw->rect.height != old_rect.height)
{
- if (cw->shaded.back_pixmap != None)
- {
- XFreePixmap (xrender->xdisplay, cw->shaded.back_pixmap);
- cw->shaded.back_pixmap = None;
- }
-
- if (cw->shaded.mask_pixmap != None)
- {
- XFreePixmap (xrender->xdisplay, cw->shaded.mask_pixmap);
- cw->shaded.mask_pixmap = None;
- }
-
- if (cw->shaded.client_region != None)
- {
- XFixesDestroyRegion (xrender->xdisplay, cw->shaded.client_region);
- cw->shaded.client_region = None;
- }
-
if (cw->back_pixmap != None)
{
- /* If the window is shaded, we store the old backing pixmap
- * so we can return a proper image of the window
- */
- if (meta_window_is_shaded (cw->window))
- {
- cw->shaded.back_pixmap = cw->back_pixmap;
- cw->back_pixmap = None;
- }
- else
- {
- XFreePixmap (xrender->xdisplay, cw->back_pixmap);
- cw->back_pixmap = None;
- }
+ XFreePixmap (xrender->xdisplay, cw->back_pixmap);
+ cw->back_pixmap = None;
}
if (cw->mask_pixmap != None)
{
- /* If the window is shaded, we store the old backing pixmap
- * so we can return a proper image of the window
- */
- if (meta_window_is_shaded (cw->window))
- {
- cw->shaded.mask_pixmap = cw->mask_pixmap;
- cw->mask_pixmap = None;
- }
- else
- {
- XFreePixmap (xrender->xdisplay, cw->mask_pixmap);
- cw->mask_pixmap = None;
- }
- }
-
- if (meta_window_is_shaded (cw->window))
- {
- cw->shaded.x = old_rect.x;
- cw->shaded.y = old_rect.y;
- cw->shaded.width = old_rect.width;
- cw->shaded.height = old_rect.height;
-
- if (cw->client_region != None)
- {
- cw->shaded.client_region = XFixesCreateRegion (xrender->xdisplay,
- NULL, 0);
-
- XFixesCopyRegion (xrender->xdisplay, cw->shaded.client_region,
- cw->client_region);
- }
+ XFreePixmap (xrender->xdisplay, cw->mask_pixmap);
+ cw->mask_pixmap = None;
}
if (cw->picture != None)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]