mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 17:40:40 -05:00
window-actor: Add back antialiased window corners
This simply adds fancy arcs to the mask texture. It's still not painted with GTK+ yet. https://bugzilla.gnome.org/show_bug.cgi?id=676052
This commit is contained in:
parent
c47de98c88
commit
60c05a0dac
@ -1991,9 +1991,112 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TAU (2*M_PI)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
generate_mask (MetaWindowActor *self,
|
install_corners (MetaWindow *window,
|
||||||
MetaFrameBorders *borders,
|
MetaFrameBorders *borders,
|
||||||
|
cairo_t *cr)
|
||||||
|
{
|
||||||
|
float top_left, top_right, bottom_left, bottom_right;
|
||||||
|
int x, y;
|
||||||
|
MetaRectangle outer;
|
||||||
|
|
||||||
|
meta_frame_get_corner_radiuses (window->frame,
|
||||||
|
&top_left,
|
||||||
|
&top_right,
|
||||||
|
&bottom_left,
|
||||||
|
&bottom_right);
|
||||||
|
|
||||||
|
meta_window_get_outer_rect (window, &outer);
|
||||||
|
|
||||||
|
/* top left */
|
||||||
|
x = borders->invisible.left;
|
||||||
|
y = borders->invisible.top;
|
||||||
|
|
||||||
|
cairo_arc (cr,
|
||||||
|
x + top_left,
|
||||||
|
y + top_left,
|
||||||
|
top_left,
|
||||||
|
2 * TAU / 4,
|
||||||
|
3 * TAU / 4);
|
||||||
|
|
||||||
|
/* top right */
|
||||||
|
x = borders->invisible.left + outer.width - top_right;
|
||||||
|
y = borders->invisible.top;
|
||||||
|
|
||||||
|
cairo_arc (cr,
|
||||||
|
x,
|
||||||
|
y + top_right,
|
||||||
|
top_right,
|
||||||
|
3 * TAU / 4,
|
||||||
|
4 * TAU / 4);
|
||||||
|
|
||||||
|
/* bottom right */
|
||||||
|
x = borders->invisible.left + outer.width - bottom_right;
|
||||||
|
y = borders->invisible.top + outer.height - bottom_right;
|
||||||
|
|
||||||
|
cairo_arc (cr,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
bottom_right,
|
||||||
|
0 * TAU / 4,
|
||||||
|
1 * TAU / 4);
|
||||||
|
|
||||||
|
/* bottom left */
|
||||||
|
x = borders->invisible.left;
|
||||||
|
y = borders->invisible.top + outer.height - bottom_left;
|
||||||
|
|
||||||
|
cairo_arc (cr,
|
||||||
|
x + bottom_left,
|
||||||
|
y,
|
||||||
|
bottom_left,
|
||||||
|
1 * TAU / 4,
|
||||||
|
2 * TAU / 4);
|
||||||
|
|
||||||
|
cairo_set_source_rgba (cr, 1, 1, 1, 1);
|
||||||
|
cairo_fill (cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
scan_visible_region (guchar *mask_data,
|
||||||
|
int stride,
|
||||||
|
cairo_region_t *scan_area,
|
||||||
|
cairo_region_t *union_against)
|
||||||
|
{
|
||||||
|
int i, n_rects;
|
||||||
|
n_rects = cairo_region_num_rectangles (scan_area);
|
||||||
|
|
||||||
|
for (i = 0; i < n_rects; i++)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
cairo_rectangle_int_t rect;
|
||||||
|
|
||||||
|
cairo_region_get_rectangle (scan_area, i, &rect);
|
||||||
|
|
||||||
|
for (y = rect.y; y < (rect.y + rect.height); y++)
|
||||||
|
{
|
||||||
|
for (x = rect.x; x < (rect.x + rect.width); x++)
|
||||||
|
{
|
||||||
|
int w = x;
|
||||||
|
while (mask_data[y * stride + w] == 255 && w < (rect.x + rect.width))
|
||||||
|
w++;
|
||||||
|
|
||||||
|
if (w > 0)
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t tmp = { x, y, w - x, 1 };
|
||||||
|
cairo_region_union_rectangle (union_against, &tmp);
|
||||||
|
x = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
build_and_scan_frame_mask (MetaWindowActor *self,
|
||||||
|
MetaFrameBorders *borders,
|
||||||
|
cairo_rectangle_int_t *client_area,
|
||||||
cairo_region_t *shape_region)
|
cairo_region_t *shape_region)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
@ -2026,6 +2129,24 @@ generate_mask (MetaWindowActor *self,
|
|||||||
gdk_cairo_region (cr, shape_region);
|
gdk_cairo_region (cr, shape_region);
|
||||||
cairo_fill (cr);
|
cairo_fill (cr);
|
||||||
|
|
||||||
|
if (priv->window->frame != NULL)
|
||||||
|
{
|
||||||
|
cairo_region_t *frame_paint_region;
|
||||||
|
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
|
||||||
|
|
||||||
|
/* Make sure we don't paint the frame over the client window. */
|
||||||
|
frame_paint_region = cairo_region_create_rectangle (&rect);
|
||||||
|
cairo_region_subtract_rectangle (frame_paint_region, client_area);
|
||||||
|
|
||||||
|
gdk_cairo_region (cr, frame_paint_region);
|
||||||
|
cairo_clip (cr);
|
||||||
|
|
||||||
|
install_corners (priv->window, borders, cr);
|
||||||
|
|
||||||
|
cairo_surface_flush (surface);
|
||||||
|
scan_visible_region (mask_data, stride, frame_paint_region, shape_region);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
@ -2066,44 +2187,30 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
MetaFrameBorders borders;
|
MetaFrameBorders borders;
|
||||||
cairo_region_t *region;
|
cairo_region_t *region;
|
||||||
|
cairo_rectangle_int_t client_area;
|
||||||
|
|
||||||
if (!priv->needs_reshape)
|
if (!priv->needs_reshape)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), COGL_INVALID_HANDLE);
|
|
||||||
meta_window_actor_clear_shape_region (self);
|
|
||||||
|
|
||||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||||
|
|
||||||
region = meta_window_get_frame_bounds (priv->window);
|
client_area.x = borders.total.left;
|
||||||
if (region != NULL)
|
client_area.y = borders.total.top;
|
||||||
{
|
client_area.width = priv->window->rect.width;
|
||||||
/* This returns the window's internal frame bounds region,
|
client_area.height = priv->window->rect.height;
|
||||||
* so we need to copy it because we modify it below. */
|
|
||||||
region = cairo_region_copy (region);
|
meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), COGL_INVALID_HANDLE);
|
||||||
}
|
meta_window_actor_clear_shape_region (self);
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If we have no region, we have no frame. We have no frame,
|
|
||||||
* so just use the bounding region instead */
|
|
||||||
region = cairo_region_copy (priv->bounding_region);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_SHAPE
|
#ifdef HAVE_SHAPE
|
||||||
if (priv->window->has_shape)
|
if (priv->window->has_shape)
|
||||||
{
|
{
|
||||||
|
/* Translate the set of XShape rectangles that we
|
||||||
|
* get from the X server to a cairo_region. */
|
||||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||||
XRectangle *rects;
|
XRectangle *rects;
|
||||||
int n_rects, ordering;
|
int n_rects, ordering;
|
||||||
cairo_rectangle_int_t client_area;
|
cairo_rectangle_int_t *cairo_rects = NULL;
|
||||||
|
|
||||||
client_area.width = priv->window->rect.width;
|
|
||||||
client_area.height = priv->window->rect.height;
|
|
||||||
client_area.x = borders.total.left;
|
|
||||||
client_area.y = borders.total.top;
|
|
||||||
|
|
||||||
/* Punch out client area. */
|
|
||||||
cairo_region_subtract_rectangle (region, &client_area);
|
|
||||||
|
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push (display);
|
||||||
rects = XShapeGetRectangles (xdisplay,
|
rects = XShapeGetRectangles (xdisplay,
|
||||||
@ -2116,20 +2223,34 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
if (rects)
|
if (rects)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
cairo_rects = g_new (cairo_rectangle_int_t, n_rects);
|
||||||
for (i = 0; i < n_rects; i ++)
|
for (i = 0; i < n_rects; i ++)
|
||||||
{
|
{
|
||||||
cairo_rectangle_int_t rect = { rects[i].x + client_area.x,
|
cairo_rects[i].x = rects[i].x + client_area.x;
|
||||||
rects[i].y + client_area.y,
|
cairo_rects[i].y = rects[i].y + client_area.y;
|
||||||
rects[i].width,
|
cairo_rects[i].width = rects[i].width;
|
||||||
rects[i].height };
|
cairo_rects[i].height = rects[i].height;
|
||||||
cairo_region_union_rectangle (region, &rect);
|
|
||||||
}
|
}
|
||||||
XFree (rects);
|
XFree (rects);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
generate_mask (self, &borders, region);
|
region = cairo_region_create_rectangles (cairo_rects, n_rects);
|
||||||
|
g_free (cairo_rects);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* If we don't have a shape on the server, that means that
|
||||||
|
* we have an implicit shape of one rectangle covering the
|
||||||
|
* entire window. */
|
||||||
|
region = cairo_region_create_rectangle (&client_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This takes the region, generates a mask using GTK+
|
||||||
|
* and scans the mask looking for all opaque pixels,
|
||||||
|
* adding it to region.
|
||||||
|
*/
|
||||||
|
build_and_scan_frame_mask (self, &borders, &client_area, region);
|
||||||
meta_window_actor_update_shape_region (self, region);
|
meta_window_actor_update_shape_region (self, region);
|
||||||
|
|
||||||
cairo_region_destroy (region);
|
cairo_region_destroy (region);
|
||||||
|
Loading…
Reference in New Issue
Block a user