Esempio n. 1
0
static cairo_surface_t *
create_root_surface (GdkScreen *screen)
{
    Atom prop_root, prop_esetroot;
    gint number, width, height;
    Display *display;
    Pixmap pixmap;
    cairo_surface_t *surface;

    number = gdk_screen_get_number (screen);
    width = gdk_screen_get_width (screen);
    height = gdk_screen_get_height (screen);

    /* Open a new connection so with Retain Permanent so the pixmap remains when the greeter quits */
    gdk_flush ();
    display = XOpenDisplay (gdk_display_get_name (gdk_screen_get_display (screen)));
    if (!display)
    {
        g_warning ("Failed to create root pixmap");
        return NULL;
    }
    XSetCloseDownMode (display, RetainPermanent);
    pixmap = XCreatePixmap (display, RootWindow (display, number), width, height, DefaultDepth (display, number));
    XCloseDisplay (display);

    /* Convert into a Cairo surface */
    surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
                                         pixmap,
                                         GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)),
                                         width, height);

    /* Use this pixmap for the background */
    XSetWindowBackgroundPixmap (GDK_SCREEN_XDISPLAY (screen),
                                RootWindow (GDK_SCREEN_XDISPLAY (screen), number),
                                cairo_xlib_surface_get_drawable (surface));



    /* Fix to make the code work when a compositor is running */
    Pixmap xpm = cairo_xlib_surface_get_drawable (surface);
    prop_root = XInternAtom(GDK_SCREEN_XDISPLAY (screen), "_XROOTPMAP_ID", False);
    prop_esetroot = XInternAtom(GDK_SCREEN_XDISPLAY (screen), "ESETROOT_PMAP_ID", False);

    XChangeProperty(GDK_SCREEN_XDISPLAY (screen), RootWindow (GDK_SCREEN_XDISPLAY (screen), number), prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &xpm, 1);
    XChangeProperty(GDK_SCREEN_XDISPLAY (screen), RootWindow (GDK_SCREEN_XDISPLAY (screen), number), prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &xpm, 1);


    return surface;
}
Esempio n. 2
0
GdkWindow *clg_gdk_cairo_surface_get_window (cairo_surface_t *surface)
{
  /* If 'surface_info_key' had been public we would have had a
     portable way to find the GdkWindow of a Cairo surface. */
  
#ifdef GDK_WINDOWING_X11
  g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB);
  
  Display* display = cairo_xlib_surface_get_display (surface);
  if (display) {
    Drawable window = cairo_xlib_surface_get_drawable (surface);
    if (window)
      return gdk_window_lookup_for_display (window, display);
  }

  return NULL;
#elif defined (G_OS_WIN32)
  HDC hdc = (HDC)cairo_win32_surface_get_dc (surface);
  if (hdc)
    return gdk_window_lookup ((GdkNativeWindow)hdc);
  else
    return NULL;
#else
  return NULL;
