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 <cairo-xlib.h>
34 #include <string.h> /* for memcpy() */
36 #include "gdkprivate-x11.h"
37 #include "gdkdrawable-x11.h"
38 #include "gdkpixmap-x11.h"
39 #include "gdkscreen-x11.h"
40 #include "gdkdisplay-x11.h"
43 static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable);
44 static cairo_surface_t *gdk_x11_create_cairo_surface (GdkDrawable *drawable,
48 static void gdk_x11_set_colormap (GdkDrawable *drawable,
49 GdkColormap *colormap);
51 static GdkColormap* gdk_x11_get_colormap (GdkDrawable *drawable);
52 static gint gdk_x11_get_depth (GdkDrawable *drawable);
53 static GdkScreen * gdk_x11_get_screen (GdkDrawable *drawable);
54 static GdkVisual* gdk_x11_get_visual (GdkDrawable *drawable);
56 static void gdk_drawable_impl_x11_finalize (GObject *object);
58 static const cairo_user_data_key_t gdk_x11_cairo_key;
60 G_DEFINE_TYPE (GdkDrawableImplX11, _gdk_drawable_impl_x11, GDK_TYPE_DRAWABLE)
63 _gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
65 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
66 GObjectClass *object_class = G_OBJECT_CLASS (klass);
68 object_class->finalize = gdk_drawable_impl_x11_finalize;
70 drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
71 drawable_class->create_cairo_surface = gdk_x11_create_cairo_surface;
73 drawable_class->set_colormap = gdk_x11_set_colormap;
74 drawable_class->get_colormap = gdk_x11_get_colormap;
76 drawable_class->get_depth = gdk_x11_get_depth;
77 drawable_class->get_screen = gdk_x11_get_screen;
78 drawable_class->get_visual = gdk_x11_get_visual;
82 _gdk_drawable_impl_x11_init (GdkDrawableImplX11 *impl)
87 gdk_drawable_impl_x11_finalize (GObject *object)
89 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
91 G_OBJECT_CLASS (_gdk_drawable_impl_x11_parent_class)->finalize (object);
95 * _gdk_x11_drawable_finish:
96 * @drawable: a #GdkDrawableImplX11.
98 * Performs necessary cleanup prior to freeing a pixmap or
99 * destroying a window.
102 _gdk_x11_drawable_finish (GdkDrawable *drawable)
104 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
106 if (impl->cairo_surface)
108 cairo_surface_finish (impl->cairo_surface);
109 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
115 * _gdk_x11_drawable_update_size:
116 * @drawable: a #GdkDrawableImplX11.
118 * Updates the state of the drawable (in particular the drawable's
119 * cairo surface) when its size has changed.
122 _gdk_x11_drawable_update_size (GdkDrawable *drawable)
124 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
126 if (impl->cairo_surface)
130 gdk_drawable_get_size (drawable, &width, &height);
131 cairo_xlib_surface_set_size (impl->cairo_surface, width, height);
135 /*****************************************************
136 * X11 specific implementations of generic functions *
137 *****************************************************/
140 gdk_x11_get_colormap (GdkDrawable *drawable)
142 GdkDrawableImplX11 *impl;
144 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
146 return impl->colormap;
150 gdk_x11_set_colormap (GdkDrawable *drawable,
151 GdkColormap *colormap)
153 GdkDrawableImplX11 *impl;
155 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
157 if (impl->colormap == colormap)
161 g_object_unref (impl->colormap);
162 impl->colormap = colormap;
164 g_object_ref (impl->colormap);
168 gdk_x11_get_depth (GdkDrawable *drawable)
170 /* This is a bit bogus but I'm not sure the other way is better */
172 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
176 get_impl_drawable (GdkDrawable *drawable)
178 if (GDK_IS_WINDOW (drawable))
179 return ((GdkWindowObject *)drawable)->impl;
180 else if (GDK_IS_PIXMAP (drawable))
181 return ((GdkPixmapObject *)drawable)->impl;
184 g_warning (G_STRLOC " drawable is not a pixmap or window");
190 gdk_x11_get_screen (GdkDrawable *drawable)
192 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
193 return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
195 return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
199 gdk_x11_get_visual (GdkDrawable *drawable)
201 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
205 * gdk_x11_drawable_get_xdisplay:
206 * @drawable: a #GdkDrawable.
208 * Returns the display of a #GdkDrawable.
210 * Return value: an Xlib <type>Display*</type>.
213 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
215 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
216 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
218 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
222 * gdk_x11_drawable_get_xid:
223 * @drawable: a #GdkDrawable.
225 * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
227 * Return value: the ID of @drawable's X resource.
230 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
234 if (GDK_IS_WINDOW (drawable))
236 GdkWindow *window = (GdkWindow *)drawable;
238 /* Try to ensure the window has a native window */
239 if (!_gdk_window_has_impl (window))
241 gdk_window_ensure_native (window);
243 /* We sync here to ensure the window is created in the Xserver when
244 * this function returns. This is required because the returned XID
245 * for this window must be valid immediately, even with another
246 * connection to the Xserver */
247 gdk_display_sync (gdk_drawable_get_display (window));
250 if (!GDK_WINDOW_IS_X11 (window))
252 g_warning (G_STRLOC " drawable is not a native X11 window");
256 impl = ((GdkWindowObject *)drawable)->impl;
258 else if (GDK_IS_PIXMAP (drawable))
259 impl = ((GdkPixmapObject *)drawable)->impl;
262 g_warning (G_STRLOC " drawable is not a pixmap or window");
266 return ((GdkDrawableImplX11 *)impl)->xid;
270 gdk_x11_window_get_drawable_impl (GdkWindow *window)
272 return ((GdkWindowObject *)window)->impl;
275 gdk_x11_pixmap_get_drawable_impl (GdkPixmap *pixmap)
277 return ((GdkPixmapObject *)pixmap)->impl;
281 gdk_x11_cairo_surface_destroy (void *data)
283 GdkDrawableImplX11 *impl = data;
285 impl->cairo_surface = NULL;
289 _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
293 cairo_xlib_surface_set_size (surface, width, height);
297 static cairo_surface_t *
298 gdk_x11_create_cairo_surface (GdkDrawable *drawable,
302 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
305 visual = gdk_drawable_get_visual (drawable);
307 return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
309 GDK_VISUAL_XVISUAL (visual),
311 else if (gdk_drawable_get_depth (drawable) == 1)
312 return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
314 GDK_SCREEN_XSCREEN (impl->screen),
318 g_warning ("Using Cairo rendering requires the drawable argument to\n"
319 "have a specified colormap. All windows have a colormap,\n"
320 "however, pixmaps only have colormap by default if they\n"
321 "were created with a non-NULL window argument. Otherwise\n"
322 "a colormap must be set on them with gdk_drawable_set_colormap");
328 static cairo_surface_t *
329 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
331 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
333 if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
334 GDK_WINDOW_DESTROYED (impl->wrapper))
337 if (!impl->cairo_surface)
341 gdk_drawable_get_size (impl->wrapper, &width, &height);
343 impl->cairo_surface = gdk_x11_create_cairo_surface (drawable, width, height);
345 if (impl->cairo_surface)
346 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
347 drawable, gdk_x11_cairo_surface_destroy);
350 cairo_surface_reference (impl->cairo_surface);
352 return impl->cairo_surface;