2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
31 #include "gdkregion-generic.h"
33 #include <pango/pangoxft.h>
36 #include <string.h> /* for memcpy() */
38 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
43 #include <X11/extensions/XShm.h>
46 #include "gdkprivate-x11.h"
47 #include "gdkdrawable-x11.h"
48 #include "gdkpixmap-x11.h"
49 #include "gdkscreen-x11.h"
50 #include "gdkdisplay-x11.h"
52 static void gdk_x11_draw_rectangle (GdkDrawable *drawable,
59 static void gdk_x11_draw_arc (GdkDrawable *drawable,
68 static void gdk_x11_draw_polygon (GdkDrawable *drawable,
73 static void gdk_x11_draw_text (GdkDrawable *drawable,
80 static void gdk_x11_draw_text_wc (GdkDrawable *drawable,
87 static void gdk_x11_draw_drawable (GdkDrawable *drawable,
96 static void gdk_x11_draw_points (GdkDrawable *drawable,
100 static void gdk_x11_draw_segments (GdkDrawable *drawable,
104 static void gdk_x11_draw_lines (GdkDrawable *drawable,
109 static void gdk_x11_draw_glyphs (GdkDrawable *drawable,
114 PangoGlyphString *glyphs);
115 static void gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable,
121 PangoGlyphString *glyphs);
123 static void gdk_x11_draw_image (GdkDrawable *drawable,
132 static void gdk_x11_draw_pixbuf (GdkDrawable *drawable,
145 static void gdk_x11_draw_trapezoids (GdkDrawable *drawable,
147 GdkTrapezoid *trapezoids,
150 static void gdk_x11_set_cairo_target (GdkDrawable *drawable,
153 static void gdk_x11_set_colormap (GdkDrawable *drawable,
154 GdkColormap *colormap);
156 static GdkColormap* gdk_x11_get_colormap (GdkDrawable *drawable);
157 static gint gdk_x11_get_depth (GdkDrawable *drawable);
158 static GdkScreen * gdk_x11_get_screen (GdkDrawable *drawable);
159 static GdkVisual* gdk_x11_get_visual (GdkDrawable *drawable);
161 static void gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass);
163 static void gdk_drawable_impl_x11_finalize (GObject *object);
165 static gpointer parent_class = NULL;
168 _gdk_drawable_impl_x11_get_type (void)
170 static GType object_type = 0;
174 static const GTypeInfo object_info =
176 sizeof (GdkDrawableImplX11Class),
177 (GBaseInitFunc) NULL,
178 (GBaseFinalizeFunc) NULL,
179 (GClassInitFunc) gdk_drawable_impl_x11_class_init,
180 NULL, /* class_finalize */
181 NULL, /* class_data */
182 sizeof (GdkDrawableImplX11),
184 (GInstanceInitFunc) NULL,
187 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
188 "GdkDrawableImplX11",
196 gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
198 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
199 GObjectClass *object_class = G_OBJECT_CLASS (klass);
201 parent_class = g_type_class_peek_parent (klass);
203 object_class->finalize = gdk_drawable_impl_x11_finalize;
205 drawable_class->create_gc = _gdk_x11_gc_new;
206 drawable_class->draw_rectangle = gdk_x11_draw_rectangle;
207 drawable_class->draw_arc = gdk_x11_draw_arc;
208 drawable_class->draw_polygon = gdk_x11_draw_polygon;
209 drawable_class->draw_text = gdk_x11_draw_text;
210 drawable_class->draw_text_wc = gdk_x11_draw_text_wc;
211 drawable_class->draw_drawable = gdk_x11_draw_drawable;
212 drawable_class->draw_points = gdk_x11_draw_points;
213 drawable_class->draw_segments = gdk_x11_draw_segments;
214 drawable_class->draw_lines = gdk_x11_draw_lines;
215 drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
216 drawable_class->draw_glyphs_transformed = gdk_x11_draw_glyphs_transformed;
217 drawable_class->draw_image = gdk_x11_draw_image;
218 drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
219 drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids;
221 drawable_class->set_cairo_target = gdk_x11_set_cairo_target;
223 drawable_class->set_colormap = gdk_x11_set_colormap;
224 drawable_class->get_colormap = gdk_x11_get_colormap;
226 drawable_class->get_depth = gdk_x11_get_depth;
227 drawable_class->get_screen = gdk_x11_get_screen;
228 drawable_class->get_visual = gdk_x11_get_visual;
230 drawable_class->_copy_to_image = _gdk_x11_copy_to_image;
234 gdk_drawable_impl_x11_finalize (GObject *object)
236 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
238 G_OBJECT_CLASS (parent_class)->finalize (object);
242 try_pixmap (Display *xdisplay,
246 Pixmap pixmap = XCreatePixmap (xdisplay,
247 RootWindow (xdisplay, screen),
249 XFreePixmap (xdisplay, pixmap);
253 _gdk_x11_have_render (GdkDisplay *display)
255 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
256 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
258 if (x11display->have_render == GDK_UNKNOWN)
260 int event_base, error_base;
261 x11display->have_render =
262 XRenderQueryExtension (xdisplay, &event_base, &error_base)
265 if (x11display->have_render == GDK_YES)
268 * Sun advertises RENDER, but fails to support 32-bit pixmaps.
269 * That is just no good. Therefore, we check all screens
270 * for proper support.
274 for (screen = 0; screen < ScreenCount (xdisplay); screen++)
277 int *depths = XListDepths (xdisplay, screen, &count);
278 gboolean has_8 = FALSE, has_32 = FALSE;
284 for (i = 0; i < count; i++)
288 else if (depths[i] == 32)
294 /* At this point, we might have a false positive;
295 * buggy versions of Xinerama only report depths for
296 * which there is an associated visual; so we actually
297 * go ahead and try create pixmaps.
299 if (!(has_8 && has_32))
301 gdk_error_trap_push ();
303 try_pixmap (xdisplay, screen, 8);
305 try_pixmap (xdisplay, screen, 32);
306 XSync (xdisplay, False);
307 if (gdk_error_trap_pop () == 0)
314 if (!(has_8 && has_32))
316 g_warning ("The X server advertises that RENDER support is present,\n"
317 "but fails to supply the necessary pixmap support. In\n"
318 "other words, it is buggy.");
319 x11display->have_render = GDK_NO;
326 return x11display->have_render == GDK_YES;
330 _gdk_x11_have_render_with_trapezoids (GdkDisplay *display)
332 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
333 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
335 if (x11display->have_render_with_trapezoids == GDK_UNKNOWN)
337 if (!_gdk_x11_have_render (display))
338 x11display->have_render_with_trapezoids = GDK_NO;
342 * Require protocol >= 0.4 for CompositeTrapezoids support.
344 int major_version, minor_version;
346 #define XRENDER_TETRAPEZOIDS_MAJOR 0
347 #define XRENDER_TETRAPEZOIDS_MINOR 4
349 if (XRenderQueryVersion (xdisplay, &major_version,
351 if ((major_version < XRENDER_TETRAPEZOIDS_MAJOR) ||
352 ((major_version == XRENDER_TETRAPEZOIDS_MAJOR) &&
353 (minor_version < XRENDER_TETRAPEZOIDS_MINOR)))
354 x11display->have_render_with_trapezoids = GDK_NO;
358 return x11display->have_render_with_trapezoids == GDK_YES;
362 gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable)
364 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
366 if (impl->xft_draw == NULL)
368 GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
374 visual = gdk_colormap_get_visual (colormap);
376 impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
377 GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap));
379 else if (gdk_drawable_get_depth (drawable) == 1)
381 impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid);
385 g_warning ("Using Xft rendering requires the drawable argument to\n"
386 "have a specified colormap. All windows have a colormap,\n"
387 "however, pixmaps only have colormap by default if they\n"
388 "were created with a non-NULL window argument. Otherwise\n"
389 "a colormap must be set on them with gdk_drawable_set_colormap");
394 return impl->xft_draw;
398 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
400 XftDraw *draw = gdk_x11_drawable_get_xft_draw (drawable);
402 return draw ? XftDrawPicture (draw) : None;
406 gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable,
409 GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL;
410 XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable);
412 if (gc && gc_private->clip_region)
414 GdkRegionBox *boxes = gc_private->clip_region->rects;
415 gint n_boxes = gc_private->clip_region->numRects;
416 #if 0 /* Until XftDrawSetClipRectangles is there */
417 XRectangle *rects = g_new (XRectangle, n_boxes);
420 for (i=0; i < n_boxes; i++)
422 rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
423 rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
424 rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
425 rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
427 XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes);
431 Region xregion = XCreateRegion ();
434 for (i=0; i < n_boxes; i++)
438 rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
439 rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
440 rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
441 rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
443 XUnionRectWithRegion (&rect, xregion, xregion);
446 XftDrawSetClip (xft_draw, xregion);
447 XDestroyRegion (xregion);
452 XftDrawSetClip (xft_draw, NULL);
456 /*****************************************************
457 * X11 specific implementations of generic functions *
458 *****************************************************/
461 gdk_x11_get_colormap (GdkDrawable *drawable)
463 GdkDrawableImplX11 *impl;
465 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
467 return impl->colormap;
471 gdk_x11_set_colormap (GdkDrawable *drawable,
472 GdkColormap *colormap)
474 GdkDrawableImplX11 *impl;
476 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
478 if (impl->colormap == colormap)
482 g_object_unref (impl->colormap);
483 impl->colormap = colormap;
485 g_object_ref (impl->colormap);
492 gdk_x11_draw_rectangle (GdkDrawable *drawable,
500 GdkDrawableImplX11 *impl;
502 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
505 XFillRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
506 GDK_GC_GET_XGC (gc), x, y, width, height);
508 XDrawRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
509 GDK_GC_GET_XGC (gc), x, y, width, height);
513 gdk_x11_draw_arc (GdkDrawable *drawable,
523 GdkDrawableImplX11 *impl;
525 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
529 XFillArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
530 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
532 XDrawArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
533 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
537 gdk_x11_draw_polygon (GdkDrawable *drawable,
545 GdkDrawableImplX11 *impl;
547 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
551 (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
553 tmp_npoints = npoints + 1;
554 tmp_points = g_new (XPoint, tmp_npoints);
555 tmp_points[npoints].x = points[0].x;
556 tmp_points[npoints].y = points[0].y;
560 tmp_npoints = npoints;
561 tmp_points = g_new (XPoint, tmp_npoints);
564 for (i=0; i<npoints; i++)
566 tmp_points[i].x = points[i].x;
567 tmp_points[i].y = points[i].y;
571 XFillPolygon (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
572 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
574 XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
575 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
582 * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
584 * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
587 gdk_x11_draw_text (GdkDrawable *drawable,
595 GdkDrawableImplX11 *impl;
598 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
599 xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
601 if (font->type == GDK_FONT_FONT)
603 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
604 XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
605 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
607 XDrawString (xdisplay, impl->xid,
608 GDK_GC_GET_XGC (gc), x, y, text, text_length);
612 XDrawString16 (xdisplay, impl->xid,
613 GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
616 else if (font->type == GDK_FONT_FONTSET)
618 XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
619 XmbDrawString (xdisplay, impl->xid,
620 fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
623 g_error("undefined font type\n");
627 gdk_x11_draw_text_wc (GdkDrawable *drawable,
632 const GdkWChar *text,
635 GdkDrawableImplX11 *impl;
638 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
639 xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
641 if (font->type == GDK_FONT_FONT)
643 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
646 XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
647 text_8bit = g_new (gchar, text_length);
648 for (i=0; i<text_length; i++) text_8bit[i] = text[i];
649 XDrawString (xdisplay, impl->xid,
650 GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
653 else if (font->type == GDK_FONT_FONTSET)
655 if (sizeof(GdkWChar) == sizeof(wchar_t))
657 XwcDrawString (xdisplay, impl->xid,
658 (XFontSet) GDK_FONT_XFONT (font),
659 GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
665 text_wchar = g_new (wchar_t, text_length);
666 for (i=0; i<text_length; i++) text_wchar[i] = text[i];
667 XwcDrawString (xdisplay, impl->xid,
668 (XFontSet) GDK_FONT_XFONT (font),
669 GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
674 g_error("undefined font type\n");
678 gdk_x11_draw_drawable (GdkDrawable *drawable,
688 int src_depth = gdk_drawable_get_depth (src);
689 int dest_depth = gdk_drawable_get_depth (drawable);
690 GdkDrawableImplX11 *impl;
691 GdkDrawableImplX11 *src_impl;
693 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
695 if (GDK_IS_DRAWABLE_IMPL_X11 (src))
696 src_impl = GDK_DRAWABLE_IMPL_X11 (src);
702 XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
703 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
710 else if (dest_depth != 0 && src_depth == dest_depth)
712 XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
713 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
721 g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
722 src_depth, dest_depth);
726 gdk_x11_draw_points (GdkDrawable *drawable,
731 GdkDrawableImplX11 *impl;
733 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
736 /* We special-case npoints == 1, because X will merge multiple
737 * consecutive XDrawPoint requests into a PolyPoint request
741 XDrawPoint (GDK_SCREEN_XDISPLAY (impl->screen),
744 points[0].x, points[0].y);
749 XPoint *tmp_points = g_new (XPoint, npoints);
751 for (i=0; i<npoints; i++)
753 tmp_points[i].x = points[i].x;
754 tmp_points[i].y = points[i].y;
757 XDrawPoints (GDK_SCREEN_XDISPLAY (impl->screen),
769 gdk_x11_draw_segments (GdkDrawable *drawable,
774 GdkDrawableImplX11 *impl;
776 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
779 /* We special-case nsegs == 1, because X will merge multiple
780 * consecutive XDrawLine requests into a PolySegment request
784 XDrawLine (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
785 GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
786 segs[0].x2, segs[0].y2);
791 XSegment *tmp_segs = g_new (XSegment, nsegs);
793 for (i=0; i<nsegs; i++)
795 tmp_segs[i].x1 = segs[i].x1;
796 tmp_segs[i].x2 = segs[i].x2;
797 tmp_segs[i].y1 = segs[i].y1;
798 tmp_segs[i].y2 = segs[i].y2;
801 XDrawSegments (GDK_SCREEN_XDISPLAY (impl->screen),
811 gdk_x11_draw_lines (GdkDrawable *drawable,
817 XPoint *tmp_points = g_new (XPoint, npoints);
818 GdkDrawableImplX11 *impl;
820 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
823 for (i=0; i<npoints; i++)
825 tmp_points[i].x = points[i].x;
826 tmp_points[i].y = points[i].y;
829 XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen),
839 gdk_x11_draw_glyphs (GdkDrawable *drawable,
844 PangoGlyphString *glyphs)
846 gdk_x11_draw_glyphs_transformed (drawable, gc, NULL,
854 gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable,
860 PangoGlyphString *glyphs)
862 GdkDrawableImplX11 *impl;
863 PangoRenderer *renderer;
865 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
867 g_return_if_fail (PANGO_XFT_IS_FONT (font));
869 renderer = _gdk_x11_renderer_get (drawable, gc);
871 pango_renderer_set_matrix (renderer, matrix);
872 pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
874 pango_renderer_set_matrix (renderer, NULL);
878 gdk_x11_draw_image (GdkDrawable *drawable,
888 GdkDrawableImplX11 *impl;
890 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
893 if (image->type == GDK_IMAGE_SHARED)
894 XShmPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
895 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
896 xsrc, ysrc, xdest, ydest, width, height, False);
899 XPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
900 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
901 xsrc, ysrc, xdest, ydest, width, height);
905 gdk_x11_get_depth (GdkDrawable *drawable)
907 /* This is a bit bogus but I'm not sure the other way is better */
909 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
913 get_impl_drawable (GdkDrawable *drawable)
915 if (GDK_IS_WINDOW (drawable))
916 return ((GdkWindowObject *)drawable)->impl;
917 else if (GDK_IS_PIXMAP (drawable))
918 return ((GdkPixmapObject *)drawable)->impl;
921 g_warning (G_STRLOC " drawable is not a pixmap or window");
927 gdk_x11_get_screen (GdkDrawable *drawable)
929 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
930 return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
932 return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
936 gdk_x11_get_visual (GdkDrawable *drawable)
938 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
942 * gdk_x11_drawable_get_xdisplay:
943 * @drawable: a #GdkDrawable.
945 * Returns the display of a #GdkDrawable.
947 * Return value: an Xlib <type>Display*</type>.
950 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
952 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
953 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
955 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
959 * gdk_x11_drawable_get_xid:
960 * @drawable: a #GdkDrawable.
962 * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
964 * Return value: the ID of @drawable's X resource.
967 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
971 if (GDK_IS_WINDOW (drawable))
972 impl = ((GdkPixmapObject *)drawable)->impl;
973 else if (GDK_IS_PIXMAP (drawable))
974 impl = ((GdkPixmapObject *)drawable)->impl;
977 g_warning (G_STRLOC " drawable is not a pixmap or window");
981 return ((GdkDrawableImplX11 *)impl)->xid;
984 /* Code for accelerated alpha compositing using the RENDER extension.
985 * It's a bit long because there are lots of possibilities for
986 * what's the fastest depending on the available picture formats,
987 * whether we can used shared pixmaps, etc.
990 static GdkX11FormatType
991 select_format (GdkDisplay *display,
992 XRenderPictFormat **format,
993 XRenderPictFormat **mask)
995 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
996 XRenderPictFormat pf;
998 if (!_gdk_x11_have_render (display))
999 return GDK_X11_FORMAT_NONE;
1001 /* Look for a 32-bit xRGB and Axxx formats that exactly match the
1002 * in memory data format. We can use them as pixmap and mask
1003 * to deal with non-premultiplied data.
1006 pf.type = PictTypeDirect;
1008 pf.direct.redMask = 0xff;
1009 pf.direct.greenMask = 0xff;
1010 pf.direct.blueMask = 0xff;
1012 pf.direct.alphaMask = 0;
1013 if (ImageByteOrder (xdisplay) == LSBFirst)
1017 pf.direct.green = 8;
1018 pf.direct.blue = 16;
1024 pf.direct.green = 16;
1028 *format = XRenderFindFormat (xdisplay,
1029 (PictFormatType | PictFormatDepth |
1030 PictFormatRedMask | PictFormatRed |
1031 PictFormatGreenMask | PictFormatGreen |
1032 PictFormatBlueMask | PictFormatBlue |
1033 PictFormatAlphaMask),
1037 pf.direct.alphaMask = 0xff;
1038 if (ImageByteOrder (xdisplay) == LSBFirst)
1041 pf.direct.alpha = 24;
1045 pf.direct.alpha = 0;
1048 *mask = XRenderFindFormat (xdisplay,
1049 (PictFormatType | PictFormatDepth |
1050 PictFormatAlphaMask | PictFormatAlpha),
1054 if (*format && *mask)
1055 return GDK_X11_FORMAT_EXACT_MASK;
1057 /* OK, that failed, now look for xRGB and Axxx formats in
1058 * RENDER's preferred order
1060 pf.direct.alphaMask = 0;
1063 pf.direct.green = 8;
1066 *format = XRenderFindFormat (xdisplay,
1067 (PictFormatType | PictFormatDepth |
1068 PictFormatRedMask | PictFormatRed |
1069 PictFormatGreenMask | PictFormatGreen |
1070 PictFormatBlueMask | PictFormatBlue |
1071 PictFormatAlphaMask),
1075 pf.direct.alphaMask = 0xff;
1076 pf.direct.alpha = 24;
1078 *mask = XRenderFindFormat (xdisplay,
1079 (PictFormatType | PictFormatDepth |
1080 PictFormatAlphaMask | PictFormatAlpha),
1084 if (*format && *mask)
1085 return GDK_X11_FORMAT_ARGB_MASK;
1087 /* Finally, if neither of the above worked, fall back to
1088 * looking for combined ARGB -- we'll premultiply ourselves.
1091 pf.type = PictTypeDirect;
1094 pf.direct.green = 8;
1096 pf.direct.alphaMask = 0xff;
1097 pf.direct.alpha = 24;
1099 *format = XRenderFindFormat (xdisplay,
1100 (PictFormatType | PictFormatDepth |
1101 PictFormatRedMask | PictFormatRed |
1102 PictFormatGreenMask | PictFormatGreen |
1103 PictFormatBlueMask | PictFormatBlue |
1104 PictFormatAlphaMask | PictFormatAlpha),
1110 return GDK_X11_FORMAT_ARGB;
1112 return GDK_X11_FORMAT_NONE;
1117 list_formats (XRenderPictFormat *pf)
1123 XRenderPictFormat *pf = XRenderFindFormat (impl->xdisplay, 0, NULL, i);
1126 g_print ("%2d R-%#06x/%#06x G-%#06x/%#06x B-%#06x/%#06x A-%#06x/%#06x\n",
1131 pf->direct.greenMask,
1133 pf->direct.blueMask,
1135 pf->direct.alphaMask);
1144 _gdk_x11_convert_to_format (guchar *src_buf,
1147 gint dest_rowstride,
1148 GdkX11FormatType dest_format,
1149 GdkByteOrder dest_byteorder,
1155 for (i=0; i < height; i++)
1157 switch (dest_format)
1159 case GDK_X11_FORMAT_EXACT_MASK:
1161 memcpy (dest_buf + i * dest_rowstride,
1162 src_buf + i * src_rowstride,
1166 case GDK_X11_FORMAT_ARGB_MASK:
1168 guchar *row = src_buf + i * src_rowstride;
1169 if (((gsize)row & 3) != 0)
1172 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1173 guchar *end = p + 4 * width;
1177 *q = (p[3] << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
1184 guint32 *p = (guint32 *)row;
1185 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1186 guint32 *end = p + width;
1188 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1189 if (dest_byteorder == GDK_LSB_FIRST)
1195 *q = ( (*p & 0xff00ff00) |
1196 ((*p & 0x000000ff) << 16) |
1197 ((*p & 0x00ff0000) >> 16));
1208 *q = (((*p & 0xff000000) >> 24) |
1209 ((*p & 0x00ffffff) << 8));
1214 #else /* G_BYTE_ORDER == G_BIG_ENDIAN */
1215 if (dest_byteorder == GDK_LSB_FIRST)
1221 *q = ( (*p & 0x00ff00ff) |
1222 ((*p & 0x0000ff00) << 16) |
1223 ((*p & 0xff000000) >> 16));
1234 *q = (((*p & 0xffffff00) >> 8) |
1235 ((*p & 0x000000ff) << 24));
1240 #endif /* G_BYTE_ORDER*/
1244 case GDK_X11_FORMAT_ARGB:
1246 guchar *p = (src_buf + i * src_rowstride);
1247 guchar *q = (dest_buf + i * dest_rowstride);
1248 guchar *end = p + 4 * width;
1251 #define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
1253 if (dest_byteorder == GDK_LSB_FIRST)
1257 MULT(q[0], p[2], p[3], t1);
1258 MULT(q[1], p[1], p[3], t2);
1259 MULT(q[2], p[0], p[3], t3);
1270 MULT(q[1], p[0], p[3], t1);
1271 MULT(q[2], p[1], p[3], t2);
1272 MULT(q[3], p[2], p[3], t3);
1280 case GDK_X11_FORMAT_NONE:
1281 g_assert_not_reached ();
1288 draw_with_images (GdkDrawable *drawable,
1290 GdkX11FormatType format_type,
1291 XRenderPictFormat *format,
1292 XRenderPictFormat *mask_format,
1300 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1301 Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
1307 Picture mask = None;
1310 pix = gdk_pixmap_new (gdk_screen_get_root_window (screen), width, height, 32);
1312 pict = XRenderCreatePicture (xdisplay,
1313 GDK_PIXMAP_XID (pix),
1316 mask = XRenderCreatePicture (xdisplay,
1317 GDK_PIXMAP_XID (pix),
1318 mask_format, 0, NULL);
1320 dest_pict = gdk_x11_drawable_get_picture (drawable);
1322 pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE);
1324 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1326 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1327 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1331 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1333 image = _gdk_image_get_scratch (screen, width1, height1, 32, &xs0, &ys0);
1335 _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1336 (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1337 format_type, image->byte_order,
1340 gdk_draw_image (pix, pix_gc,
1341 image, xs0, ys0, x0, y0, width1, height1);
1345 XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
1346 0, 0, 0, 0, dest_x, dest_y, width, height);
1348 XRenderFreePicture (xdisplay, pict);
1350 XRenderFreePicture (xdisplay, mask);
1352 g_object_unref (pix);
1355 typedef struct _ShmPixmapInfo ShmPixmapInfo;
1357 struct _ShmPixmapInfo
1365 /* Returns FALSE if we can't get a shm pixmap */
1367 get_shm_pixmap_for_image (Display *xdisplay,
1369 XRenderPictFormat *format,
1370 XRenderPictFormat *mask_format,
1375 ShmPixmapInfo *info;
1377 if (image->type != GDK_IMAGE_SHARED)
1380 info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
1383 *pix = _gdk_x11_image_get_shm_pixmap (image);
1388 info = g_new (ShmPixmapInfo, 1);
1391 info->pict = XRenderCreatePicture (xdisplay, info->pix,
1394 info->mask = XRenderCreatePicture (xdisplay, info->pix,
1395 mask_format, 0, NULL);
1399 g_object_set_data (G_OBJECT (image), "gdk-x11-shm-pixmap", info);
1410 /* Returns FALSE if drawing with ShmPixmaps is not possible */
1412 draw_with_pixmaps (GdkDrawable *drawable,
1414 GdkX11FormatType format_type,
1415 XRenderPictFormat *format,
1416 XRenderPictFormat *mask_format,
1424 Display *xdisplay = GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
1429 Picture mask = None;
1432 dest_pict = gdk_x11_drawable_get_picture (drawable);
1434 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1436 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1437 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1441 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1443 image = _gdk_image_get_scratch (GDK_DRAWABLE_IMPL_X11 (drawable)->screen,
1444 width1, height1, 32, &xs0, &ys0);
1445 if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
1448 _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1449 (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1450 format_type, image->byte_order,
1453 XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
1454 xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
1464 gdk_x11_draw_pixbuf (GdkDrawable *drawable,
1473 GdkRgbDither dither,
1477 GdkX11FormatType format_type;
1478 XRenderPictFormat *format, *mask_format;
1481 gboolean use_pixmaps = TRUE;
1482 #endif /* USE_SHM */
1484 format_type = select_format (gdk_drawable_get_display (drawable),
1485 &format, &mask_format);
1487 if (format_type == GDK_X11_FORMAT_NONE ||
1488 !gdk_pixbuf_get_has_alpha (pixbuf) ||
1489 gdk_drawable_get_depth (drawable) == 1 ||
1490 (dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
1491 gdk_x11_drawable_get_picture (drawable) == None)
1493 GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1494 GDK_DRAWABLE_CLASS (parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
1495 src_x, src_y, dest_x, dest_y,
1497 dither, x_dither, y_dither);
1501 gdk_x11_drawable_update_xft_clip (drawable, gc);
1503 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1508 if (!draw_with_pixmaps (drawable, gc,
1509 format_type, format, mask_format,
1510 gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1512 dest_x, dest_y, width, height))
1513 use_pixmaps = FALSE;
1517 #endif /* USE_SHM */
1518 draw_with_images (drawable, gc,
1519 format_type, format, mask_format,
1520 gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1522 dest_x, dest_y, width, height);
1526 gdk_x11_draw_trapezoids (GdkDrawable *drawable,
1528 GdkTrapezoid *trapezoids,
1531 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1532 GdkDisplay *display = gdk_screen_get_display (screen);
1533 XTrapezoid *xtrapezoids;
1536 if (!_gdk_x11_have_render_with_trapezoids (display))
1538 GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1539 GDK_DRAWABLE_CLASS (parent_class)->draw_trapezoids (wrapper, gc,
1540 trapezoids, n_trapezoids);
1544 xtrapezoids = g_new (XTrapezoid, n_trapezoids);
1546 for (i = 0; i < n_trapezoids; i++)
1548 xtrapezoids[i].top = XDoubleToFixed (trapezoids[i].y1);
1549 xtrapezoids[i].bottom = XDoubleToFixed (trapezoids[i].y2);
1550 xtrapezoids[i].left.p1.x = XDoubleToFixed (trapezoids[i].x11);
1551 xtrapezoids[i].left.p1.y = XDoubleToFixed (trapezoids[i].y1);
1552 xtrapezoids[i].left.p2.x = XDoubleToFixed (trapezoids[i].x12);
1553 xtrapezoids[i].left.p2.y = XDoubleToFixed (trapezoids[i].y2);
1554 xtrapezoids[i].right.p1.x = XDoubleToFixed (trapezoids[i].x21);
1555 xtrapezoids[i].right.p1.y = XDoubleToFixed (trapezoids[i].y1);
1556 xtrapezoids[i].right.p2.x = XDoubleToFixed (trapezoids[i].x22);
1557 xtrapezoids[i].right.p2.y = XDoubleToFixed (trapezoids[i].y2);
1560 _gdk_x11_drawable_draw_xtrapezoids (drawable, gc,
1561 xtrapezoids, n_trapezoids);
1563 g_free (xtrapezoids);
1566 static cairo_surface_t *
1567 gdk_x11_drawable_get_cairo_surface (GdkDrawable *drawable)
1569 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
1570 GdkColormap *colormap;
1573 if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
1574 GDK_WINDOW_DESTROYED (impl->wrapper))
1577 colormap = gdk_drawable_get_colormap (drawable);
1580 g_warning ("Using Cairo rendering requires the drawable argument to\n"
1581 "have a specified colormap. All windows have a colormap,\n"
1582 "however, pixmaps only have colormap by default if they\n"
1583 "were created with a non-NULL window argument. Otherwise\n"
1584 "a colormap must be set on them with gdk_drawable_set_colormap");
1588 visual = gdk_colormap_get_visual (colormap);
1590 if (!impl->cairo_surface)
1592 impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
1594 GDK_VISUAL_XVISUAL (visual),
1596 GDK_COLORMAP_XCOLORMAP (colormap));
1599 return impl->cairo_surface;
1603 gdk_x11_set_cairo_target (GdkDrawable *drawable,
1606 cairo_surface_t *surface = gdk_x11_drawable_get_cairo_surface (drawable);
1608 cairo_set_target_surface (cr, surface);
1612 * gdk_draw_rectangle_alpha_libgtk_only:
1613 * @drawable: The #GdkDrawable to draw on
1614 * @x: the x coordinate of the left edge of the rectangle.
1615 * @y: the y coordinate of the top edge of the rectangle.
1616 * @width: the width of the rectangle.
1617 * @height: the height of the rectangle.
1619 * @alpha: The alpha value.
1621 * Tries to draw a filled alpha blended rectangle using the window
1622 * system's native routines. This is not public API and must not be
1623 * used by applications.
1625 * Return value: TRUE if the rectangle could be drawn, FALSE
1629 gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable,
1638 XRenderColor render_color;
1640 int x_offset, y_offset;
1641 GdkDrawable *real_drawable, *impl;
1643 g_return_val_if_fail (color != NULL, FALSE);
1645 if (!GDK_IS_WINDOW (drawable))
1648 if (!_gdk_x11_have_render (gdk_drawable_get_display (drawable)))
1651 gdk_window_get_internal_paint_info (GDK_WINDOW (drawable),
1653 &x_offset, &y_offset);
1655 impl = ((GdkWindowObject *)real_drawable)->impl;
1657 pict = gdk_x11_drawable_get_picture (impl);
1662 xdisplay = GDK_DISPLAY_XDISPLAY (gdk_drawable_get_display (drawable));
1664 render_color.alpha = alpha;
1665 render_color.red = (guint32)color->red * render_color.alpha / 0xffff;
1666 render_color.green = (guint32)color->green * render_color.alpha / 0xffff;
1667 render_color.blue = (guint32)color->blue * render_color.alpha / 0xffff;
1669 XRenderFillRectangle (xdisplay,
1670 PictOpOver, pict, &render_color,
1671 x - x_offset, y - y_offset,
1677 _gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable,
1679 XTrapezoid *xtrapezoids,
1682 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1683 GdkDisplay *display = gdk_screen_get_display (screen);
1684 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
1688 if (!_gdk_x11_have_render_with_trapezoids (display))
1690 /* This is the case of drawing the borders of the unknown glyph box
1691 * without render on the display, we need to feed it back to
1692 * fallback code. Not efficient, but doesn't matter.
1694 GdkTrapezoid *trapezoids = g_new (GdkTrapezoid, n_trapezoids);
1697 for (i = 0; i < n_trapezoids; i++)
1699 trapezoids[i].y1 = XFixedToDouble (xtrapezoids[i].top);
1700 trapezoids[i].y2 = XFixedToDouble (xtrapezoids[i].bottom);
1701 trapezoids[i].x11 = XFixedToDouble (xtrapezoids[i].left.p1.x);
1702 trapezoids[i].x12 = XFixedToDouble (xtrapezoids[i].left.p2.x);
1703 trapezoids[i].x21 = XFixedToDouble (xtrapezoids[i].right.p1.x);
1704 trapezoids[i].x22 = XFixedToDouble (xtrapezoids[i].right.p2.x);
1707 gdk_x11_draw_trapezoids (drawable, gc, trapezoids, n_trapezoids);
1708 g_free (trapezoids);
1713 gdk_x11_drawable_update_xft_clip (drawable, gc);
1714 draw = gdk_x11_drawable_get_xft_draw (drawable);
1716 if (!x11display->mask_format)
1717 x11display->mask_format = XRenderFindStandardFormat (x11display->xdisplay,
1720 XRenderCompositeTrapezoids (x11display->xdisplay, PictOpOver,
1721 _gdk_x11_gc_get_fg_picture (gc),
1722 XftDrawPicture (draw),
1723 x11display->mask_format,
1724 - gc->ts_x_origin, - gc->ts_y_origin,
1725 xtrapezoids, n_trapezoids);
1729 _gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable,
1732 XftGlyphSpec *glyphs,
1735 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1736 GdkDisplay *display = gdk_screen_get_display (screen);
1737 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
1740 gdk_x11_drawable_update_xft_clip (drawable, gc);
1741 draw = gdk_x11_drawable_get_xft_draw (drawable);
1743 if (_gdk_x11_have_render (display))
1745 XftGlyphSpecRender (x11display->xdisplay, PictOpOver,
1746 _gdk_x11_gc_get_fg_picture (gc),
1748 XftDrawPicture (draw),
1749 - gc->ts_x_origin, - gc->ts_y_origin,
1756 _gdk_gc_x11_get_fg_xft_color (gc, &color);
1757 XftDrawGlyphSpec (draw, &color, xft_font, glyphs, n_glyphs);