mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 12:32: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>
|
#include <config.h>
|
||||||
|
|
||||||
#define _ISOC99_SOURCE /* for roundf */
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <X11/extensions/shape.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
|
/* Get the area of the window texture that would be drawn if
|
||||||
* we weren't obscured at all
|
* we weren't obscured at all
|
||||||
*/
|
*/
|
||||||
if (priv->shape_region)
|
texture_clip_region = meta_shaped_texture_get_visible_pixels_region (META_SHAPED_TEXTURE (priv->actor));
|
||||||
texture_clip_region = cairo_region_copy (priv->shape_region);
|
texture_clip_region = cairo_region_copy (texture_clip_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 ();
|
|
||||||
|
|
||||||
/* Then intersect that with the visible region to get the region
|
/* Then intersect that with the visible region to get the region
|
||||||
* that we actually need to redraw.
|
* 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
|
static void
|
||||||
check_needs_reshape (MetaWindowActor *self)
|
check_needs_reshape (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaScreen *screen = priv->screen;
|
MetaScreen *screen = priv->screen;
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
|
MetaFrameBorders borders;
|
||||||
cairo_region_t *region;
|
cairo_region_t *region;
|
||||||
|
|
||||||
if (!priv->needs_reshape)
|
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_shaped_texture_set_shape_region (META_SHAPED_TEXTURE (priv->actor), NULL);
|
||||||
meta_window_actor_clear_shape_region (self);
|
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);
|
region = meta_window_get_frame_bounds (priv->window);
|
||||||
if (region != NULL)
|
if (region != NULL)
|
||||||
{
|
{
|
||||||
@ -2034,9 +2139,6 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
|
|
||||||
if (priv->window->frame)
|
if (priv->window->frame)
|
||||||
{
|
{
|
||||||
MetaFrameBorders borders;
|
|
||||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
|
||||||
|
|
||||||
client_area.x = borders.total.left;
|
client_area.x = borders.total.left;
|
||||||
client_area.y = borders.total.top;
|
client_area.y = borders.total.top;
|
||||||
}
|
}
|
||||||
@ -2080,6 +2182,8 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
|
|
||||||
cairo_region_destroy (region);
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
|
update_corners (self, &borders);
|
||||||
|
|
||||||
priv->needs_reshape = FALSE;
|
priv->needs_reshape = FALSE;
|
||||||
meta_window_actor_invalidate_shadow (self);
|
meta_window_actor_invalidate_shadow (self);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user