nsresult gfxGdkNativeRenderer::DrawWithXlib(gfxXlibSurface* surface, nsIntPoint offset, nsIntRect* clipRects, PRUint32 numClipRects) { GdkDrawable *drawable = gfxPlatformGtk::GetGdkDrawable(surface); if (!drawable) { gfxIntSize size = surface->GetSize(); int depth = cairo_xlib_surface_get_depth(surface->CairoSurface()); GdkScreen* screen = gdk_colormap_get_screen(mColormap); drawable = gdk_pixmap_foreign_new_for_screen(screen, surface->XDrawable(), size.width, size.height, depth); if (!drawable) return NS_ERROR_FAILURE; gdk_drawable_set_colormap(drawable, mColormap); gfxPlatformGtk::SetGdkDrawable(surface, drawable); g_object_unref(drawable); // The drawable now belongs to |surface|. } GdkRectangle clipRect; if (numClipRects) { NS_ASSERTION(numClipRects == 1, "Too many clip rects"); clipRect.x = clipRects[0].x; clipRect.y = clipRects[0].y; clipRect.width = clipRects[0].width; clipRect.height = clipRects[0].height; } return DrawWithGDK(drawable, offset.x, offset.y, numClipRects ? &clipRect : NULL, numClipRects); }
static cairo_surface_t * _create_temp_xlib_surface (cairo_t *cr, Display *dpy, int width, int height, cairo_xlib_drawing_support_t capabilities) { /* base the temp surface on the *screen* surface, not any intermediate * group surface, because the screen surface is more likely to have * characteristics that the xlib-using code is likely to be happy with */ cairo_surface_t *target = cairo_get_target (cr); Drawable target_drawable = cairo_xlib_surface_get_drawable (target); int screen_index = DefaultScreen (dpy); Drawable drawable = RootWindow (dpy, screen_index); Screen *screen = DefaultScreenOfDisplay (dpy); Visual *visual = DefaultVisual (dpy, screen_index); int depth = DefaultDepth (dpy, screen_index); Pixmap pixmap; cairo_surface_t *result; pixmap_free_struct *pfs; /* make the temporary surface match target_drawable to the extent supported by the native rendering code */ if (target_drawable) { Screen *target_screen = cairo_xlib_surface_get_screen (target); Visual *target_visual = cairo_xlib_surface_get_visual (target); if ((target_screen == screen || (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN)) && target_visual && (target_visual == DefaultVisualOfScreen (target_screen) || (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL))) { drawable = target_drawable; dpy = cairo_xlib_surface_get_display (target); visual = target_visual; depth = cairo_xlib_surface_get_depth (target); } } pfs = malloc (sizeof(pixmap_free_struct)); if (pfs == NULL) return NULL; pixmap = XCreatePixmap (dpy, drawable, width, height, depth); if (!pixmap) { free (pfs); return NULL; } pfs->dpy = dpy; pfs->pixmap = pixmap; result = cairo_xlib_surface_create (dpy, pixmap, visual, width, height); if (cairo_surface_status (result) != CAIRO_STATUS_SUCCESS) { pixmap_free_func (pfs); return NULL; } cairo_surface_set_user_data (result, &pixmap_free_key, pfs, pixmap_free_func); return result; }
already_AddRefed<gfxASurface> gfxXlibSurface::CreateSimilarSurface(gfxContentType aContent, const gfxIntSize& aSize) { if (!mSurface || !mSurfaceValid) { return nsnull; } if (aContent == CONTENT_COLOR) { // cairo_surface_create_similar will use a matching visual if it can. // However, systems with 16-bit or indexed default visuals may benefit // from rendering with 24-bit formats. static PRBool force24bpp = GetForce24bppPref(); if (force24bpp && cairo_xlib_surface_get_depth(CairoSurface()) != 24) { XRenderPictFormat* format = XRenderFindStandardFormat(mDisplay, PictStandardRGB24); if (format) { // Cairo only performs simple self-copies as desired if it // knows that this is a Pixmap surface. It only knows that // surfaces are pixmap surfaces if it creates the Pixmap // itself, so we use cairo_surface_create_similar with a // temporary reference surface to indicate the format. Screen* screen = cairo_xlib_surface_get_screen(CairoSurface()); nsRefPtr<gfxXlibSurface> depth24reference = gfxXlibSurface::Create(screen, format, gfxIntSize(1, 1), mDrawable); if (depth24reference) return depth24reference-> gfxASurface::CreateSimilarSurface(aContent, aSize); } } } return gfxASurface::CreateSimilarSurface(aContent, aSize); }
static cairo_test_status_t test_cairo_xlib_surface_get_depth (cairo_surface_t *surface) { int depth = cairo_xlib_surface_get_depth (surface); return depth == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR; }
static PyObject * xlib_surface_get_depth (PycairoXlibSurface *o) { return PyInt_FromLong (cairo_xlib_surface_get_depth (o->surface)); }
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); }