[mutter] window-actor: Add back antialiased window corners
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] window-actor: Add back antialiased window corners
- Date: Fri, 25 May 2012 22:45:43 +0000 (UTC)
commit 60c05a0dac2bbc7fa1aa5abde3d60c4a5749c1e4
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Fri Apr 27 00:15:30 2012 -0400
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
src/compositor/meta-window-actor.c | 189 +++++++++++++++++++++++++++++-------
1 files changed, 155 insertions(+), 34 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 87eb0d8..0ebea53 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -1991,10 +1991,113 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
}
}
+#define TAU (2*M_PI)
+
+static void
+install_corners (MetaWindow *window,
+ 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
-generate_mask (MetaWindowActor *self,
- MetaFrameBorders *borders,
- cairo_region_t *shape_region)
+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)
{
MetaWindowActorPrivate *priv = self->priv;
guchar *mask_data;
@@ -2026,6 +2129,24 @@ generate_mask (MetaWindowActor *self,
gdk_cairo_region (cr, shape_region);
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_surface_destroy (surface);
@@ -2066,44 +2187,30 @@ check_needs_reshape (MetaWindowActor *self)
MetaDisplay *display = meta_screen_get_display (screen);
MetaFrameBorders borders;
cairo_region_t *region;
+ cairo_rectangle_int_t client_area;
if (!priv->needs_reshape)
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);
- region = meta_window_get_frame_bounds (priv->window);
- if (region != NULL)
- {
- /* This returns the window's internal frame bounds region,
- * so we need to copy it because we modify it below. */
- region = cairo_region_copy (region);
- }
- 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);
- }
+ client_area.x = borders.total.left;
+ client_area.y = borders.total.top;
+ client_area.width = priv->window->rect.width;
+ client_area.height = priv->window->rect.height;
+
+ meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), COGL_INVALID_HANDLE);
+ meta_window_actor_clear_shape_region (self);
#ifdef HAVE_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);
XRectangle *rects;
int n_rects, ordering;
- cairo_rectangle_int_t client_area;
-
- 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);
+ cairo_rectangle_int_t *cairo_rects = NULL;
meta_error_trap_push (display);
rects = XShapeGetRectangles (xdisplay,
@@ -2116,20 +2223,34 @@ check_needs_reshape (MetaWindowActor *self)
if (rects)
{
int i;
+ cairo_rects = g_new (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i ++)
{
- cairo_rectangle_int_t rect = { rects[i].x + client_area.x,
- rects[i].y + client_area.y,
- rects[i].width,
- rects[i].height };
- cairo_region_union_rectangle (region, &rect);
+ cairo_rects[i].x = rects[i].x + client_area.x;
+ cairo_rects[i].y = rects[i].y + client_area.y;
+ cairo_rects[i].width = rects[i].width;
+ cairo_rects[i].height = rects[i].height;
}
XFree (rects);
}
+
+ 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);
+ }
- generate_mask (self, &borders, region);
+ /* 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);
cairo_region_destroy (region);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]