mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 08:00:42 -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
|
static void
|
||||||
install_corners (MetaWindow *window,
|
scan_visible_region (guchar *mask_data,
|
||||||
MetaFrameBorders *borders,
|
int stride,
|
||||||
cairo_t *cr)
|
cairo_region_t *scan_area,
|
||||||
|
cairo_region_t *union_against)
|
||||||
{
|
{
|
||||||
float top_left, top_right, bottom_left, bottom_right;
|
int i, n_rects;
|
||||||
int x, y;
|
n_rects = cairo_region_num_rectangles (scan_area);
|
||||||
MetaRectangle outer;
|
|
||||||
|
|
||||||
meta_frame_get_corner_radiuses (window->frame,
|
for (i = 0; i < n_rects; i++)
|
||||||
&top_left,
|
{
|
||||||
&top_right,
|
int x, y;
|
||||||
&bottom_left,
|
cairo_rectangle_int_t rect;
|
||||||
&bottom_right);
|
|
||||||
|
|
||||||
meta_window_get_outer_rect (window, &outer);
|
cairo_region_get_rectangle (scan_area, i, &rect);
|
||||||
|
|
||||||
/* top left */
|
for (y = rect.y; y < (rect.y + rect.height); y++)
|
||||||
x = borders->invisible.left;
|
{
|
||||||
y = borders->invisible.top;
|
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,
|
if (w > 0)
|
||||||
x + top_left,
|
{
|
||||||
y + top_left,
|
cairo_rectangle_int_t tmp = { x, y, w - x, 1 };
|
||||||
top_left,
|
cairo_region_union_rectangle (union_against, &tmp);
|
||||||
0, M_PI*2);
|
x = w;
|
||||||
|
}
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
generate_mask (MetaWindowActor *self,
|
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;
|
||||||
guchar *mask_data;
|
guchar *mask_data;
|
||||||
@ -2106,6 +2079,12 @@ generate_mask (MetaWindowActor *self,
|
|||||||
{
|
{
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
cairo_surface_t *surface;
|
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,
|
surface = cairo_image_surface_create_for_data (mask_data,
|
||||||
CAIRO_FORMAT_A8,
|
CAIRO_FORMAT_A8,
|
||||||
@ -2114,7 +2093,13 @@ generate_mask (MetaWindowActor *self,
|
|||||||
stride);
|
stride);
|
||||||
cr = cairo_create (surface);
|
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_destroy (cr);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
@ -2157,45 +2142,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;
|
||||||
cairo_rectangle_int_t *cairo_rects = NULL;
|
cairo_rectangle_int_t *cairo_rects = NULL;
|
||||||
int n_rects, ordering;
|
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);
|
meta_error_trap_push (display);
|
||||||
rects = XShapeGetRectangles (xdisplay,
|
rects = XShapeGetRectangles (xdisplay,
|
||||||
@ -2222,10 +2192,21 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
region = cairo_region_create_rectangles (cairo_rects, n_rects);
|
region = cairo_region_create_rectangles (cairo_rects, n_rects);
|
||||||
g_free (cairo_rects);
|
g_free (cairo_rects);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
#endif
|
#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);
|
meta_window_actor_update_shape_region (self, region);
|
||||||
generate_mask (self, &borders, region);
|
|
||||||
|
|
||||||
priv->needs_reshape = FALSE;
|
priv->needs_reshape = FALSE;
|
||||||
meta_window_actor_invalidate_shadow (self);
|
meta_window_actor_invalidate_shadow (self);
|
||||||
|
@ -333,16 +333,12 @@ meta_frame_calc_borders (MetaFrame *frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_frame_get_corner_radiuses (MetaFrame *frame,
|
meta_frame_render_background (MetaFrame *frame,
|
||||||
float *top_left,
|
cairo_t *cr)
|
||||||
float *top_right,
|
|
||||||
float *bottom_left,
|
|
||||||
float *bottom_right)
|
|
||||||
{
|
{
|
||||||
meta_ui_get_corner_radiuses (frame->window->screen->ui,
|
meta_ui_render_background (frame->window->screen->ui,
|
||||||
frame->xwindow,
|
frame->xwindow,
|
||||||
top_left, top_right,
|
cr);
|
||||||
bottom_left, bottom_right);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -63,11 +63,8 @@ Window meta_frame_get_xwindow (MetaFrame *frame);
|
|||||||
void meta_frame_calc_borders (MetaFrame *frame,
|
void meta_frame_calc_borders (MetaFrame *frame,
|
||||||
MetaFrameBorders *borders);
|
MetaFrameBorders *borders);
|
||||||
|
|
||||||
void meta_frame_get_corner_radiuses (MetaFrame *frame,
|
void meta_frame_render_background (MetaFrame *frame,
|
||||||
float *top_left,
|
cairo_t *cr);
|
||||||
float *top_right,
|
|
||||||
float *bottom_left,
|
|
||||||
float *bottom_right);
|
|
||||||
|
|
||||||
gboolean meta_frame_sync_to_window (MetaFrame *frame,
|
gboolean meta_frame_sync_to_window (MetaFrame *frame,
|
||||||
int gravity,
|
int gravity,
|
||||||
|
@ -687,28 +687,22 @@ meta_frames_get_borders (MetaFrames *frames,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_frames_get_corner_radiuses (MetaFrames *frames,
|
meta_frames_render_background (MetaFrames *frames,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
float *top_left,
|
cairo_t *cr)
|
||||||
float *top_right,
|
|
||||||
float *bottom_left,
|
|
||||||
float *bottom_right)
|
|
||||||
{
|
{
|
||||||
MetaUIFrame *frame;
|
MetaUIFrame *frame;
|
||||||
MetaFrameGeometry fgeom;
|
MetaFrameGeometry fgeom;
|
||||||
|
MetaFrameFlags flags;
|
||||||
|
|
||||||
frame = meta_frames_lookup_window (frames, xwindow);
|
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)
|
meta_frames_calc_geometry (frames, frame, &fgeom);
|
||||||
*top_left = fgeom.top_left_corner_rounded_radius;
|
meta_theme_render_background (frame->tv->style_context, cr, flags, &fgeom);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -143,12 +143,9 @@ cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
|
|||||||
int window_width,
|
int window_width,
|
||||||
int window_height);
|
int window_height);
|
||||||
|
|
||||||
void meta_frames_get_corner_radiuses (MetaFrames *frames,
|
void meta_frames_render_background (MetaFrames *frames,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
float *top_left,
|
cairo_t *cr);
|
||||||
float *top_right,
|
|
||||||
float *bottom_left,
|
|
||||||
float *bottom_right);
|
|
||||||
|
|
||||||
void meta_frames_move_resize_frame (MetaFrames *frames,
|
void meta_frames_move_resize_frame (MetaFrames *frames,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
|
@ -1030,6 +1030,11 @@ double meta_theme_get_title_scale (MetaTheme *theme,
|
|||||||
MetaFrameType type,
|
MetaFrameType type,
|
||||||
MetaFrameFlags flags);
|
MetaFrameFlags flags);
|
||||||
|
|
||||||
|
void meta_theme_render_background (GtkStyleContext *style,
|
||||||
|
cairo_t *cr,
|
||||||
|
MetaFrameFlags flags,
|
||||||
|
const MetaFrameGeometry *fgeom);
|
||||||
|
|
||||||
void meta_theme_draw_frame (MetaTheme *theme,
|
void meta_theme_draw_frame (MetaTheme *theme,
|
||||||
GtkWidget *widget,
|
GtkWidget *widget,
|
||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
|
@ -4117,19 +4117,11 @@ button_rect (MetaButtonType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
meta_frame_style_draw_with_style (MetaFrameStyle *style,
|
meta_theme_render_background (GtkStyleContext *style_gtk,
|
||||||
GtkStyleContext *style_gtk,
|
cairo_t *cr,
|
||||||
MetaFrameFlags flags,
|
MetaFrameFlags flags,
|
||||||
cairo_t *cr,
|
const MetaFrameGeometry *fgeom)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
GdkRectangle visible_rect;
|
GdkRectangle visible_rect;
|
||||||
const MetaFrameBorders *borders;
|
const MetaFrameBorders *borders;
|
||||||
@ -4158,6 +4150,23 @@ meta_frame_style_draw_with_style (MetaFrameStyle *style,
|
|||||||
visible_rect.height);
|
visible_rect.height);
|
||||||
|
|
||||||
gtk_style_context_restore (style_gtk);
|
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
|
#if 0
|
||||||
int i, j;
|
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
|
void
|
||||||
meta_ui_get_corner_radiuses (MetaUI *ui,
|
meta_ui_render_background (MetaUI *ui,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
float *top_left,
|
cairo_t *cr)
|
||||||
float *top_right,
|
|
||||||
float *bottom_left,
|
|
||||||
float *bottom_right)
|
|
||||||
{
|
{
|
||||||
meta_frames_get_corner_radiuses (ui->frames, xwindow,
|
meta_frames_render_background (ui->frames, xwindow, cr);
|
||||||
top_left, top_right,
|
|
||||||
bottom_left, bottom_right);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window
|
Window
|
||||||
|
@ -100,12 +100,9 @@ cairo_region_t *meta_ui_get_frame_bounds (MetaUI *ui,
|
|||||||
int window_width,
|
int window_width,
|
||||||
int window_height);
|
int window_height);
|
||||||
|
|
||||||
void meta_ui_get_corner_radiuses (MetaUI *ui,
|
void meta_ui_render_background (MetaUI *ui,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
float *top_left,
|
cairo_t *cr);
|
||||||
float *top_right,
|
|
||||||
float *bottom_left,
|
|
||||||
float *bottom_right);
|
|
||||||
|
|
||||||
void meta_ui_queue_frame_draw (MetaUI *ui,
|
void meta_ui_queue_frame_draw (MetaUI *ui,
|
||||||
Window xwindow);
|
Window xwindow);
|
||||||
|
Loading…
Reference in New Issue
Block a user