mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
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.
This commit is contained in:
parent
fd13dad0c4
commit
302302a116
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
13
src/ui/ui.c
13
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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user