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>
35 #include <cairo-xlib.h>
38 #include <string.h> /* for memcpy() */
40 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
45 #include <X11/extensions/XShm.h>
48 #include "gdkprivate-x11.h"
49 #include "gdkdrawable-x11.h"
50 #include "gdkpixmap-x11.h"
51 #include "gdkscreen-x11.h"
52 #include "gdkdisplay-x11.h"
54 static void gdk_x11_draw_rectangle (GdkDrawable *drawable,
61 static void gdk_x11_draw_arc (GdkDrawable *drawable,
70 static void gdk_x11_draw_polygon (GdkDrawable *drawable,
75 static void gdk_x11_draw_text (GdkDrawable *drawable,
82 static void gdk_x11_draw_text_wc (GdkDrawable *drawable,
89 static void gdk_x11_draw_drawable (GdkDrawable *drawable,
98 static void gdk_x11_draw_points (GdkDrawable *drawable,
102 static void gdk_x11_draw_segments (GdkDrawable *drawable,
106 static void gdk_x11_draw_lines (GdkDrawable *drawable,
111 static void gdk_x11_draw_glyphs (GdkDrawable *drawable,
116 PangoGlyphString *glyphs);
117 static void gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable,
123 PangoGlyphString *glyphs);
125 static void gdk_x11_draw_image (GdkDrawable *drawable,
134 static void gdk_x11_draw_pixbuf (GdkDrawable *drawable,
147 static void gdk_x11_draw_trapezoids (GdkDrawable *drawable,
149 GdkTrapezoid *trapezoids,
152 static void gdk_x11_set_cairo_target (GdkDrawable *drawable,
155 static void gdk_x11_set_colormap (GdkDrawable *drawable,
156 GdkColormap *colormap);
158 static GdkColormap* gdk_x11_get_colormap (GdkDrawable *drawable);
159 static gint gdk_x11_get_depth (GdkDrawable *drawable);
160 static GdkScreen * gdk_x11_get_screen (GdkDrawable *drawable);
161 static GdkVisual* gdk_x11_get_visual (GdkDrawable *drawable);
163 static void gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass);
165 static void gdk_drawable_impl_x11_finalize (GObject *object);
167 static gpointer parent_class = NULL;
170 _gdk_drawable_impl_x11_get_type (void)
172 static GType object_type = 0;
176 static const GTypeInfo object_info =
178 sizeof (GdkDrawableImplX11Class),
179 (GBaseInitFunc) NULL,
180 (GBaseFinalizeFunc) NULL,
181 (GClassInitFunc) gdk_drawable_impl_x11_class_init,
182 NULL, /* class_finalize */
183 NULL, /* class_data */
184 sizeof (GdkDrawableImplX11),
186 (GInstanceInitFunc) NULL,
189 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
190 "GdkDrawableImplX11",
198 gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
200 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
201 GObjectClass *object_class = G_OBJECT_CLASS (klass);
203 parent_class = g_type_class_peek_parent (klass);
205 object_class->finalize = gdk_drawable_impl_x11_finalize;
207 drawable_class->create_gc = _gdk_x11_gc_new;
208 drawable_class->draw_rectangle = gdk_x11_draw_rectangle;
209 drawable_class->draw_arc = gdk_x11_draw_arc;
210 drawable_class->draw_polygon = gdk_x11_draw_polygon;
211 drawable_class->draw_text = gdk_x11_draw_text;
212 drawable_class->draw_text_wc = gdk_x11_draw_text_wc;
213 drawable_class->draw_drawable = gdk_x11_draw_drawable;
214 drawable_class->draw_points = gdk_x11_draw_points;
215 drawable_class->draw_segments = gdk_x11_draw_segments;
216 drawable_class->draw_lines = gdk_x11_draw_lines;
217 drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
218 drawable_class->draw_glyphs_transformed = gdk_x11_draw_glyphs_transformed;
219 drawable_class->draw_image = gdk_x11_draw_image;
220 drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
221 drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids;
223 drawable_class->set_cairo_target = gdk_x11_set_cairo_target;
225 drawable_class->set_colormap = gdk_x11_set_colormap;
226 drawable_class->get_colormap = gdk_x11_get_colormap;
228 drawable_class->get_depth = gdk_x11_get_depth;
229 drawable_class->get_screen = gdk_x11_get_screen;
230 drawable_class->get_visual = gdk_x11_get_visual;
232 drawable_class->_copy_to_image = _gdk_x11_copy_to_image;
236 gdk_drawable_impl_x11_finalize (GObject *object)
238 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
240 G_OBJECT_CLASS (parent_class)->finalize (object);
244 try_pixmap (Display *xdisplay,
248 Pixmap pixmap = XCreatePixmap (xdisplay,
249 RootWindow (xdisplay, screen),
251 XFreePixmap (xdisplay, pixmap);
255 _gdk_x11_have_render (GdkDisplay *display)
257 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
258 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
260 if (x11display->have_render == GDK_UNKNOWN)
262 int event_base, error_base;
263 x11display->have_render =
264 XRenderQueryExtension (xdisplay, &event_base, &error_base)
267 if (x11display->have_render == GDK_YES)
270 * Sun advertises RENDER, but fails to support 32-bit pixmaps.
271 * That is just no good. Therefore, we check all screens
272 * for proper support.
276 for (screen = 0; screen < ScreenCount (xdisplay); screen++)
279 int *depths = XListDepths (xdisplay, screen, &count);
280 gboolean has_8 = FALSE, has_32 = FALSE;
286 for (i = 0; i < count; i++)
290 else if (depths[i] == 32)
296 /* At this point, we might have a false positive;
297 * buggy versions of Xinerama only report depths for
298 * which there is an associated visual; so we actually
299 * go ahead and try create pixmaps.
301 if (!(has_8 && has_32))
303 gdk_error_trap_push ();
305 try_pixmap (xdisplay, screen, 8);
307 try_pixmap (xdisplay, screen, 32);
308 XSync (xdisplay, False);
309 if (gdk_error_trap_pop () == 0)
316 if (!(has_8 && has_32))
318 g_warning ("The X server advertises that RENDER support is present,\n"
319 "but fails to supply the necessary pixmap support. In\n"
320 "other words, it is buggy.");
321 x11display->have_render = GDK_NO;
328 return x11display->have_render == GDK_YES;
332 _gdk_x11_have_render_with_trapezoids (GdkDisplay *display)
334 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
335 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
337 if (x11display->have_render_with_trapezoids == GDK_UNKNOWN)
339 if (!_gdk_x11_have_render (display))
340 x11display->have_render_with_trapezoids = GDK_NO;
344 * Require protocol >= 0.4 for CompositeTrapezoids support.
346 int major_version, minor_version;
348 #define XRENDER_TETRAPEZOIDS_MAJOR 0
349 #define XRENDER_TETRAPEZOIDS_MINOR 4
351 if (XRenderQueryVersion (xdisplay, &major_version,
353 if ((major_version < XRENDER_TETRAPEZOIDS_MAJOR) ||
354 ((major_version == XRENDER_TETRAPEZOIDS_MAJOR) &&
355 (minor_version < XRENDER_TETRAPEZOIDS_MINOR)))
356 x11display->have_render_with_trapezoids = GDK_NO;
360 return x11display->have_render_with_trapezoids == GDK_YES;
364 gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable)
366 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
368 if (impl->xft_draw == NULL)
370 GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
376 visual = gdk_colormap_get_visual (colormap);
378 impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
379 GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap));
381 else if (gdk_drawable_get_depth (drawable) == 1)
383 impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid);
387 g_warning ("Using Xft rendering requires the drawable argument to\n"
388 "have a specified colormap. All windows have a colormap,\n"
389 "however, pixmaps only have colormap by default if they\n"
390 "were created with a non-NULL window argument. Otherwise\n"
391 "a colormap must be set on them with gdk_drawable_set_colormap");
396 return impl->xft_draw;
400 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
402 XftDraw *draw = gdk_x11_drawable_get_xft_draw (drawable);
404 return draw ? XftDrawPicture (draw) : None;
408 gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable,
411 GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL;
412 XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable);
414 if (gc && gc_private->clip_region)
416 GdkRegionBox *boxes = gc_private->clip_region->rects;
417 gint n_boxes = gc_private->clip_region->numRects;
418 #if 0 /* Until XftDrawSetClipRectangles is there */
419 XRectangle *rects = g_new (XRectangle, n_boxes);
422 for (i=0; i < n_boxes; i++)
424 rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
425 rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
426 rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
427 rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
429 XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes);
433 Region xregion = XCreateRegion ();
436 for (i=0; i < n_boxes; i++)
440 rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
441 rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
442 rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
443 rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
445 XUnionRectWithRegion (&rect, xregion, xregion);
448 XftDrawSetClip (xft_draw, xregion);
449 XDestroyRegion (xregion);
454 XftDrawSetClip (xft_draw, NULL);
458 /*****************************************************
459 * X11 specific implementations of generic functions *
460 *****************************************************/
463 gdk_x11_get_colormap (GdkDrawable *drawable)
465 GdkDrawableImplX11 *impl;
467 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
469 return impl->colormap;
473 gdk_x11_set_colormap (GdkDrawable *drawable,
474 GdkColormap *colormap)
476 GdkDrawableImplX11 *impl;
478 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
480 if (impl->colormap == colormap)
484 g_object_unref (impl->colormap);
485 impl->colormap = colormap;
487 g_object_ref (impl->colormap);
494 gdk_x11_draw_rectangle (GdkDrawable *drawable,
502 GdkDrawableImplX11 *impl;
504 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
507 XFillRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
508 GDK_GC_GET_XGC (gc), x, y, width, height);
510 XDrawRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
511 GDK_GC_GET_XGC (gc), x, y, width, height);
515 gdk_x11_draw_arc (GdkDrawable *drawable,
525 GdkDrawableImplX11 *impl;
527 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
531 XFillArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
532 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
534 XDrawArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
535 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
539 gdk_x11_draw_polygon (GdkDrawable *drawable,
547 GdkDrawableImplX11 *impl;
549 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
553 (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
555 tmp_npoints = npoints + 1;
556 tmp_points = g_new (XPoint, tmp_npoints);
557 tmp_points[npoints].x = points[0].x;
558 tmp_points[npoints].y = points[0].y;
562 tmp_npoints = npoints;
563 tmp_points = g_new (XPoint, tmp_npoints);
566 for (i=0; i<npoints; i++)
568 tmp_points[i].x = points[i].x;
569 tmp_points[i].y = points[i].y;
573 XFillPolygon (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
574 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
576 XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
577 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
584 * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
586 * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
589 gdk_x11_draw_text (GdkDrawable *drawable,
597 GdkDrawableImplX11 *impl;
600 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
601 xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
603 if (font->type == GDK_FONT_FONT)
605 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
606 XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
607 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
609 XDrawString (xdisplay, impl->xid,
610 GDK_GC_GET_XGC (gc), x, y, text, text_length);
614 XDrawString16 (xdisplay, impl->xid,
615 GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
618 else if (font->type == GDK_FONT_FONTSET)
620 XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
621 XmbDrawString (xdisplay, impl->xid,
622 fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
625 g_error("undefined font type\n");
629 gdk_x11_draw_text_wc (GdkDrawable *drawable,
634 const GdkWChar *text,
637 GdkDrawableImplX11 *impl;
640 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
641 xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
643 if (font->type == GDK_FONT_FONT)
645 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
648 XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
649 text_8bit = g_new (gchar, text_length);
650 for (i=0; i<text_length; i++) text_8bit[i] = text[i];
651 XDrawString (xdisplay, impl->xid,
652 GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
655 else if (font->type == GDK_FONT_FONTSET)
657 if (sizeof(GdkWChar) == sizeof(wchar_t))
659 XwcDrawString (xdisplay, impl->xid,
660 (XFontSet) GDK_FONT_XFONT (font),
661 GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
667 text_wchar = g_new (wchar_t, text_length);
668 for (i=0; i<text_length; i++) text_wchar[i] = text[i];
669 XwcDrawString (xdisplay, impl->xid,
670 (XFontSet) GDK_FONT_XFONT (font),
671 GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
676 g_error("undefined font type\n");
680 gdk_x11_draw_drawable (GdkDrawable *drawable,
690 int src_depth = gdk_drawable_get_depth (src);
691 int dest_depth = gdk_drawable_get_depth (drawable);
692 GdkDrawableImplX11 *impl;
693 GdkDrawableImplX11 *src_impl;
695 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
697 if (GDK_IS_DRAWABLE_IMPL_X11 (src))
698 src_impl = GDK_DRAWABLE_IMPL_X11 (src);
704 XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
705 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
712 else if (dest_depth != 0 && src_depth == dest_depth)
714 XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
715 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
723 g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
724 src_depth, dest_depth);
728 gdk_x11_draw_points (GdkDrawable *drawable,
733 GdkDrawableImplX11 *impl;
735 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
738 /* We special-case npoints == 1, because X will merge multiple
739 * consecutive XDrawPoint requests into a PolyPoint request
743 XDrawPoint (GDK_SCREEN_XDISPLAY (impl->screen),
746 points[0].x, points[0].y);
751 XPoint *tmp_points = g_new (XPoint, npoints);
753 for (i=0; i<npoints; i++)
755 tmp_points[i].x = points[i].x;
756 tmp_points[i].y = points[i].y;
759 XDrawPoints (GDK_SCREEN_XDISPLAY (impl->screen),
771 gdk_x11_draw_segments (GdkDrawable *drawable,
776 GdkDrawableImplX11 *impl;
778 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
781 /* We special-case nsegs == 1, because X will merge multiple
782 * consecutive XDrawLine requests into a PolySegment request
786 XDrawLine (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
787 GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
788 segs[0].x2, segs[0].y2);
793 XSegment *tmp_segs = g_new (XSegment, nsegs);
795 for (i=0; i<nsegs; i++)
797 tmp_segs[i].x1 = segs[i].x1;
798 tmp_segs[i].x2 = segs[i].x2;
799 tmp_segs[i].y1 = segs[i].y1;
800 tmp_segs[i].y2 = segs[i].y2;
803 XDrawSegments (GDK_SCREEN_XDISPLAY (impl->screen),
813 gdk_x11_draw_lines (GdkDrawable *drawable,
819 XPoint *tmp_points = g_new (XPoint, npoints);
820 GdkDrawableImplX11 *impl;
822 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
825 for (i=0; i<npoints; i++)
827 tmp_points[i].x = points[i].x;
828 tmp_points[i].y = points[i].y;
831 XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen),
841 gdk_x11_draw_glyphs (GdkDrawable *drawable,
846 PangoGlyphString *glyphs)
848 gdk_x11_draw_glyphs_transformed (drawable, gc, NULL,
856 gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable,
862 PangoGlyphString *glyphs)
864 GdkDrawableImplX11 *impl;
865 PangoRenderer *renderer;
867 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
869 g_return_if_fail (PANGO_XFT_IS_FONT (font));
871 renderer = _gdk_x11_renderer_get (drawable, gc);
873 pango_renderer_set_matrix (renderer, matrix);
874 pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
876 pango_renderer_set_matrix (renderer, NULL);
880 gdk_x11_draw_image (GdkDrawable *drawable,
890 GdkDrawableImplX11 *impl;
892 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
895 if (image->type == GDK_IMAGE_SHARED)
896 XShmPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
897 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
898 xsrc, ysrc, xdest, ydest, width, height, False);
901 XPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
902 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
903 xsrc, ysrc, xdest, ydest, width, height);
907 gdk_x11_get_depth (GdkDrawable *drawable)
909 /* This is a bit bogus but I'm not sure the other way is better */
911 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
915 get_impl_drawable (GdkDrawable *drawable)
917 if (GDK_IS_WINDOW (drawable))
918 return ((GdkWindowObject *)drawable)->impl;
919 else if (GDK_IS_PIXMAP (drawable))
920 return ((GdkPixmapObject *)drawable)->impl;
923 g_warning (G_STRLOC " drawable is not a pixmap or window");
929 gdk_x11_get_screen (GdkDrawable *drawable)
931 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
932 return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
934 return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
938 gdk_x11_get_visual (GdkDrawable *drawable)
940 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
944 * gdk_x11_drawable_get_xdisplay:
945 * @drawable: a #GdkDrawable.
947 * Returns the display of a #GdkDrawable.
949 * Return value: an Xlib <type>Display*</type>.
952 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
954 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
955 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
957 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
961 * gdk_x11_drawable_get_xid:
962 * @drawable: a #GdkDrawable.
964 * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
966 * Return value: the ID of @drawable's X resource.
969 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
973 if (GDK_IS_WINDOW (drawable))
974 impl = ((GdkPixmapObject *)drawable)->impl;
975 else if (GDK_IS_PIXMAP (drawable))
976 impl = ((GdkPixmapObject *)drawable)->impl;
979 g_warning (G_STRLOC " drawable is not a pixmap or window");
983 return ((GdkDrawableImplX11 *)impl)->xid;
986 /* Code for accelerated alpha compositing using the RENDER extension.
987 * It's a bit long because there are lots of possibilities for
988 * what's the fastest depending on the available picture formats,
989 * whether we can used shared pixmaps, etc.
992 static GdkX11FormatType
993 select_format (GdkDisplay *display,
994 XRenderPictFormat **format,
995 XRenderPictFormat **mask)
997 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
998 XRenderPictFormat pf;
1000 if (!_gdk_x11_have_render (display))
1001 return GDK_X11_FORMAT_NONE;
1003 /* Look for a 32-bit xRGB and Axxx formats that exactly match the
1004 * in memory data format. We can use them as pixmap and mask
1005 * to deal with non-premultiplied data.
1008 pf.type = PictTypeDirect;
1010 pf.direct.redMask = 0xff;
1011 pf.direct.greenMask = 0xff;
1012 pf.direct.blueMask = 0xff;
1014 pf.direct.alphaMask = 0;
1015 if (ImageByteOrder (xdisplay) == LSBFirst)
1019 pf.direct.green = 8;
1020 pf.direct.blue = 16;
1026 pf.direct.green = 16;
1030 *format = XRenderFindFormat (xdisplay,
1031 (PictFormatType | PictFormatDepth |
1032 PictFormatRedMask | PictFormatRed |
1033 PictFormatGreenMask | PictFormatGreen |
1034 PictFormatBlueMask | PictFormatBlue |
1035 PictFormatAlphaMask),
1039 pf.direct.alphaMask = 0xff;
1040 if (ImageByteOrder (xdisplay) == LSBFirst)
1043 pf.direct.alpha = 24;
1047 pf.direct.alpha = 0;
1050 *mask = XRenderFindFormat (xdisplay,
1051 (PictFormatType | PictFormatDepth |
1052 PictFormatAlphaMask | PictFormatAlpha),
1056 if (*format && *mask)
1057 return GDK_X11_FORMAT_EXACT_MASK;
1059 /* OK, that failed, now look for xRGB and Axxx formats in
1060 * RENDER's preferred order
1062 pf.direct.alphaMask = 0;
1065 pf.direct.green = 8;
1068 *format = XRenderFindFormat (xdisplay,
1069 (PictFormatType | PictFormatDepth |
1070 PictFormatRedMask | PictFormatRed |
1071 PictFormatGreenMask | PictFormatGreen |
1072 PictFormatBlueMask | PictFormatBlue |
1073 PictFormatAlphaMask),
1077 pf.direct.alphaMask = 0xff;
1078 pf.direct.alpha = 24;
1080 *mask = XRenderFindFormat (xdisplay,
1081 (PictFormatType | PictFormatDepth |
1082 PictFormatAlphaMask | PictFormatAlpha),
1086 if (*format && *mask)
1087 return GDK_X11_FORMAT_ARGB_MASK;
1089 /* Finally, if neither of the above worked, fall back to
1090 * looking for combined ARGB -- we'll premultiply ourselves.
1093 pf.type = PictTypeDirect;
1096 pf.direct.green = 8;
1098 pf.direct.alphaMask = 0xff;
1099 pf.direct.alpha = 24;
1101 *format = XRenderFindFormat (xdisplay,
1102 (PictFormatType | PictFormatDepth |
1103 PictFormatRedMask | PictFormatRed |
1104 PictFormatGreenMask | PictFormatGreen |
1105 PictFormatBlueMask | PictFormatBlue |
1106 PictFormatAlphaMask | PictFormatAlpha),
1112 return GDK_X11_FORMAT_ARGB;
1114 return GDK_X11_FORMAT_NONE;
1119 list_formats (XRenderPictFormat *pf)
1125 XRenderPictFormat *pf = XRenderFindFormat (impl->xdisplay, 0, NULL, i);
1128 g_print ("%2d R-%#06x/%#06x G-%#06x/%#06x B-%#06x/%#06x A-%#06x/%#06x\n",
1133 pf->direct.greenMask,
1135 pf->direct.blueMask,
1137 pf->direct.alphaMask);
1146 _gdk_x11_convert_to_format (guchar *src_buf,
1149 gint dest_rowstride,
1150 GdkX11FormatType dest_format,
1151 GdkByteOrder dest_byteorder,
1157 for (i=0; i < height; i++)
1159 switch (dest_format)
1161 case GDK_X11_FORMAT_EXACT_MASK:
1163 memcpy (dest_buf + i * dest_rowstride,
1164 src_buf + i * src_rowstride,
1168 case GDK_X11_FORMAT_ARGB_MASK:
1170 guchar *row = src_buf + i * src_rowstride;
1171 if (((gsize)row & 3) != 0)
1174 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1175 guchar *end = p + 4 * width;
1179 *q = (p[3] << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
1186 guint32 *p = (guint32 *)row;
1187 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1188 guint32 *end = p + width;
1190 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1191 if (dest_byteorder == GDK_LSB_FIRST)
1197 *q = ( (*p & 0xff00ff00) |
1198 ((*p & 0x000000ff) << 16) |
1199 ((*p & 0x00ff0000) >> 16));
1210 *q = (((*p & 0xff000000) >> 24) |
1211 ((*p & 0x00ffffff) << 8));
1216 #else /* G_BYTE_ORDER == G_BIG_ENDIAN */
1217 if (dest_byteorder == GDK_LSB_FIRST)
1223 *q = ( (*p & 0x00ff00ff) |
1224 ((*p & 0x0000ff00) << 16) |
1225 ((*p & 0xff000000) >> 16));
1236 *q = (((*p & 0xffffff00) >> 8) |
1237 ((*p & 0x000000ff) << 24));
1242 #endif /* G_BYTE_ORDER*/
1246 case GDK_X11_FORMAT_ARGB:
1248 guchar *p = (src_buf + i * src_rowstride);
1249 guchar *q = (dest_buf + i * dest_rowstride);
1250 guchar *end = p + 4 * width;
1253 #define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
1255 if (dest_byteorder == GDK_LSB_FIRST)
1259 MULT(q[0], p[2], p[3], t1);
1260 MULT(q[1], p[1], p[3], t2);
1261 MULT(q[2], p[0], p[3], t3);
1272 MULT(q[1], p[0], p[3], t1);
1273 MULT(q[2], p[1], p[3], t2);
1274 MULT(q[3], p[2], p[3], t3);
1282 case GDK_X11_FORMAT_NONE:
1283 g_assert_not_reached ();
1290 draw_with_images (GdkDrawable *drawable,
1292 GdkX11FormatType format_type,
1293 XRenderPictFormat *format,
1294 XRenderPictFormat *mask_format,
1302 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1303 Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
1309 Picture mask = None;
1312 pix = gdk_pixmap_new (gdk_screen_get_root_window (screen), width, height, 32);
1314 pict = XRenderCreatePicture (xdisplay,
1315 GDK_PIXMAP_XID (pix),
1318 mask = XRenderCreatePicture (xdisplay,
1319 GDK_PIXMAP_XID (pix),
1320 mask_format, 0, NULL);
1322 dest_pict = gdk_x11_drawable_get_picture (drawable);
1324 pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE);
1326 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1328 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1329 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1333 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1335 image = _gdk_image_get_scratch (screen, width1, height1, 32, &xs0, &ys0);
1337 _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1338 (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1339 format_type, image->byte_order,
1342 gdk_draw_image (pix, pix_gc,
1343 image, xs0, ys0, x0, y0, width1, height1);
1347 XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
1348 0, 0, 0, 0, dest_x, dest_y, width, height);
1350 XRenderFreePicture (xdisplay, pict);
1352 XRenderFreePicture (xdisplay, mask);
1354 g_object_unref (pix);
1357 typedef struct _ShmPixmapInfo ShmPixmapInfo;
1359 struct _ShmPixmapInfo
1367 /* Returns FALSE if we can't get a shm pixmap */
1369 get_shm_pixmap_for_image (Display *xdisplay,
1371 XRenderPictFormat *format,
1372 XRenderPictFormat *mask_format,
1377 ShmPixmapInfo *info;
1379 if (image->type != GDK_IMAGE_SHARED)
1382 info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
1385 *pix = _gdk_x11_image_get_shm_pixmap (image);
1390 info = g_new (ShmPixmapInfo, 1);
1393 info->pict = XRenderCreatePicture (xdisplay, info->pix,
1396 info->mask = XRenderCreatePicture (xdisplay, info->pix,
1397 mask_format, 0, NULL);
1401 g_object_set_data (G_OBJECT (image), "gdk-x11-shm-pixmap", info);
1412 /* Returns FALSE if drawing with ShmPixmaps is not possible */
1414 draw_with_pixmaps (GdkDrawable *drawable,
1416 GdkX11FormatType format_type,
1417 XRenderPictFormat *format,
1418 XRenderPictFormat *mask_format,
1426 Display *xdisplay = GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
1431 Picture mask = None;
1434 dest_pict = gdk_x11_drawable_get_picture (drawable);
1436 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1438 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1439 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1443 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1445 image = _gdk_image_get_scratch (GDK_DRAWABLE_IMPL_X11 (drawable)->screen,
1446 width1, height1, 32, &xs0, &ys0);
1447 if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
1450 _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1451 (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1452 format_type, image->byte_order,
1455 XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
1456 xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
1466 gdk_x11_draw_pixbuf (GdkDrawable *drawable,
1475 GdkRgbDither dither,
1479 GdkX11FormatType format_type;
1480 XRenderPictFormat *format, *mask_format;
1483 gboolean use_pixmaps = TRUE;
1484 #endif /* USE_SHM */
1486 format_type = select_format (gdk_drawable_get_display (drawable),
1487 &format, &mask_format);
1489 if (format_type == GDK_X11_FORMAT_NONE ||
1490 !gdk_pixbuf_get_has_alpha (pixbuf) ||
1491 gdk_drawable_get_depth (drawable) == 1 ||
1492 (dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
1493 gdk_x11_drawable_get_picture (drawable) == None)
1495 GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1496 GDK_DRAWABLE_CLASS (parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
1497 src_x, src_y, dest_x, dest_y,
1499 dither, x_dither, y_dither);
1503 gdk_x11_drawable_update_xft_clip (drawable, gc);
1505 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1510 if (!draw_with_pixmaps (drawable, gc,
1511 format_type, format, mask_format,
1512 gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1514 dest_x, dest_y, width, height))
1515 use_pixmaps = FALSE;
1519 #endif /* USE_SHM */
1520 draw_with_images (drawable, gc,
1521 format_type, format, mask_format,
1522 gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1524 dest_x, dest_y, width, height);
1528 gdk_x11_draw_trapezoids (GdkDrawable *drawable,
1530 GdkTrapezoid *trapezoids,
1533 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1534 GdkDisplay *display = gdk_screen_get_display (screen);
1535 XTrapezoid *xtrapezoids;
1538 if (!_gdk_x11_have_render_with_trapezoids (display))
1540 GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1541 GDK_DRAWABLE_CLASS (parent_class)->draw_trapezoids (wrapper, gc,
1542 trapezoids, n_trapezoids);
1546 xtrapezoids = g_new (XTrapezoid, n_trapezoids);
1548 for (i = 0; i < n_trapezoids; i++)
1550 xtrapezoids[i].top = XDoubleToFixed (trapezoids[i].y1);
1551 xtrapezoids[i].bottom = XDoubleToFixed (trapezoids[i].y2);
1552 xtrapezoids[i].left.p1.x = XDoubleToFixed (trapezoids[i].x11);
1553 xtrapezoids[i].left.p1.y = XDoubleToFixed (trapezoids[i].y1);
1554 xtrapezoids[i].left.p2.x = XDoubleToFixed (trapezoids[i].x12);
1555 xtrapezoids[i].left.p2.y = XDoubleToFixed (trapezoids[i].y2);
1556 xtrapezoids[i].right.p1.x = XDoubleToFixed (trapezoids[i].x21);
1557 xtrapezoids[i].right.p1.y = XDoubleToFixed (trapezoids[i].y1);
1558 xtrapezoids[i].right.p2.x = XDoubleToFixed (trapezoids[i].x22);
1559 xtrapezoids[i].right.p2.y = XDoubleToFixed (trapezoids[i].y2);
1562 _gdk_x11_drawable_draw_xtrapezoids (drawable, gc,
1563 xtrapezoids, n_trapezoids);
1565 g_free (xtrapezoids);
1568 static cairo_surface_t *
1569 gdk_x11_drawable_get_cairo_surface (GdkDrawable *drawable)
1571 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
1572 GdkColormap *colormap;
1575 if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
1576 GDK_WINDOW_DESTROYED (impl->wrapper))
1579 colormap = gdk_drawable_get_colormap (drawable);
1582 g_warning ("Using Cairo rendering requires the drawable argument to\n"
1583 "have a specified colormap. All windows have a colormap,\n"
1584 "however, pixmaps only have colormap by default if they\n"
1585 "were created with a non-NULL window argument. Otherwise\n"
1586 "a colormap must be set on them with gdk_drawable_set_colormap");
1590 visual = gdk_colormap_get_visual (colormap);
1592 if (!impl->cairo_surface)
1594 impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
1596 GDK_VISUAL_XVISUAL (visual),
1598 GDK_COLORMAP_XCOLORMAP (colormap));
1601 return impl->cairo_surface;
1605 gdk_x11_set_cairo_target (GdkDrawable *drawable,
1608 cairo_surface_t *surface = gdk_x11_drawable_get_cairo_surface (drawable);
1610 cairo_set_target_surface (cr, surface);
1614 * gdk_draw_rectangle_alpha_libgtk_only:
1615 * @drawable: The #GdkDrawable to draw on
1616 * @x: the x coordinate of the left edge of the rectangle.
1617 * @y: the y coordinate of the top edge of the rectangle.
1618 * @width: the width of the rectangle.
1619 * @height: the height of the rectangle.
1621 * @alpha: The alpha value.
1623 * Tries to draw a filled alpha blended rectangle using the window
1624 * system's native routines. This is not public API and must not be
1625 * used by applications.
1627 * Return value: TRUE if the rectangle could be drawn, FALSE
1631 gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable,
1640 XRenderColor render_color;
1642 int x_offset, y_offset;
1643 GdkDrawable *real_drawable, *impl;
1645 g_return_val_if_fail (color != NULL, FALSE);
1647 if (!GDK_IS_WINDOW (drawable))
1650 if (!_gdk_x11_have_render (gdk_drawable_get_display (drawable)))
1653 gdk_window_get_internal_paint_info (GDK_WINDOW (drawable),
1655 &x_offset, &y_offset);
1657 impl = ((GdkWindowObject *)real_drawable)->impl;
1659 pict = gdk_x11_drawable_get_picture (impl);
1664 xdisplay = GDK_DISPLAY_XDISPLAY (gdk_drawable_get_display (drawable));
1666 render_color.alpha = alpha;
1667 render_color.red = (guint32)color->red * render_color.alpha / 0xffff;
1668 render_color.green = (guint32)color->green * render_color.alpha / 0xffff;
1669 render_color.blue = (guint32)color->blue * render_color.alpha / 0xffff;
1671 XRenderFillRectangle (xdisplay,
1672 PictOpOver, pict, &render_color,
1673 x - x_offset, y - y_offset,
1679 _gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable,
1681 XTrapezoid *xtrapezoids,
1684 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1685 GdkDisplay *display = gdk_screen_get_display (screen);
1686 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
1690 if (!_gdk_x11_have_render_with_trapezoids (display))
1692 /* This is the case of drawing the borders of the unknown glyph box
1693 * without render on the display, we need to feed it back to
1694 * fallback code. Not efficient, but doesn't matter.
1696 GdkTrapezoid *trapezoids = g_new (GdkTrapezoid, n_trapezoids);
1699 for (i = 0; i < n_trapezoids; i++)
1701 trapezoids[i].y1 = XFixedToDouble (xtrapezoids[i].top);
1702 trapezoids[i].y2 = XFixedToDouble (xtrapezoids[i].bottom);
1703 trapezoids[i].x11 = XFixedToDouble (xtrapezoids[i].left.p1.x);
1704 trapezoids[i].x12 = XFixedToDouble (xtrapezoids[i].left.p2.x);
1705 trapezoids[i].x21 = XFixedToDouble (xtrapezoids[i].right.p1.x);
1706 trapezoids[i].x22 = XFixedToDouble (xtrapezoids[i].right.p2.x);
1709 gdk_x11_draw_trapezoids (drawable, gc, trapezoids, n_trapezoids);
1710 g_free (trapezoids);
1715 gdk_x11_drawable_update_xft_clip (drawable, gc);
1716 draw = gdk_x11_drawable_get_xft_draw (drawable);
1718 if (!x11display->mask_format)
1719 x11display->mask_format = XRenderFindStandardFormat (x11display->xdisplay,
1722 XRenderCompositeTrapezoids (x11display->xdisplay, PictOpOver,
1723 _gdk_x11_gc_get_fg_picture (gc),
1724 XftDrawPicture (draw),
1725 x11display->mask_format,
1726 - gc->ts_x_origin, - gc->ts_y_origin,
1727 xtrapezoids, n_trapezoids);
1731 _gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable,
1734 XftGlyphSpec *glyphs,
1737 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1738 GdkDisplay *display = gdk_screen_get_display (screen);
1739 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
1742 gdk_x11_drawable_update_xft_clip (drawable, gc);
1743 draw = gdk_x11_drawable_get_xft_draw (drawable);
1745 if (_gdk_x11_have_render (display))
1747 XftGlyphSpecRender (x11display->xdisplay, PictOpOver,
1748 _gdk_x11_gc_get_fg_picture (gc),
1750 XftDrawPicture (draw),
1751 - gc->ts_x_origin, - gc->ts_y_origin,
1758 _gdk_gc_x11_get_fg_xft_color (gc, &color);
1759 XftDrawGlyphSpec (draw, &color, xft_font, glyphs, n_glyphs);