void engine_draw_frame (decor_t * d, cairo_t * cr) { frame_settings *fs = d->fs; private_fs *pfs = fs->engine_fs; window_settings *ws = fs->ws; double x1, y1, x2, y2; x1 = ws->left_space - ws->win_extents.left; y1 = ws->top_space - ws->win_extents.top; x2 = d->width - ws->right_space + ws->win_extents.right; y2 = d->height - ws->bottom_space + ws->win_extents.bottom; int top; top = ws->win_extents.top + ws->titlebar_height; double m1 = MIN(ws->win_extents.left, ws->win_extents.right); double m2 = MIN(ws->win_extents.top, ws->win_extents.bottom); double border_width = MIN(m1, m2); double border_offset = border_width/2.0; cairo_set_line_width (cr, border_width); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); rounded_rectangle (cr, x1 + border_offset, y1 + top - border_offset, x2 - x1 - border_width, y2 - y1 - top, 0, ws, 0); cairo_set_source_alpha_color(cr, &pfs->border); cairo_stroke (cr); /* title bar */ if (pfs->title_bar.alpha != 0.0) { rounded_rectangle (cr, x1, y1, x2 - x1, top, 0, ws, 0); cairo_set_source_alpha_color(cr, &pfs->title_bar); cairo_fill(cr); } else { cairo_save(cr); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle (cr, 0.0, 0.0, d->width, top + y1 - border_width); cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); cairo_fill(cr); cairo_restore(cr); /* FIXME => find a proper solution for this */ #ifdef SHADOW_FIX cairo_rectangle (cr, 0.0, 0.0, d->width, top + y1 - border_width); cairo_clip(cr); cairo_translate(cr, 0.0, ws->top_space + ws->win_extents.top); draw_shadow_background(d, cr); cairo_translate(cr, 0.0, -ws->top_space - ws->win_extents.top); #endif } }
void meta_draw_window_decoration (decor_t *d) { Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); cairo_surface_t *surface; Picture src; MetaButtonState button_states [META_BUTTON_TYPE_LAST]; MetaButtonLayout button_layout; MetaFrameGeometry fgeom; MetaFrameFlags flags; MetaFrameType frame_type; MetaTheme *theme; GtkStyleContext *context; cairo_t *cr; gint i; GdkRectangle clip; Region top_region = NULL; Region bottom_region = NULL; Region left_region = NULL; Region right_region = NULL; gdouble meta_active_opacity, meta_inactive_opacity; gboolean meta_active_shade_opacity, meta_inactive_shade_opacity; g_object_get (settings, "metacity-active-opacity", &meta_active_opacity, NULL); g_object_get (settings, "metacity-inactive-opacity", &meta_inactive_opacity, NULL); g_object_get (settings, "metacity-active-shade-opacity", &meta_active_shade_opacity, NULL); g_object_get (settings, "metacity-inactive-shade-opacity", &meta_inactive_shade_opacity, NULL); double alpha = (d->active) ? meta_active_opacity : meta_inactive_opacity; gboolean shade_alpha = (d->active) ? meta_active_shade_opacity : meta_inactive_shade_opacity; MetaFrameStyle *frame_style; GtkWidget *style_window; GdkRGBA bg_rgba; if (!d->surface || !d->picture) return; if (decoration_alpha == 1.0) alpha = 1.0; if (cairo_xlib_surface_get_depth (d->surface) == 32) { context = gtk_widget_get_style_context (d->frame->style_window_rgba); style_window = d->frame->style_window_rgba; } else { context = gtk_widget_get_style_context (d->frame->style_window_rgb); style_window = d->frame->style_window_rgb; } cr = cairo_create (d->buffer_surface ? d->buffer_surface : d->surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); theme = meta_theme_get_current (); frame_type = meta_frame_type_from_string (d->frame->type); if (frame_type == META_FRAME_TYPE_LAST) frame_type = META_FRAME_TYPE_NORMAL; meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, frame_type, &clip); if ((d->prop_xid || !d->buffer_surface) && !d->frame_window) draw_shadow_background (d, cr, d->shadow, d->context); for (i = 0; i < META_BUTTON_TYPE_LAST; ++i) button_states[i] = meta_button_state_for_button_type (d, i); frame_style = meta_theme_get_frame_style (theme, frame_type, flags); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg_rgba); bg_rgba.alpha = 1.0; if (frame_style->window_background_color) { meta_color_spec_render (frame_style->window_background_color, gtk_widget_get_style_context (style_window), &bg_rgba); bg_rgba.alpha = frame_style->window_background_alpha / 255.0; } /* Draw something that will be almost invisible to user. This is hacky way * to fix invisible decorations. */ cairo_set_source_rgba (cr, 0, 0, 0, 0.01); cairo_rectangle (cr, 0, 0, 1, 1); cairo_fill (cr); /* ------------ */ cairo_destroy (cr); if (d->frame_window) surface = create_surface (clip.width, clip.height, d->frame->style_window_rgb); else surface = create_surface (clip.width, clip.height, d->frame->style_window_rgba); cr = cairo_create (surface); gdk_cairo_set_source_rgba (cr, &bg_rgba); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface), get_format_for_surface (d, surface), 0, NULL); cairo_paint (cr); meta_theme_draw_frame (theme, style_window, cr, frame_type, flags, clip.width - fgeom.left_width - fgeom.right_width, clip.height - fgeom.top_height - fgeom.bottom_height, d->layout, d->frame->text_height, &button_layout, button_states, d->icon_pixbuf, NULL); if (fgeom.top_height) { top_region = meta_get_top_border_region (&fgeom, clip.width); decor_blend_border_picture (xdisplay, d->context, src, 0, 0, d->picture, &d->border_layout, BORDER_TOP, top_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.bottom_height) { bottom_region = meta_get_bottom_border_region (&fgeom, clip.width); decor_blend_border_picture (xdisplay, d->context, src, 0, clip.height - fgeom.bottom_height, d->picture, &d->border_layout, BORDER_BOTTOM, bottom_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.left_width) { left_region = meta_get_left_border_region (&fgeom, clip.height); decor_blend_border_picture (xdisplay, d->context, src, 0, fgeom.top_height, d->picture, &d->border_layout, BORDER_LEFT, left_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.right_width) { right_region = meta_get_right_border_region (&fgeom, clip.height); decor_blend_border_picture (xdisplay, d->context, src, clip.width - fgeom.right_width, fgeom.top_height, d->picture, &d->border_layout, BORDER_RIGHT, right_region, alpha * 0xffff, shade_alpha, 0); } cairo_destroy (cr); cairo_surface_destroy (surface); XRenderFreePicture (xdisplay, src); copy_to_front_buffer (d); if (d->frame_window) { GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window); GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface (d->surface, 0, 0, d->width, d->height); gtk_image_set_from_pixbuf (GTK_IMAGE (d->decor_image), pixbuf); g_object_unref (pixbuf); gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height); gdk_window_move (gdk_frame_window, d->context->left_corner_space - 1, d->context->top_corner_space - 1); gdk_window_lower (gdk_frame_window); } if (d->prop_xid) { /* translate from frame to client window space */ if (top_region) XOffsetRegion (top_region, -fgeom.left_width, -fgeom.top_height); if (bottom_region) XOffsetRegion (bottom_region, -fgeom.left_width, 0); if (left_region) XOffsetRegion (left_region, -fgeom.left_width, 0); decor_update_meta_window_property (d, theme, flags, top_region, bottom_region, left_region, right_region); d->prop_xid = 0; } if (top_region) XDestroyRegion (top_region); if (bottom_region) XDestroyRegion (bottom_region); if (left_region) XDestroyRegion (left_region); if (right_region) XDestroyRegion (right_region); }