mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
Antialiased corners
Use a specially constructed cairo overlay to give us fully anti-aliased corners on the mask texture. https://bugzilla.gnome.org/show_bug.cgi?id=628195
This commit is contained in:
parent
49a3fd53b0
commit
dcfa6986c6
@ -2,7 +2,6 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define _ISOC99_SOURCE /* for roundf */
|
||||
#include <math.h>
|
||||
|
||||
#include <X11/extensions/shape.h>
|
||||
@ -1697,13 +1696,8 @@ meta_window_actor_set_visible_region (MetaWindowActor *self,
|
||||
/* Get the area of the window texture that would be drawn if
|
||||
* we weren't obscured at all
|
||||
*/
|
||||
if (priv->shape_region)
|
||||
texture_clip_region = cairo_region_copy (priv->shape_region);
|
||||
else if (priv->bounding_region)
|
||||
texture_clip_region = cairo_region_copy (priv->bounding_region);
|
||||
|
||||
if (!texture_clip_region)
|
||||
texture_clip_region = cairo_region_create ();
|
||||
texture_clip_region = meta_shaped_texture_get_visible_pixels_region (META_SHAPED_TEXTURE (priv->actor));
|
||||
texture_clip_region = cairo_region_copy (texture_clip_region);
|
||||
|
||||
/* Then intersect that with the visible region to get the region
|
||||
* that we actually need to redraw.
|
||||
@ -1993,12 +1987,120 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_integral_bounding_rect (cairo_rectangle_int_t *rect,
|
||||
double x, double y,
|
||||
double width, double height)
|
||||
{
|
||||
rect->x = floor(x);
|
||||
rect->y = floor(y);
|
||||
rect->width = ceil(x + width) - rect->x;
|
||||
rect->height = ceil(y + height) - rect->y;
|
||||
}
|
||||
|
||||
static void
|
||||
update_corners (MetaWindowActor *self,
|
||||
MetaFrameBorders *borders)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaRectangle outer;
|
||||
cairo_rectangle_int_t corner_rects[4];
|
||||
cairo_region_t *corner_region;
|
||||
cairo_path_t *corner_path;
|
||||
float top_left, top_right, bottom_left, bottom_right;
|
||||
|
||||
/* need these to build a path */
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
if (!priv->window->frame)
|
||||
return;
|
||||
|
||||
meta_window_get_outer_rect (priv->window, &outer);
|
||||
|
||||
meta_frame_get_corner_radiuses (priv->window->frame,
|
||||
&top_left,
|
||||
&top_right,
|
||||
&bottom_left,
|
||||
&bottom_right);
|
||||
|
||||
/* Unfortunately, cairo does not allow us to create a context
|
||||
* without a surface. Create a 0x0 image surface to "paint to"
|
||||
* so we can get the path. */
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
|
||||
0, 0);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
|
||||
/* top left */
|
||||
set_integral_bounding_rect (&corner_rects[0],
|
||||
borders->invisible.left,
|
||||
borders->invisible.top,
|
||||
top_left, top_left);
|
||||
|
||||
cairo_arc (cr,
|
||||
corner_rects[0].x + top_left,
|
||||
corner_rects[0].y + top_left,
|
||||
top_left,
|
||||
0, M_PI*2);
|
||||
|
||||
/* top right */
|
||||
set_integral_bounding_rect (&corner_rects[1],
|
||||
borders->invisible.left + outer.width - top_right,
|
||||
borders->invisible.top,
|
||||
top_right, top_right);
|
||||
|
||||
cairo_arc (cr,
|
||||
corner_rects[1].x,
|
||||
corner_rects[1].y + top_right,
|
||||
top_right,
|
||||
0, M_PI*2);
|
||||
|
||||
/* bottom left */
|
||||
set_integral_bounding_rect (&corner_rects[2],
|
||||
borders->invisible.left,
|
||||
borders->invisible.top + outer.height - bottom_left,
|
||||
bottom_left, bottom_left);
|
||||
|
||||
cairo_arc (cr,
|
||||
corner_rects[2].x + bottom_left,
|
||||
corner_rects[2].y,
|
||||
bottom_left,
|
||||
0, M_PI*2);
|
||||
|
||||
/* bottom right */
|
||||
set_integral_bounding_rect (&corner_rects[3],
|
||||
borders->invisible.left + outer.width - bottom_right,
|
||||
borders->invisible.top + outer.height - bottom_right,
|
||||
bottom_right, bottom_right);
|
||||
|
||||
cairo_arc (cr,
|
||||
corner_rects[3].x,
|
||||
corner_rects[3].y,
|
||||
bottom_right,
|
||||
0, M_PI*2);
|
||||
|
||||
corner_path = cairo_copy_path (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_destroy (cr);
|
||||
|
||||
corner_region = cairo_region_create_rectangles (corner_rects, 4);
|
||||
|
||||
meta_shaped_texture_set_overlay_path (META_SHAPED_TEXTURE (priv->actor),
|
||||
corner_region, corner_path);
|
||||
|
||||
cairo_region_destroy (corner_region);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
check_needs_reshape (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaFrameBorders borders;
|
||||
cairo_region_t *region;
|
||||
|
||||
if (!priv->needs_reshape)
|
||||
@ -2007,6 +2109,9 @@ check_needs_reshape (MetaWindowActor *self)
|
||||
meta_shaped_texture_set_shape_region (META_SHAPED_TEXTURE (priv->actor), NULL);
|
||||
meta_window_actor_clear_shape_region (self);
|
||||
|
||||
if (priv->window->frame)
|
||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||
|
||||
region = meta_window_get_frame_bounds (priv->window);
|
||||
if (region != NULL)
|
||||
{
|
||||
@ -2034,9 +2139,6 @@ check_needs_reshape (MetaWindowActor *self)
|
||||
|
||||
if (priv->window->frame)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||
|
||||
client_area.x = borders.total.left;
|
||||
client_area.y = borders.total.top;
|
||||
}
|
||||
@ -2080,6 +2182,8 @@ check_needs_reshape (MetaWindowActor *self)
|
||||
|
||||
cairo_region_destroy (region);
|
||||
|
||||
update_corners (self, &borders);
|
||||
|
||||
priv->needs_reshape = FALSE;
|
||||
meta_window_actor_invalidate_shadow (self);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user