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;
}
Example #3
0
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));
}
Example #6
0
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);
}