diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 386aa0f63..a6348fe72 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) +scan_visible_region (guchar *mask_data, + int stride, + cairo_region_t *scan_area, + cairo_region_t *union_against) { - float top_left, top_right, bottom_left, bottom_right; - int x, y; - MetaRectangle outer; + int i, n_rects; + n_rects = cairo_region_num_rectangles (scan_area); - meta_frame_get_corner_radiuses (window->frame, - &top_left, - &top_right, - &bottom_left, - &bottom_right); + for (i = 0; i < n_rects; i++) + { + int x, y; + cairo_rectangle_int_t rect; - meta_window_get_outer_rect (window, &outer); + cairo_region_get_rectangle (scan_area, i, &rect); - /* top left */ - x = borders->invisible.left; - y = borders->invisible.top; + 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++; - 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); + 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 15eb0cdcb..dcc0548a4 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 d612f7779..405a2d0f4 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 a5ff98766..08376285b 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 c7d54bf09..897906515 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 7549c41cb..8461b76e0 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 ac417c74b..46fd34f5e 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 8a0aad869..20746caab 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 710185333..482fadd74 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);