#endif
}
gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf)
    : mPixmapTaken(PR_FALSE), mSize(-1.0, -1.0)
{
    mDrawable = cairo_xlib_surface_get_drawable(csurf);
    mDisplay = cairo_xlib_surface_get_display(csurf);

    Init(csurf, PR_TRUE);
}
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;
}
Esempio n. 5
0
gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf)
    : mPixmapTaken(PR_FALSE),
      mSize(cairo_xlib_surface_get_width(csurf),
            cairo_xlib_surface_get_height(csurf))
{
    NS_PRECONDITION(cairo_surface_status(csurf) == 0,
                    "Not expecting an error surface");

    mDrawable = cairo_xlib_surface_get_drawable(csurf);
    mDisplay = cairo_xlib_surface_get_display(csurf);

    Init(csurf, PR_TRUE);
}
Esempio n. 6
0
void
decor_update_switcher_property (decor_t *d)
{
    long	 *data;
    Display	 *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
    gint	 nQuad;
    decor_quad_t quads[N_QUADS_MAX];
    unsigned int    nOffset = 1;
    unsigned int   frame_type = populate_frame_type (d);
    unsigned int   frame_state = populate_frame_state (d);
    unsigned int   frame_actions = populate_frame_actions (d);
    GtkStyleContext *context;
    GdkRGBA fg;
    long         fgColor[4];
    
    nQuad = decor_set_lSrStSbX_window_quads (quads, &d->frame->window_context_active,
					     &d->border_layout,
					     d->border_layout.top.x2 -
					     d->border_layout.top.x1 -
					     d->frame->window_context_active.extents.left -
						 d->frame->window_context_active.extents.right -
						     32);
    
    data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_PIXMAP);
    decor_quads_to_property (data, nOffset - 1, cairo_xlib_surface_get_drawable (d->surface),
			     &d->frame->win_extents, &d->frame->win_extents,
			     &d->frame->win_extents, &d->frame->win_extents,
			     0, 0, quads, nQuad, frame_type, frame_state, frame_actions);

    context = gtk_widget_get_style_context (d->frame->style_window_rgba);
    gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &fg);

    fgColor[0] = fg.red;
    fgColor[1] = fg.green;
    fgColor[2] = fg.blue;
    fgColor[3] = SWITCHER_ALPHA;
    
    gdk_error_trap_push ();
    XChangeProperty (xdisplay, d->prop_xid,
		     win_decor_atom,
		     XA_INTEGER,
		     32, PropModeReplace, (guchar *) data,
		     PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX);
    XChangeProperty (xdisplay, d->prop_xid, switcher_fg_atom,
		     XA_INTEGER, 32, PropModeReplace, (guchar *) fgColor, 4);
    gdk_display_sync (gdk_display_get_default ());
    gdk_error_trap_pop_ignored ();

    free (data);
}
Esempio n. 7
0
static void
free_background_surface (EelBackground *self)
{
    cairo_surface_t *surface;

    surface = self->details->bg_surface;
    if (surface != NULL)
    {
        /* If we created a root surface and didn't set it as background
           it will live forever, so we need to kill it manually.
           If set as root background it will be killed next time the
           background is changed. */
        if (self->details->unset_root_surface)
        {
            XKillClient (cairo_xlib_surface_get_display (surface),
                         cairo_xlib_surface_get_drawable (surface));
        }
        cairo_surface_destroy (surface);
        self->details->bg_surface = NULL;
    }
}
Esempio n. 8
0
char *
panel_background_make_string (PanelBackground *background,
			      int              x,
			      int              y)
{
	PanelBackgroundType  effective_type;
	char                *retval;

	retval = NULL;

	effective_type = panel_background_effective_type (background);

	if (effective_type == PANEL_BACK_IMAGE ||
	    (effective_type == PANEL_BACK_COLOR && background->has_alpha
	    && (!gdk_window_check_composited_wm(background->window)))) {
		cairo_surface_t *surface;

		if (!background->composited_pattern)
			return NULL;

		if (cairo_pattern_get_surface (background->composited_pattern, &surface) != CAIRO_STATUS_SUCCESS)
			return NULL;

		if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
			return NULL;

		retval = g_strdup_printf ("pixmap:%d,%d,%d", (guint32)cairo_xlib_surface_get_drawable (surface), x, y);
	} else if (effective_type == PANEL_BACK_COLOR) {
		gchar *rgba = gdk_rgba_to_string (&background->color);
		retval = g_strdup_printf (
				"color:%s",
				rgba);
		g_free (rgba);
	} else
		retval = g_strdup ("none:");

	return retval;
}
static cairo_bool_t
_draw_onto_temp_xlib_surface (cairo_surface_t *temp_xlib_surface,
                              cairo_xlib_drawing_callback callback,
                              void *closure,
                              double background_gray_value)
{
    Drawable d = cairo_xlib_surface_get_drawable (temp_xlib_surface);
    Screen *screen = cairo_xlib_surface_get_screen (temp_xlib_surface);
    Visual *visual = cairo_xlib_surface_get_visual (temp_xlib_surface);
    cairo_bool_t result;
    cairo_t *cr = cairo_create (temp_xlib_surface);
    cairo_set_source_rgb (cr, background_gray_value, background_gray_value,
                          background_gray_value);
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint (cr);
    cairo_destroy (cr);
    
    cairo_surface_flush (temp_xlib_surface);
    /* no clipping is needed because the callback can't draw outside the native
       surface anyway */
    result = callback (closure, screen, d, visual, 0, 0, NULL, 0);
    cairo_surface_mark_dirty (temp_xlib_surface);
    return result;
}
Esempio n. 10
0
void
decor_update_window_property (decor_t *d)
{
    long	    *data;
    Display	    *xdisplay =
	GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
    decor_extents_t extents = d->frame->win_extents;
    gint	    nQuad;
    unsigned int    nOffset = 1;
    unsigned int   frame_type = populate_frame_type (d);
    unsigned int   frame_state = populate_frame_state (d);
    unsigned int   frame_actions = populate_frame_actions (d);
    decor_quad_t    quads[N_QUADS_MAX];
    int		    w, h;
    gint	    stretch_offset;
    REGION	    top, bottom, left, right;

    w = d->border_layout.top.x2 - d->border_layout.top.x1 -
	d->context->left_space - d->context->right_space;

    if (d->border_layout.rotation)
	h = d->border_layout.left.x2 - d->border_layout.left.x1;
    else
	h = d->border_layout.left.y2 - d->border_layout.left.y1;

    stretch_offset = w - d->button_width - 1;

    nQuad = decor_set_lSrStXbS_window_quads (quads, d->context,
					     &d->border_layout,
					     stretch_offset);

    extents.top += d->frame->titlebar_height;

    if (d->frame_window)
    {
        data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_WINDOW);
        decor_gen_window_property (data, nOffset - 1, &extents, &extents, 20, 20, frame_type, frame_state, frame_actions);
    }
    else
    {
        data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_PIXMAP);
        decor_quads_to_property (data, nOffset - 1, cairo_xlib_surface_get_drawable (d->surface),
			     &extents, &extents,
			     &extents, &extents,
			     ICON_SPACE + d->button_width,
			     0,
			     quads, nQuad, frame_type, frame_state, frame_actions);
    }

    gdk_error_trap_push ();
    XChangeProperty (xdisplay, d->prop_xid,
		     win_decor_atom,
		     XA_INTEGER,
		     32, PropModeReplace, (guchar *) data,
		     PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX);
    gdk_display_sync (gdk_display_get_default ());
    gdk_error_trap_pop_ignored ();

    top.rects = &top.extents;
    top.numRects = top.size = 1;

    top.extents.x1 = -extents.left;
    top.extents.y1 = -extents.top;
    top.extents.x2 = w + extents.right;
    top.extents.y2 = 0;

    bottom.rects = &bottom.extents;
    bottom.numRects = bottom.size = 1;

    bottom.extents.x1 = -extents.left;
    bottom.extents.y1 = 0;
    bottom.extents.x2 = w + extents.right;
    bottom.extents.y2 = extents.bottom;

    left.rects = &left.extents;
    left.numRects = left.size = 1;

    left.extents.x1 = -extents.left;
    left.extents.y1 = 0;
    left.extents.x2 = 0;
    left.extents.y2 = h;

    right.rects = &right.extents;
    right.numRects = right.size = 1;

    right.extents.x1 = 0;
    right.extents.y1 = 0;
    right.extents.x2 = extents.right;
    right.extents.y2 = h;

    decor_update_blur_property (d,
				w, h,
				&top, stretch_offset,
				&bottom, w / 2,
				&left, h / 2,
				&right, h / 2);

    free (data);
}
Esempio n. 11
0
gboolean
update_window_decoration_size (WnckWindow *win)
{
    decor_t           *d;
    cairo_surface_t   *surface, *buffer_surface = NULL;
    Picture           picture;
    Display           *xdisplay;
    XRenderPictFormat *format;

    if (win == NULL)
	return FALSE;

    d = g_object_get_data (G_OBJECT (win), "decor");

    if (!d->decorated)
	return FALSE;

    xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());

    gdk_error_trap_push ();

    /* Get the correct depth for the frame window in reparenting mode, otherwise
     * enforce 32 */
    if (d->frame_window)
	surface = create_native_surface_and_wrap (d->width, d->height, d->frame->style_window_rgb);
    else
	surface = create_native_surface_and_wrap (d->width, d->height, d->frame->style_window_rgba);

    gdk_flush ();

    /* Handle failure */
    if (!surface || gdk_error_trap_pop ())
    {
	if (surface)
	    cairo_surface_destroy (surface);
	return FALSE;
    }

    gdk_error_trap_push ();

    if (d->frame_window)
	buffer_surface = create_surface (d->width, d->height, d->frame->style_window_rgb);
    else
	buffer_surface = create_surface (d->width, d->height, d->frame->style_window_rgba);

    gdk_flush ();

    /* Handle failure */
    if (!buffer_surface || gdk_error_trap_pop ())
    {
	if (buffer_surface)
	    cairo_surface_destroy (buffer_surface);
	cairo_surface_destroy (surface);
	return FALSE;
    }

    /* Create XRender context */
    format = get_format_for_surface (d, buffer_surface);
    picture = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (buffer_surface),
				    format, 0, NULL);

    /* Destroy the old pixmaps and pictures */
    if (d->surface)
	cairo_surface_destroy (d->surface);

    if (d->x11Pixmap)
	decor_post_delete_pixmap (xdisplay,
				  wnck_window_get_xid (d->win),
				  d->x11Pixmap);

    if (d->buffer_surface)
	cairo_surface_destroy (d->buffer_surface);

    if (d->picture)
	XRenderFreePicture (xdisplay, d->picture);

    if (d->cr)
	cairo_destroy (d->cr);

    /* Assign new pixmaps and pictures */
    d->surface        = surface;
    d->x11Pixmap      = cairo_xlib_surface_get_drawable (d->surface);
    d->buffer_surface = buffer_surface;
    d->cr             = cairo_create (surface);

    d->picture = picture;

    d->prop_xid = wnck_window_get_xid (win);

    update_window_decoration_name (win);

    /* Redraw decoration on idle */
    queue_decor_draw (d);

    return TRUE;
}
Esempio n. 12
0
/*
 * update_default_decorations
 *
 * Description: update the default decorations
 */
