diff options
author | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2019-10-22 23:45:02 +0300 |
---|---|---|
committer | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2019-10-22 23:45:02 +0300 |
commit | 16a3262615e7d1cf5de89a6e9cc8d58ad5c6ad2c (patch) | |
tree | c419aa98a17ea28d7931440e2f9163f5065cef5a /src/compositor | |
parent | e944c77e505306615e7eb35c3f4c47375a82ec3b (diff) | |
download | metacity-16a3262615e7d1cf5de89a6e9cc8d58ad5c6ad2c.tar.gz |
compositor-xrender: move shadow to MetaShadowXRender
Diffstat (limited to 'src/compositor')
-rw-r--r-- | src/compositor/meta-compositor-xrender.c | 200 | ||||
-rw-r--r-- | src/compositor/meta-shadow-xrender.c | 78 | ||||
-rw-r--r-- | src/compositor/meta-shadow-xrender.h | 54 |
3 files changed, 226 insertions, 106 deletions
diff --git a/src/compositor/meta-compositor-xrender.c b/src/compositor/meta-compositor-xrender.c index 51063ca9..1585fae6 100644 --- a/src/compositor/meta-compositor-xrender.c +++ b/src/compositor/meta-compositor-xrender.c @@ -39,6 +39,7 @@ #include "prefs.h" #include "window-private.h" #include "meta-compositor-xrender.h" +#include "meta-shadow-xrender.h" #include "meta-surface-xrender.h" #include "xprops.h" #include "util.h" @@ -87,13 +88,7 @@ typedef struct _MetaCompWindow MetaRectangle rect; - XserverRegion shadow_region; - - Picture shadow; - int shadow_dx; - int shadow_dy; - int shadow_width; - int shadow_height; + MetaShadowXRender *shadow; gboolean shadow_changed; } MetaCompWindow; @@ -113,7 +108,6 @@ struct _MetaCompositorXRender Picture root_picture; Picture root_buffer; - Picture black_picture; Picture root_tile; gboolean prefs_listener_added; @@ -737,6 +731,7 @@ shadow_changed (MetaSurface *surface) MetaCompositor *compositor; MetaCompositorXRender *xrender; MetaCompWindow *cw; + XserverRegion shadow_region; compositor = meta_surface_get_compositor (surface); xrender = META_COMPOSITOR_XRENDER (compositor); @@ -746,78 +741,89 @@ shadow_changed (MetaSurface *surface) cw = g_object_get_data (G_OBJECT (surface), "cw"); - if (cw->shadow_region != None) + if (cw->shadow == NULL) { - meta_compositor_add_damage (compositor, "shadow_changed", cw->shadow_region); - XFixesDestroyRegion (xrender->xdisplay, cw->shadow_region); - cw->shadow_region = None; + meta_compositor_queue_redraw (compositor); + return; } - if (cw->shadow != None) - { - XRenderFreePicture (xrender->xdisplay, cw->shadow); - cw->shadow = None; - } + shadow_region = meta_shadow_xrender_get_region (cw->shadow); + XFixesTranslateRegion (xrender->xdisplay, shadow_region, cw->rect.x, cw->rect.y); + meta_compositor_add_damage (compositor, "shadow_changed", shadow_region); + XFixesDestroyRegion (xrender->xdisplay, shadow_region); - meta_compositor_queue_redraw (compositor); + meta_shadow_xrender_free (cw->shadow); + cw->shadow = NULL; cw->shadow_changed = TRUE; } -static XserverRegion -get_shadow_region (MetaCompositorXRender *xrender, - MetaCompWindow *cw, - MetaShadowType shadow_type) +static MetaShadowXRender * +create_shadow (MetaCompositorXRender *xrender, + MetaSurface *surface, + MetaShadowType shadow_type) { - MetaFrame *frame; + MetaWindow *window; MetaFrameBorders borders; - XRectangle sr; - Display *xdisplay; - XserverRegion shadow_region; + GtkBorder *invisible; + double opacity; + int width; + int height; + MetaShadowXRender *ret; cairo_region_t *frame_bounds; - frame = meta_window_get_frame (cw->window); - meta_frame_calc_borders (frame, &borders); + window = meta_surface_get_window (surface); - cw->shadow_dx = (int) shadow_offsets_x [shadow_type] + borders.invisible.left; - cw->shadow_dy = (int) shadow_offsets_y [shadow_type] + borders.invisible.top; + meta_frame_calc_borders (window->frame, &borders); + invisible = &borders.invisible; - if (!cw->shadow) - { - double opacity = SHADOW_OPACITY; - int invisible_width = borders.invisible.left + borders.invisible.right; - int invisible_height = borders.invisible.top + borders.invisible.bottom; + opacity = SHADOW_OPACITY; + if (window->opacity != OPAQUE) + opacity = opacity * ((double) window->opacity) / OPAQUE; - if (cw->window->opacity != (guint) OPAQUE) - opacity = opacity * ((double) cw->window->opacity) / ((double) OPAQUE); + width = meta_surface_get_width (surface); + height = meta_surface_get_height (surface); - cw->shadow = shadow_picture (xrender, shadow_type, opacity, - cw->rect.width - invisible_width, - cw->rect.height - invisible_height, - &cw->shadow_width, &cw->shadow_height); - } + ret = g_new0 (MetaShadowXRender, 1); + ret->xdisplay = xrender->xdisplay; - sr.x = cw->shadow_dx; - sr.y = cw->shadow_dy; - sr.width = cw->shadow_width; - sr.height = cw->shadow_height; + ret->dx = shadow_offsets_x[shadow_type] + invisible->left; + ret->dy = shadow_offsets_y[shadow_type] + invisible->top; - xdisplay = xrender->xdisplay; - shadow_region = XFixesCreateRegion (xdisplay, &sr, 1); - frame_bounds = meta_window_get_frame_bounds (cw->window); + ret->black = solid_picture (xrender->xdisplay, TRUE, 1, 0, 0, 0); + ret->shadow = shadow_picture (xrender, + shadow_type, + opacity, + width - invisible->left - invisible->right, + height - invisible->top - invisible->bottom, + &ret->width, + &ret->height); + + ret->region = XFixesCreateRegion (xrender->xdisplay, &(XRectangle) { + .x = ret->dx, + .y = ret->dy, + .width = ret->width, + .height = ret->height + }, 1); + + frame_bounds = meta_window_get_frame_bounds (window); if (frame_bounds != NULL) { XserverRegion bounds_region; - bounds_region = cairo_region_to_xserver_region (xdisplay, frame_bounds); - XFixesSubtractRegion (xdisplay, shadow_region, shadow_region, bounds_region); - XFixesDestroyRegion (xdisplay, bounds_region); - } + bounds_region = cairo_region_to_xserver_region (xrender->xdisplay, + frame_bounds); - XFixesTranslateRegion (xdisplay, shadow_region, cw->rect.x, cw->rect.y); + XFixesSubtractRegion (xrender->xdisplay, + ret->region, + ret->region, + bounds_region); - return shadow_region; + XFixesDestroyRegion (xrender->xdisplay, bounds_region); + } + + return ret; } static void @@ -827,21 +833,18 @@ paint_shadow (MetaCompositorXRender *xrender, Picture paint_buffer) { MetaCompWindow *cw; - XserverRegion shadow_clip; XserverRegion border_clip; - int x; - int y; + XserverRegion shadow_clip; cw = g_object_get_data (G_OBJECT (surface_xrender), "cw"); - if (cw->shadow == None) + if (cw->shadow == NULL) return; - shadow_clip = XFixesCreateRegion (xrender->xdisplay, NULL, 0); - XFixesCopyRegion (xrender->xdisplay, shadow_clip, cw->shadow_region); - border_clip = meta_surface_xrender_get_border_clip (surface_xrender); - XFixesIntersectRegion (xrender->xdisplay, shadow_clip, shadow_clip, border_clip); + + shadow_clip = XFixesCreateRegion (xrender->xdisplay, NULL, 0); + XFixesCopyRegion (xrender->xdisplay, shadow_clip, border_clip); if (paint_region != None) { @@ -851,17 +854,13 @@ paint_shadow (MetaCompositorXRender *xrender, paint_region); } - XFixesSetPictureClipRegion (xrender->xdisplay, paint_buffer, 0, 0, shadow_clip); - XFixesDestroyRegion (xrender->xdisplay, shadow_clip); - - x = cw->rect.x; - y = cw->rect.y; + meta_shadow_xrender_paint (cw->shadow, + shadow_clip, + paint_buffer, + cw->rect.x, + cw->rect.y); - XRenderComposite (xrender->xdisplay, PictOpOver, - xrender->black_picture, cw->shadow, paint_buffer, - 0, 0, 0, 0, - x + cw->shadow_dx, y + cw->shadow_dy, - cw->shadow_width, cw->shadow_height); + XFixesDestroyRegion (xrender->xdisplay, shadow_clip); } static void @@ -1027,24 +1026,13 @@ static void cw_destroy_cb (gpointer data) { MetaCompWindow *cw; - MetaDisplay *display; - Display *xdisplay; cw = (MetaCompWindow *) data; - display = meta_window_get_display (cw->window); - xdisplay = meta_display_get_xdisplay (display); - - if (cw->shadow) - { - XRenderFreePicture (xdisplay, cw->shadow); - cw->shadow = None; - } - - if (cw->shadow_region != None) + if (cw->shadow != NULL) { - XFixesDestroyRegion (xdisplay, cw->shadow_region); - cw->shadow_region = None; + meta_shadow_xrender_free (cw->shadow); + cw->shadow = NULL; } g_free (cw); @@ -1166,9 +1154,6 @@ meta_compositor_xrender_finalize (GObject *object) if (xrender->root_picture) XRenderFreePicture (xdisplay, xrender->root_picture); - if (xrender->black_picture) - XRenderFreePicture (xdisplay, xrender->black_picture); - if (xrender->have_shadows) { int i; @@ -1246,7 +1231,6 @@ meta_compositor_xrender_manage (MetaCompositor *compositor, } xrender->root_buffer = None; - xrender->black_picture = solid_picture (xdisplay, TRUE, 1, 0, 0, 0); xrender->root_tile = None; @@ -1404,16 +1388,15 @@ meta_compositor_xrender_sync_window_geometry (MetaCompositor *compositor, { shadow_changed (surface); } - else if (cw->shadow_region != None) + else if (cw->shadow != NULL) { - meta_compositor_add_damage (compositor, "sync_window_geometry", cw->shadow_region); + XserverRegion region; - XFixesTranslateRegion (xrender->xdisplay, - cw->shadow_region, - cw->rect.x - old_rect.x, - cw->rect.y - old_rect.y); + region = meta_shadow_xrender_get_region (cw->shadow); + XFixesTranslateRegion (xrender->xdisplay, region, old_rect.x, old_rect.y); - meta_compositor_add_damage (compositor, "sync_window_geometry", cw->shadow_region); + meta_compositor_add_damage (compositor, "sync_window_geometry", region); + XFixesDestroyRegion (xrender->xdisplay, region); } } @@ -1448,22 +1431,27 @@ meta_compositor_xrender_pre_paint (MetaCompositor *compositor) meta_surface_has_shadow (surface)) { MetaShadowType shadow_type; + XserverRegion shadow_region; if (meta_window_appears_focused (cw->window)) shadow_type = META_SHADOW_LARGE; else shadow_type = META_SHADOW_MEDIUM; - g_assert (cw->shadow_region == None); - cw->shadow_region = get_shadow_region (xrender, cw, shadow_type); + g_assert (cw->shadow == NULL); + cw->shadow = create_shadow (xrender, surface, shadow_type); - if (cw->shadow_region != None) - { - meta_compositor_add_damage (compositor, - "meta_compositor_xrender_pre_paint", - cw->shadow_region); - } + shadow_region = meta_shadow_xrender_get_region (cw->shadow); + XFixesTranslateRegion (xrender->xdisplay, + shadow_region, + meta_surface_get_x (surface), + meta_surface_get_y (surface)); + + meta_compositor_add_damage (compositor, + "meta_compositor_xrender_pre_paint", + shadow_region); + XFixesDestroyRegion (xrender->xdisplay, shadow_region); cw->shadow_changed = FALSE; } } diff --git a/src/compositor/meta-shadow-xrender.c b/src/compositor/meta-shadow-xrender.c new file mode 100644 index 00000000..058ef057 --- /dev/null +++ b/src/compositor/meta-shadow-xrender.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 Alberts Muktupāvels + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" +#include "meta-shadow-xrender.h" + +void +meta_shadow_xrender_free (MetaShadowXRender *self) +{ + if (self->black != None) + { + XRenderFreePicture (self->xdisplay, self->black); + self->black = None; + } + + if (self->shadow != None) + { + XRenderFreePicture (self->xdisplay, self->shadow); + self->shadow = None; + } + + if (self->region != None) + { + XFixesDestroyRegion (self->xdisplay, self->region); + self->region = None; + } + + g_free (self); +} + +XserverRegion +meta_shadow_xrender_get_region (MetaShadowXRender *self) +{ + XserverRegion region; + + region = XFixesCreateRegion (self->xdisplay, NULL, 0); + XFixesCopyRegion (self->xdisplay, region, self->region); + + return region; +} + +void +meta_shadow_xrender_paint (MetaShadowXRender *self, + XserverRegion paint_region, + Picture paint_buffer, + int x, + int y) +{ + XserverRegion shadow_clip; + + shadow_clip = XFixesCreateRegion (self->xdisplay, NULL, 0); + XFixesCopyRegion (self->xdisplay, shadow_clip, self->region); + XFixesTranslateRegion (self->xdisplay, shadow_clip, x, y); + + XFixesIntersectRegion (self->xdisplay, shadow_clip, shadow_clip, paint_region); + XFixesSetPictureClipRegion (self->xdisplay, paint_buffer, 0, 0, shadow_clip); + XFixesDestroyRegion (self->xdisplay, shadow_clip); + + XRenderComposite (self->xdisplay, PictOpOver, + self->black, self->shadow, paint_buffer, + 0, 0, 0, 0, + x + self->dx, y + self->dy, + self->width, self->height); +} diff --git a/src/compositor/meta-shadow-xrender.h b/src/compositor/meta-shadow-xrender.h new file mode 100644 index 00000000..d6f2ebf8 --- /dev/null +++ b/src/compositor/meta-shadow-xrender.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019 Alberts Muktupāvels + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef META_SHADOW_XRENDER_H +#define META_SHADOW_XRENDER_H + +#include <glib-object.h> +#include <X11/extensions/Xfixes.h> +#include <X11/extensions/Xrender.h> + +G_BEGIN_DECLS + +typedef struct +{ + Display *xdisplay; + + int dx; + int dy; + int width; + int height; + + Picture black; + Picture shadow; + + XserverRegion region; +} MetaShadowXRender; + +void meta_shadow_xrender_free (MetaShadowXRender *self); + +XserverRegion meta_shadow_xrender_get_region (MetaShadowXRender *self); + +void meta_shadow_xrender_paint (MetaShadowXRender *self, + XserverRegion paint_region, + Picture paint_buffer, + int x, + int y); + +G_END_DECLS + +#endif |