[mutter/wip/cb2eb3: 27/55] window-actor: Paint the frame mask with GTK+ as well



commit 302302a116d336dfcc02427054243a1e41f454d3
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sun Apr 29 07:40:25 2012 -0400

    window-actor: Paint the frame mask with GTK+ as well
    
    Use meta_theme_render_background to paint the background of the frame,
    and then scan it to give us a region we can use to generate the shape
    region from. It may be worth looking at the uses of the shape region
    to see if we can replace some (all?) of them by masks instead, so we
    don't have to scan the mask.

 src/compositor/meta-window-actor.c |  159 ++++++++++++++++--------------------
 src/core/frame.c                   |   14 +--
 src/core/frame.h                   |    7 +-
 src/ui/frames.c                    |   24 ++----
 src/ui/frames.h                    |    9 +--
 src/ui/theme-private.h             |    5 +
 src/ui/theme.c                     |   35 +++++---
 src/ui/ui.c                        |   13 +--
 src/ui/ui.h                        |    9 +--
 9 files changed, 123 insertions(+), 152 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 386aa0f..a6348fe 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -1991,71 +1991,44 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
 }
 
 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,
-             0, M_PI*2);
-
-  /* top right */
-  x = borders->invisible.left + outer.width - top_right;
-  y = borders->invisible.top;
-
-  cairo_arc (cr,
-             x,
-             y + top_right,
-             top_right,
-             0, M_PI*2);
-
-  /* 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, M_PI*2);
-
-  /* bottom left */
-  x = borders->invisible.left;
-  y = borders->invisible.top + outer.height - bottom_left;
-
-  cairo_arc (cr,
-             x + bottom_left,
-             y,
-             bottom_left,
-             0, M_PI*2);
-
-  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
-  cairo_set_source_rgba (cr, 1, 1, 1, 1);
-  cairo_fill (cr);
+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
-generate_mask (MetaWindowActor  *self,
-               MetaFrameBorders *borders,
-               cairo_region_t   *shape_region)
+build_and_scan_frame_mask (MetaWindowActor       *self,
+                           cairo_rectangle_int_t *client_area,
+                           cairo_region_t        *shape_region)
 {
   MetaWindowActorPrivate *priv = self->priv;
   guchar *mask_data;
@@ -2106,6 +2079,12 @@ generate_mask (MetaWindowActor  *self,
     {
       cairo_t *cr;
       cairo_surface_t *surface;
+      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);
 
       surface = cairo_image_surface_create_for_data (mask_data,
                                                      CAIRO_FORMAT_A8,
@@ -2114,7 +2093,13 @@ generate_mask (MetaWindowActor  *self,
                                                      stride);
       cr = cairo_create (surface);
 
-      install_corners (priv->window, borders, cr);
+      gdk_cairo_region (cr, frame_paint_region);
+      cairo_clip (cr);
+
+      meta_frame_render_background (priv->window->frame, cr);
+
+      cairo_surface_flush (surface);
+      scan_visible_region (mask_data, stride, frame_paint_region, shape_region);
 
       cairo_destroy (cr);
       cairo_surface_destroy (surface);
@@ -2157,45 +2142,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;
       cairo_rectangle_int_t *cairo_rects = NULL;
       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);
 
       meta_error_trap_push (display);
       rects = XShapeGetRectangles (xdisplay,
@@ -2222,10 +2192,21 @@ check_needs_reshape (MetaWindowActor *self)
       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, &client_area, region);
   meta_window_actor_update_shape_region (self, region);
-  generate_mask (self, &borders, region);
 
   priv->needs_reshape = FALSE;
   meta_window_actor_invalidate_shadow (self);
diff --git a/src/core/frame.c b/src/core/frame.c
index 15eb0cd..dcc0548 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -333,16 +333,12 @@ meta_frame_calc_borders (MetaFrame        *frame,
 }
 
 void
-meta_frame_get_corner_radiuses (MetaFrame *frame,
-                                float     *top_left,
-                                float     *top_right,
-                                float     *bottom_left,
-                                float     *bottom_right)
+meta_frame_render_background (MetaFrame *frame,
+                              cairo_t   *cr)
 {
-  meta_ui_get_corner_radiuses (frame->window->screen->ui,
-                               frame->xwindow,
-                               top_left, top_right,
-                               bottom_left, bottom_right);
+  meta_ui_render_background (frame->window->screen->ui,
+                             frame->xwindow,
+                             cr);
 }
 
 gboolean
diff --git a/src/core/frame.h b/src/core/frame.h
index d612f77..405a2d0 100644
--- a/src/core/frame.h
+++ b/src/core/frame.h
@@ -63,11 +63,8 @@ Window         meta_frame_get_xwindow (MetaFrame *frame);
 void meta_frame_calc_borders      (MetaFrame        *frame,
                                    MetaFrameBorders *borders);
 
-void meta_frame_get_corner_radiuses (MetaFrame *frame,
-                                     float     *top_left,
-                                     float     *top_right,
-                                     float     *bottom_left,
-                                     float     *bottom_right);
+void meta_frame_render_background (MetaFrame *frame,
+                                   cairo_t   *cr);
 
 gboolean meta_frame_sync_to_window (MetaFrame         *frame,
                                     int                gravity,
diff --git a/src/ui/frames.c b/src/ui/frames.c
index a5ff987..0837628 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -687,28 +687,22 @@ meta_frames_get_borders (MetaFrames *frames,
 }
 
 void
-meta_frames_get_corner_radiuses (MetaFrames *frames,
-                                 Window      xwindow,
-                                 float      *top_left,
-                                 float      *top_right,
-                                 float      *bottom_left,
-                                 float      *bottom_right)
+meta_frames_render_background (MetaFrames *frames,
+                               Window      xwindow,
+                               cairo_t    *cr)
 {
   MetaUIFrame *frame;
   MetaFrameGeometry fgeom;
+  MetaFrameFlags flags;
 
   frame = meta_frames_lookup_window (frames, xwindow);
 
-  meta_frames_calc_geometry (frames, frame, &fgeom);
+  meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
+                 META_CORE_GET_FRAME_FLAGS, &flags,
+                 META_CORE_GET_END);
 
-  if (top_left)
-    *top_left = fgeom.top_left_corner_rounded_radius;
-  if (top_right)
-    *top_right = fgeom.top_right_corner_rounded_radius;
-  if (bottom_left)
-    *bottom_left = fgeom.bottom_left_corner_rounded_radius;
-  if (bottom_right)
-    *bottom_right = fgeom.bottom_right_corner_rounded_radius;
+  meta_frames_calc_geometry (frames, frame, &fgeom);
+  meta_theme_render_background (frame->tv->style_context, cr, flags, &fgeom);
 }
 
 void
diff --git a/src/ui/frames.h b/src/ui/frames.h
index c7d54bf..8979065 100644
--- a/src/ui/frames.h
+++ b/src/ui/frames.h
@@ -143,12 +143,9 @@ cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
                                               int         window_width,
                                               int         window_height);
 
-void meta_frames_get_corner_radiuses (MetaFrames *frames,
-                                      Window      xwindow,
-                                      float      *top_left,
-                                      float      *top_right,
-                                      float      *bottom_left,
-                                      float      *bottom_right);
+void meta_frames_render_background (MetaFrames *frames,
+                                    Window      xwindow,
+                                    cairo_t    *cr);
 
 void meta_frames_move_resize_frame (MetaFrames *frames,
                                    Window      xwindow,
diff --git a/src/ui/theme-private.h b/src/ui/theme-private.h
index 7549c41..8461b76 100644
--- a/src/ui/theme-private.h
+++ b/src/ui/theme-private.h
@@ -1030,6 +1030,11 @@ double meta_theme_get_title_scale (MetaTheme     *theme,
                                    MetaFrameType  type,
                                    MetaFrameFlags flags);
 
+void meta_theme_render_background (GtkStyleContext *style,
+                                   cairo_t         *cr,
+                                   MetaFrameFlags   flags,
+                                   const MetaFrameGeometry *fgeom);
+
 void meta_theme_draw_frame (MetaTheme              *theme,
                             GtkWidget              *widget,
                             cairo_t                *cr,
diff --git a/src/ui/theme.c b/src/ui/theme.c
index ac417c7..46fd34f 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -4117,19 +4117,11 @@ button_rect (MetaButtonType           type,
     }
 }
 
-static void
-meta_frame_style_draw_with_style (MetaFrameStyle          *style,
-                                  GtkStyleContext         *style_gtk,
-                                  MetaFrameFlags           flags,
-                                  cairo_t                 *cr,
-                                  const MetaFrameGeometry *fgeom,
-                                  int                      client_width,
-                                  int                      client_height,
-                                  PangoLayout             *title_layout,
-                                  int                      text_height,
-                                  MetaButtonState          button_states[META_BUTTON_TYPE_LAST],
-                                  GdkPixbuf               *mini_icon,
-                                  GdkPixbuf               *icon)
+void
+meta_theme_render_background (GtkStyleContext *style_gtk,
+                              cairo_t         *cr,
+                              MetaFrameFlags   flags,
+                              const MetaFrameGeometry *fgeom)
 {
   GdkRectangle visible_rect;
   const MetaFrameBorders *borders;
@@ -4158,6 +4150,23 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
                     visible_rect.height);
 
   gtk_style_context_restore (style_gtk);
+}
+
+static void
+meta_frame_style_draw_with_style (MetaFrameStyle          *style,
+                                  GtkStyleContext         *style_gtk,
+                                  MetaFrameFlags           flags,
+                                  cairo_t                 *cr,
+                                  const MetaFrameGeometry *fgeom,
+                                  int                      client_width,
+                                  int                      client_height,
+                                  PangoLayout             *title_layout,
+                                  int                      text_height,
+                                  MetaButtonState          button_states[META_BUTTON_TYPE_LAST],
+                                  GdkPixbuf               *mini_icon,
+                                  GdkPixbuf               *icon)
+{
+  meta_theme_render_background (style_gtk, cr, flags, fgeom);
 
 #if 0
   int i, j;
diff --git a/src/ui/ui.c b/src/ui/ui.c
index 8a0aad8..20746ca 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -318,16 +318,11 @@ meta_ui_get_frame_borders (MetaUI *ui,
 }
 
 void
-meta_ui_get_corner_radiuses (MetaUI *ui,
-                             Window  xwindow,
-                             float  *top_left,
-                             float  *top_right,
-                             float  *bottom_left,
-                             float  *bottom_right)
+meta_ui_render_background (MetaUI  *ui,
+                           Window   xwindow,
+                           cairo_t *cr)
 {
-  meta_frames_get_corner_radiuses (ui->frames, xwindow,
-                                   top_left, top_right,
-                                   bottom_left, bottom_right);
+  meta_frames_render_background (ui->frames, xwindow, cr);
 }
 
 Window
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 7101853..482fadd 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -100,12 +100,9 @@ cairo_region_t *meta_ui_get_frame_bounds (MetaUI  *ui,
                                           int      window_width,
                                           int      window_height);
 
-void meta_ui_get_corner_radiuses (MetaUI *ui,
-                                  Window  xwindow,
-                                  float  *top_left,
-                                  float  *top_right,
-                                  float  *bottom_left,
-                                  float  *bottom_right);
+void meta_ui_render_background (MetaUI  *ui,
+                                Window   xwindow,
+                                cairo_t *cr);
 
 void meta_ui_queue_frame_draw (MetaUI *ui,
                                Window xwindow);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]