void
update_default_decorations (GdkScreen *screen)
{
    long	    *data;
    Window	    xroot;
    GdkDisplay	    *gdkdisplay = gdk_display_get_default ();
    Display	    *xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
    Atom	    bareAtom, activeAtom;
    decor_frame_t   *frame;
    decor_frame_t   *bare_frame = gwd_get_decor_frame ("bare");
    decor_extents_t extents;
    unsigned int    i;

    xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));

    bareAtom   = XInternAtom (xdisplay, DECOR_BARE_ATOM_NAME, FALSE);
    activeAtom = XInternAtom (xdisplay, DECOR_ACTIVE_ATOM_NAME, FALSE);

    if (bare_frame->border_shadow_active)
    {
	decor_layout_t layout;
	unsigned int   frame_type = 0;
	unsigned int   frame_state = 0;
	unsigned int   frame_actions = 0;
	unsigned int   nQuad;
	decor_quad_t   quads[N_QUADS_MAX];

	long *data = decor_alloc_property (1, WINDOW_DECORATION_TYPE_PIXMAP);

	decor_get_default_layout (&bare_frame->window_context_active, 1, 1, &layout);

	nQuad = decor_set_lSrStSbS_window_quads (quads, &bare_frame->window_context_active,
						 &layout);

	decor_quads_to_property (data, 0, bare_frame->border_shadow_active->pixmap,
				 &bare_frame->win_extents, &bare_frame->win_extents,
				 &bare_frame->win_extents, &bare_frame->win_extents,
				 0, 0, quads, nQuad, frame_type, frame_state, frame_actions);

	XChangeProperty (xdisplay, xroot,
			 bareAtom,
			 XA_INTEGER,
			 32, PropModeReplace, (guchar *) data,
			 PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX);

	if (minimal)
	{
	    XChangeProperty (xdisplay, xroot,
			     activeAtom,
			     XA_INTEGER,
			     32, PropModeReplace, (guchar *) data,
			     PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX);
	}

        free (data);
    }
    else
    {
	XDeleteProperty (xdisplay, xroot, bareAtom);

	if (minimal)
	{
	    XDeleteProperty (xdisplay, xroot, activeAtom);
	}
    }

    if (minimal)
    {
	gwd_decor_frame_unref (bare_frame);
	return;
    }

    XDeleteProperty (xdisplay, xroot,
                     activeAtom);

    data = decor_alloc_property (WINDOW_TYPE_FRAMES_NUM * 2, WINDOW_DECORATION_TYPE_PIXMAP);

    /* All active states and all inactive states */
    for (i = 0; i < WINDOW_TYPE_FRAMES_NUM * 2; ++i)
    {
        frame = gwd_get_decor_frame (default_frames[i].name);
        extents = frame->win_extents;

        if (default_frames[i].d)
        {
            if (default_frames[i].d->surface)
                cairo_surface_destroy (default_frames[i].d->surface);

            free (default_frames[i].d);
        }

        default_frames[i].d = calloc (1, sizeof (decor_t));

        default_frames[i].d->context = i < WINDOW_TYPE_FRAMES_NUM ? &frame->window_context_active : &frame->window_context_inactive;
        default_frames[i].d->shadow  =  i < WINDOW_TYPE_FRAMES_NUM ? frame->border_shadow_active : frame->border_shadow_inactive;
        default_frames[i].d->layout  = pango_layout_new (frame->pango_context);

        decor_get_default_layout (default_frames[i].d->context, 1, 1, &default_frames[i].d->border_layout);

        default_frames[i].d->width  = default_frames[i].d->border_layout.width;
        default_frames[i].d->height = default_frames[i].d->border_layout.height;

        default_frames[i].d->frame = frame;
        default_frames[i].d->active = i < WINDOW_TYPE_FRAMES_NUM ? TRUE : FALSE;

        extents.top += frame->titlebar_height;

        default_frames[i].d->draw = theme_draw_window_decoration;
	default_frames[i].d->surface = create_native_surface_and_wrap (default_frames[i].d->width,
	                                                               default_frames[i].d->height,
	                                                               frame->style_window_rgba);

	unsigned int j, k;

	for (j = 0; j < 3; ++j)
	{
	    for (k = 0; k < 3; k++)
	    {
		default_frames[i].d->event_windows[j][k].window = None;
	    }
	}

	for (j = 0; j < BUTTON_NUM; ++j)
	{
	    default_frames[i].d->button_windows[j].window = None;
	    default_frames[i].d->button_states[j] = 0;
	}

        if (default_frames[i].d->surface)
        {
            gint	    nQuad;
            unsigned int   frame_type = populate_frame_type (default_frames[i].d);
            unsigned int   frame_state = populate_frame_state (default_frames[i].d);
            unsigned int   frame_actions = populate_frame_actions (default_frames[i].d);
            decor_quad_t    quads[N_QUADS_MAX];

            nQuad = decor_set_lSrStSbS_window_quads (quads, default_frames[i].d->context,
                                                     &default_frames[i].d->border_layout);

            default_frames[i].d->picture = XRenderCreatePicture (xdisplay,
                                                                 cairo_xlib_surface_get_drawable (default_frames[i].d->surface),
                                                                 xformat_rgba, 0, NULL);

            (*default_frames[i].d->draw) (default_frames[i].d);

            decor_quads_to_property (data, i, cairo_xlib_surface_get_drawable (default_frames[i].d->surface),
                                     &extents, &extents,
                                     &extents, &extents, 0, 0, quads, nQuad, frame_type, frame_state, frame_actions);
        }

        gwd_decor_frame_unref (frame);
    }

    XChangeProperty (xdisplay, xroot,
                     activeAtom,
                     XA_INTEGER,
                     32, PropModeAppend, (guchar *) data,
                     PROP_HEADER_SIZE + (WINDOW_TYPE_FRAMES_NUM * 2) * (BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX));

    free (data);

    gwd_decor_frame_unref (bare_frame);
}
Esempio n. 13
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);
}
/**
 * Try the direct path.
 * @param status the status returned by the callback, if we took the direct path
 * @return True if we took the direct path
 */
static cairo_bool_t
_draw_with_xlib_direct (cairo_t *cr,
                        Display *default_display,
                        cairo_xlib_drawing_callback callback,
                        void *closure,
                        int bounds_width, int bounds_height,
                        cairo_xlib_drawing_support_t capabilities)
{
    cairo_surface_t *target;
    Drawable d;
    cairo_matrix_t matrix;
    short offset_x, offset_y;
    cairo_bool_t needs_clip;
    XRectangle rectangles[MAX_STATIC_CLIP_RECTANGLES];
    int rect_count;
    double device_offset_x, device_offset_y;
    int max_rectangles;
    Screen *screen;
    Visual *visual;
    cairo_bool_t have_rectangular_clip;

    target = cairo_get_group_target (cr);
    cairo_surface_get_device_offset (target, &device_offset_x, &device_offset_y);
    d = cairo_xlib_surface_get_drawable (target);

    cairo_get_matrix (cr, &matrix);
    
    /* Check that the matrix is a pure translation */
    /* XXX test some approximation to == 1.0 here? */
    if (matrix.xx != 1.0 || matrix.yy != 1.0 || matrix.xy != 0.0 || matrix.yx != 0.0) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: matrix not a pure translation\n");
        return False;
    }
    /* Check that the matrix translation offsets (adjusted for
       device offset) are integers */
    if (!_convert_coord_to_short (matrix.x0 + device_offset_x, &offset_x) ||
        !_convert_coord_to_short (matrix.y0 + device_offset_y, &offset_y)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-integer offset\n");
        return False;
    }
    
    max_rectangles = 0;
    if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_RECT) {
      max_rectangles = 1;
    }
    if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_LIST) {
      max_rectangles = MAX_STATIC_CLIP_RECTANGLES;
    }
    
    /* Check that the clip is rectangular and aligned on unit boundaries. */
    /* Temporarily set the matrix for _get_rectangular_clip. It's basically
       the identity matrix, but we must adjust for the fact that our
       offset-rect is in device coordinates. */
    cairo_identity_matrix (cr);
    cairo_translate (cr, -device_offset_x, -device_offset_y);
    have_rectangular_clip =
        _get_rectangular_clip (cr,
                               offset_x, offset_y, bounds_width, bounds_height,
                               &needs_clip,
                               rectangles, max_rectangles, &rect_count);
    cairo_set_matrix (cr, &matrix);
    if (!have_rectangular_clip) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported clip\n");
        return False;
    }

    /* Stop now if everything is clipped out */
    if (needs_clip && rect_count == 0) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH: all clipped\n");
        return True;
    }
      
    /* Check that the operator is OVER */
    if (cairo_get_operator (cr) != CAIRO_OPERATOR_OVER) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-OVER operator\n");
        return False;
    }
    
    /* Check that the offset is supported */  
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_OFFSET) &&
        (offset_x != 0 || offset_y != 0)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported offset\n");
        return False;
    }
    
    /* Check that the target surface is an xlib surface. Do this late because
       we might complete early above when when the object to be drawn is
       completely clipped out. */
    if (!d) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-X surface\n");
        return False;
    }
    
    /* Check that the display is supported */  
    screen = cairo_xlib_surface_get_screen (target);
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN) &&
        screen != DefaultScreenOfDisplay (default_display)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default display\n");
        return False;
    }
        
    /* Check that there is a visual */
    visual = cairo_xlib_surface_get_visual (target);
    if (!visual) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: no Visual for surface\n");
        return False;
    }        
    /* Check that the visual is supported */
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL) &&
        DefaultVisualOfScreen (screen) != visual) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default visual\n");
        return False;
    }
  
    /* we're good to go! */
    CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH\n");
    cairo_surface_flush (target);
    callback (closure, screen, d, visual, offset_x, offset_y, rectangles,
              needs_clip ? rect_count : 0);
    cairo_surface_mark_dirty (target);
    return True;
}
Esempio n. 15
0
static cairo_test_status_t
test_cairo_xlib_surface_get_drawable (cairo_surface_t *surface)
{
    Drawable drawable = cairo_xlib_surface_get_drawable (surface);
    return drawable == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
}
Esempio n. 16
0
static void
decor_update_meta_window_property (decor_t	  *d,
				   MetaTheme	  *theme,
				   MetaFrameFlags flags,
				   Region	  top,
				   Region	  bottom,
				   Region	  left,
				   Region	  right)
{
    long	    *data;
    Display	    *xdisplay =
	GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
    gint	    nQuad;
    decor_extents_t win_extents, frame_win_extents;
    decor_extents_t max_win_extents, frame_max_win_extents;
    decor_quad_t    quads[N_QUADS_MAX];
    unsigned int    nOffset = 1;
    unsigned int    frame_type = populate_frame_type (d);
    unsigned int    frame_state = populate_frame_state (d);
    unsigned int    frame_actions = populate_frame_actions (d);
    gint            w, lh, rh;
    gint	    top_stretch_offset;
    gint	    bottom_stretch_offset;
    gint	    left_stretch_offset;
    gint	    right_stretch_offset;
    gint	    mutter_draggable_border_width = 0;

    win_extents = frame_win_extents = d->frame->win_extents;
    max_win_extents = frame_max_win_extents = d->frame->max_win_extents;

    g_object_get (settings, "draggable-border-width", &mutter_draggable_border_width, NULL);

    /* Add the invisible grab area padding, but only for
     * pixmap type decorations */
    if (!d->frame_window)
    {
	if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE)
	{
	    frame_win_extents.left += mutter_draggable_border_width;
	    frame_win_extents.right += mutter_draggable_border_width;
	    frame_max_win_extents.left += mutter_draggable_border_width;
	    frame_max_win_extents.right += mutter_draggable_border_width;
	}

	if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE)
	{
	    frame_win_extents.bottom += mutter_draggable_border_width;
	    frame_win_extents.top += mutter_draggable_border_width;
	    frame_max_win_extents.bottom += mutter_draggable_border_width;
	    frame_max_win_extents.top += mutter_draggable_border_width;
	}
    }

    w = d->border_layout.top.x2 - d->border_layout.top.x1 -
	d->context->left_space - d->context->right_space;

    if (d->border_layout.rotation)
	lh = d->border_layout.left.x2 - d->border_layout.left.x1;
    else
	lh = d->border_layout.left.y2 - d->border_layout.left.y1;

    if (d->border_layout.rotation)
	rh = d->border_layout.right.x2 - d->border_layout.right.x1;
    else
	rh = d->border_layout.right.y2 - d->border_layout.right.y1;

    left_stretch_offset   = lh / 2;
    right_stretch_offset  = rh / 2;
    top_stretch_offset    = w - d->button_width - 1;
    bottom_stretch_offset = (d->border_layout.bottom.x2 -
			     d->border_layout.bottom.x1 -
			     d->context->left_space -
			     d->context->right_space) / 2;

    nQuad = decor_set_lXrXtXbX_window_quads (quads, d->context,
					     &d->border_layout,
					     left_stretch_offset,
					     right_stretch_offset,
					     top_stretch_offset,
					     bottom_stretch_offset);

    win_extents.top += d->frame->titlebar_height;
    frame_win_extents.top += d->frame->titlebar_height;
    max_win_extents.top += d->frame->max_titlebar_height;
    frame_max_win_extents.top += d->frame->max_titlebar_height;

    if (d->frame_window)
    {
	data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_WINDOW);
	decor_gen_window_property (data, nOffset - 1, &win_extents, &max_win_extents, 20, 20,
				   frame_type, frame_state, frame_actions);
    }
    else
    {
	data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_PIXMAP);
	decor_quads_to_property (data, nOffset - 1, cairo_xlib_surface_get_drawable (d->surface),
				 &frame_win_extents, &win_extents,
				 &frame_max_win_extents, &max_win_extents,
				 ICON_SPACE + d->button_width,
				 0,
				 quads, nQuad, frame_type, frame_state, frame_actions);
    }

    gdk_error_trap_push ();

    XChangeProperty (xdisplay, d->prop_xid,
		     win_decor_atom,
		     XA_INTEGER,
		     32, PropModeReplace, (guchar *) data,
		     PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX);
    gdk_display_sync (gdk_display_get_default ());
    gdk_error_trap_pop_ignored ();

    free (data);

    decor_update_blur_property (d,
				w, lh,
				top, top_stretch_offset,
				bottom, bottom_stretch_offset,
				left, left_stretch_offset,
				right, right_stretch_offset);
}
Esempio n. 17
0
void desktop_set_background (GtkWidget *desktop, gchar *wallpaper, FmWallpaperMode wallpaper_mode,
                             GdkColor *color_background)
{
    
    GdkPixbuf *pixbuf;

    
    GdkWindow *root = gdk_screen_get_root_window (gtk_widget_get_screen (desktop));
    GdkWindow *window = gtk_widget_get_window (desktop);

    if (wallpaper_mode == FM_WP_COLOR
       || !wallpaper
       || !*wallpaper
       || !(pixbuf = gdk_pixbuf_new_from_file (wallpaper, NULL)))
    {
        //GdkColor bg = color_background;

        //gdk_rgb_find_color (gdk_drawable_get_colormap (window), &bg);
        
        //gdk_window_set_back_pixmap (window, NULL, FALSE);
        gdk_window_set_background (window, color_background);
        
        //gdk_window_set_back_pixmap (root, NULL, FALSE);
        gdk_window_set_background (root, color_background);
        
        //gdk_window_clear (root);
        //gdk_window_clear (window);
        
        gdk_window_invalidate_rect (window, NULL, TRUE);
        
        return;
    }

//    #if 0
    
    int src_w = gdk_pixbuf_get_width (pixbuf);
    int src_h = gdk_pixbuf_get_height (pixbuf);
    
    
    cairo_surface_t *surface;
    int dest_w;
    int dest_h;
    
    if (wallpaper_mode == FM_WP_TILE)
    {
        dest_w = src_w;
        dest_h = src_h;
        
        //pixmap = gdk_pixmap_new (window, dest_w, dest_h, -1);
        surface = gdk_window_create_similar_surface (window, CAIRO_CONTENT_COLOR, dest_w, dest_h);
    
    }
    else
    {
        GdkScreen *screen = gtk_widget_get_screen (desktop);
        dest_w = gdk_screen_get_width (screen);
        dest_h = gdk_screen_get_height (screen);
        
        //pixmap = gdk_pixmap_new (window, dest_w, dest_h, -1);
        surface = gdk_window_create_similar_surface (window, CAIRO_CONTENT_COLOR, dest_w, dest_h);
    }

    //~ if (gdk_pixbuf_get_has_alpha (pixbuf)
        //~ || wallpaper_mode == FM_WP_CENTER
        //~ || wallpaper_mode == FM_WP_FIT)
    //~ {
        //~ gdk_gc_set_rgb_fg_color (desktop->gc, &color_background);
        //~ gdk_draw_rectangle (pixmap, desktop->gc, TRUE, 0, 0, dest_w, dest_h);
    //~ }

//    GdkPixbuf *scaled;

    cairo_t *cr;

    switch (wallpaper_mode)
    {
        case FM_WP_COLOR:
        break;
        
        case FM_WP_TILE:
        
            //gdk_draw_pixbuf (pixmap, desktop->gc, pixbuf, 0, 0, 0, 0, dest_w, dest_h, GDK_RGB_DITHER_NORMAL, 0, 0);
            
            cr = cairo_create (surface);
            gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
            cairo_paint (cr);
            cairo_destroy (cr);
            
        break;
        
        case FM_WP_STRETCH:
            //~ if (dest_w == src_w && dest_h == src_h)
                //~ scaled = (GdkPixbuf*) g_object_ref (pixbuf);
            //~ else
                //~ scaled = gdk_pixbuf_scale_simple (pixbuf, dest_w, dest_h, GDK_INTERP_BILINEAR);
            //~ 
            //~ gdk_draw_pixbuf (pixmap, desktop->gc, scaled, 0, 0, 0, 0, dest_w, dest_h, GDK_RGB_DITHER_NORMAL, 0, 0);
            //~ 
            //~ g_object_unref (scaled);
        break;
        
        case FM_WP_FIT:
            
            //~ if (dest_w != src_w || dest_h != src_h)
            //~ {
                //~ gdouble w_ratio = (float) dest_w / src_w;
                //~ gdouble h_ratio = (float) dest_h / src_h;
                //~ gdouble ratio = MIN (w_ratio, h_ratio);
                //~ 
                //~ if (ratio != 1.0)
                //~ {
                    //~ src_w *= ratio;
                    //~ src_h *= ratio;
                    //~ 
                    //~ scaled = gdk_pixbuf_scale_simple (pixbuf, src_w, src_h, GDK_INTERP_BILINEAR);
                    //~ 
                    //~ g_object_unref (pixbuf);
                    //~ pixbuf = scaled;
                //~ }
            //~ }
        
        case FM_WP_CENTER:
        {
            //~ int x;
            //~ int y;
            //~ x = (dest_w - src_w) / 2;
            //~ y = (dest_h - src_h) / 2;
            //~ 
            //~ gdk_draw_pixbuf (pixmap, desktop->gc, pixbuf, 0, 0, x, y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
        }
        break;
    }
    
    
    Display *xdisplay;
    Pixmap xpixmap = 0;
    Window xroot;
    
    cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
    
    //gdk_window_set_back_pixmap (root, pixmap, FALSE);
	gdk_window_set_background_pattern (root, pattern);

    //gdk_window_set_back_pixmap (window, NULL, TRUE);
	gdk_window_set_background_pattern (window, pattern);

    cairo_pattern_destroy (pattern);
    
    Pixmap pixmap_id = cairo_xlib_surface_get_drawable (surface);
    
    XChangeProperty (GDK_WINDOW_XDISPLAY (root),
                     GDK_WINDOW_XID (root),
                     gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"),   //XA_XROOTMAP_ID,
                     XA_PIXMAP,
                     32,
                     PropModeReplace, 
                     (guchar*) &pixmap_id,
                     1);

    // Set root map here...
    xdisplay = GDK_WINDOW_XDISPLAY (root);
    xroot = GDK_WINDOW_XID (root);

    XGrabServer (xdisplay);

    if (surface)
    {
        xpixmap = cairo_xlib_surface_get_drawable (surface);

        XChangeProperty (xdisplay,
                         xroot,
                         gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"),
                         XA_PIXMAP,
                         32,
                         PropModeReplace,
                         (guchar *) &xpixmap,
                         1);

        XSetWindowBackgroundPixmap (xdisplay, xroot, xpixmap);
    }
    else
    {
        // Anyone knows how to handle this correctly ?
    }
    
    XClearWindow (xdisplay, xroot);

    XUngrabServer (xdisplay);
    XFlush (xdisplay);

    cairo_surface_destroy (surface);
    
    if (pixbuf)
        g_object_unref (pixbuf);

//    gdk_window_clear (root);
//    gdk_window_clear (window);
    
    gdk_window_invalidate_rect (window, NULL, TRUE);
//    #endif
}
static already_AddRefed<gfxXlibSurface>
CreateTempXlibSurface (gfxASurface *destination, nsIntSize size,
                       bool canDrawOverBackground,
                       PRUint32 flags, Screen *screen, Visual *visual,
                       DrawingMethod *method)
{
    bool drawIsOpaque = (flags & gfxXlibNativeRenderer::DRAW_IS_OPAQUE) != 0;
    bool supportsAlternateVisual =
        (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
    bool supportsAlternateScreen = supportsAlternateVisual &&
        (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_SCREEN);

    cairo_surface_t *target = destination->CairoSurface();
    cairo_surface_type_t target_type = cairo_surface_get_type (target);
    cairo_content_t target_content = cairo_surface_get_content (target);

    Screen *target_screen = target_type == CAIRO_SURFACE_TYPE_XLIB ?
        cairo_xlib_surface_get_screen (target) : screen;

    // When the background has an alpha channel, we need to draw with an alpha
    // channel anyway, so there is no need to copy the background.  If
    // doCopyBackground is set here, we'll also need to check below that the
    // background can copied without any loss in format conversions.
    bool doCopyBackground = !drawIsOpaque && canDrawOverBackground &&
        target_content == CAIRO_CONTENT_COLOR;

    if (supportsAlternateScreen && screen != target_screen && drawIsOpaque) {
        // Prefer a visual on the target screen.
        // (If !drawIsOpaque, we'll need doCopyBackground or an alpha channel.)
        visual = DefaultVisualOfScreen(target_screen);
        screen = target_screen;

    } else if (doCopyBackground || (supportsAlternateVisual && drawIsOpaque)) {
        // Analyse the pixel formats either to check whether we can
        // doCopyBackground or to see if we can find a better visual for
        // opaque drawing.
        Visual *target_visual = NULL;
        XRenderPictFormat *target_format = NULL;
        switch (target_type) {
        case CAIRO_SURFACE_TYPE_XLIB:
            target_visual = cairo_xlib_surface_get_visual (target);
            target_format = cairo_xlib_surface_get_xrender_format (target);
            break;
        case CAIRO_SURFACE_TYPE_IMAGE: {
            gfxASurface::gfxImageFormat imageFormat =
                static_cast<gfxImageSurface*>(destination)->Format();
            target_visual = gfxXlibSurface::FindVisual(screen, imageFormat);
            Display *dpy = DisplayOfScreen(screen);
            if (target_visual) {
                target_format = XRenderFindVisualFormat(dpy, target_visual);
            } else {
                target_format =
                    gfxXlibSurface::FindRenderFormat(dpy, imageFormat);
            }                
            break;
        }
        default:
            break;
        }

        if (supportsAlternateVisual &&
            (supportsAlternateScreen || screen == target_screen)) {
            if (target_visual) {
                visual = target_visual;
                screen = target_screen;
            }
        }
        // Could try harder to match formats across screens for background
        // copying when !supportsAlternateScreen, if we cared.  Preferably
        // we'll find a visual below with an alpha channel anyway; if so, the
        // background won't need to be copied.

        if (doCopyBackground && visual != target_visual &&
            !FormatConversionIsExact(screen, visual, target_format)) {
            doCopyBackground = false;
        }
    }

    if (supportsAlternateVisual && !drawIsOpaque &&
        (screen != target_screen ||
         !(doCopyBackground || VisualHasAlpha(screen, visual)))) {
        // Try to find a visual with an alpha channel.
        Screen *visualScreen =
            supportsAlternateScreen ? target_screen : screen;
        Visual *argbVisual =
            gfxXlibSurface::FindVisual(visualScreen,
                                       gfxASurface::ImageFormatARGB32);
        if (argbVisual) {
            visual = argbVisual;
            screen = visualScreen;
        } else if (!doCopyBackground &&
                   gfxXlibSurface::DepthOfVisual(screen, visual) != 24) {
            // Will need to do alpha extraction; prefer a 24-bit visual.
            // No advantage in using the target screen.
            Visual *rgb24Visual =
                gfxXlibSurface::FindVisual(screen,
                                           gfxASurface::ImageFormatRGB24);
            if (rgb24Visual) {
                visual = rgb24Visual;
            }
        }
    }

    Drawable drawable =
        (screen == target_screen && target_type == CAIRO_SURFACE_TYPE_XLIB) ?
        cairo_xlib_surface_get_drawable (target) : RootWindowOfScreen(screen);

    nsRefPtr<gfxXlibSurface> surface =
        gfxXlibSurface::Create(screen, visual,
                               gfxIntSize(size.width, size.height),
                               drawable);

    if (drawIsOpaque ||
        surface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
        NATIVE_DRAWING_NOTE(drawIsOpaque ?
                            ", SIMPLE OPAQUE\n" : ", SIMPLE WITH ALPHA");
        *method = eSimple;
    } else if (doCopyBackground) {
        NATIVE_DRAWING_NOTE(", COPY BACKGROUND\n");
        *method = eCopyBackground;
    } else {
        NATIVE_DRAWING_NOTE(", SLOW ALPHA EXTRACTION\n");
        *method = eAlphaExtraction;
    }

    return surface.forget();
}
Esempio n. 19
0
void 
croActivateX11(CROddp *psa, cairo_surface_t* surface)
{
  static int initBack = 1;

    /* code for this function was heavily barrowed from the original X11 driver --RLB */
    XWindowAttributes       xwa;    /* Get window attributes        */
    CoordSpace              square_screen;

    Display *dpy = cairo_xlib_surface_get_display(surface);
    Window   win = cairo_xlib_surface_get_drawable(surface);

    if (initBack) {
       /* We want to set the window's background/border to the 
	* workstation's background color, but can't do it at window
	* creation time because the workstation color map is not 
	* available then. We do it once here, on the first activation.
	*/
        cairo_surface_flush(surface);
        XSetWindowBackground(dpy, win, psa->ctable[0]);
        XSetWindowBorder(dpy, win, psa->ctable[0]);
        initBack = 0;
    }

    XSync(dpy, False);
    
    /*
     *      Find out how big the window is; calculate the
     *      coordinate translation macros.
     */
    if (XGetWindowAttributes(dpy, win, &xwa) == 0) {
        ESprintf(ERR_WIN_ATTRIB, "XGetWindowAttributes(,,)");
        return;
    }

    square_screen = ComputeLargestSquare(
        (double) 0.0, (double) (xwa.height - 1),
	(double) (xwa.width - 1), (double) 0.0
    );

    psa->image_width = xwa.width; /*square_screen.urx; */
    psa->image_height = xwa.height; /*square_screen.lly;*/

    psa->dspace.llx = square_screen.llx;
    psa->dspace.urx = square_screen.urx;
    psa->dspace.lly = square_screen.ury;   /* note flip of y-axis */
    psa->dspace.ury = square_screen.lly;   /*         "           */

    psa->dspace.xspan = ((psa->dspace.urx) - (psa->dspace.llx));
    psa->dspace.yspan = ((psa->dspace.ury) - (psa->dspace.lly));

    if (psa->cro_clip.null == FALSE) {
      psa->cro_clip.llx = psa->dspace.llx;
      psa->cro_clip.lly = psa->dspace.lly;
      psa->cro_clip.urx = psa->dspace.urx;
      psa->cro_clip.ury = psa->dspace.ury;
    }

    cairo_xlib_surface_set_size(surface, xwa.width, xwa.height);

    return;
}