]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdrawable-x11.c
x11: Remove last traces of XShm
[~andy/gtk] / gdk / x11 / gdkdrawable-x11.c
1 /* GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include "config.h"
28
29 #include "gdkx.h"
30
31 #include <cairo-xlib.h>
32
33 #include <stdlib.h>
34 #include <string.h>             /* for memcpy() */
35
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"
41
42
43 static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable);
44 static cairo_surface_t *gdk_x11_create_cairo_surface (GdkDrawable *drawable,
45                                                       int          width,
46                                                       int          height);
47      
48 static void gdk_x11_set_colormap   (GdkDrawable    *drawable,
49                                     GdkColormap    *colormap);
50
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);
55
56 static void gdk_drawable_impl_x11_finalize   (GObject *object);
57
58 static const cairo_user_data_key_t gdk_x11_cairo_key;
59
60 G_DEFINE_TYPE (GdkDrawableImplX11, _gdk_drawable_impl_x11, GDK_TYPE_DRAWABLE)
61
62 static void
63 _gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
64 {
65   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
66   GObjectClass *object_class = G_OBJECT_CLASS (klass);
67   
68   object_class->finalize = gdk_drawable_impl_x11_finalize;
69   
70   drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
71   drawable_class->create_cairo_surface = gdk_x11_create_cairo_surface;
72
73   drawable_class->set_colormap = gdk_x11_set_colormap;
74   drawable_class->get_colormap = gdk_x11_get_colormap;
75
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;
79 }
80
81 static void
82 _gdk_drawable_impl_x11_init (GdkDrawableImplX11 *impl)
83 {
84 }
85
86 static void
87 gdk_drawable_impl_x11_finalize (GObject *object)
88 {
89   gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
90
91   G_OBJECT_CLASS (_gdk_drawable_impl_x11_parent_class)->finalize (object);
92 }
93
94 /**
95  * _gdk_x11_drawable_finish:
96  * @drawable: a #GdkDrawableImplX11.
97  * 
98  * Performs necessary cleanup prior to freeing a pixmap or
99  * destroying a window.
100  **/
101 void
102 _gdk_x11_drawable_finish (GdkDrawable *drawable)
103 {
104   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
105   
106   if (impl->cairo_surface)
107     {
108       cairo_surface_finish (impl->cairo_surface);
109       cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
110                                    NULL, NULL);
111     }
112 }
113
114 /**
115  * _gdk_x11_drawable_update_size:
116  * @drawable: a #GdkDrawableImplX11.
117  * 
118  * Updates the state of the drawable (in particular the drawable's
119  * cairo surface) when its size has changed.
120  **/
121 void
122 _gdk_x11_drawable_update_size (GdkDrawable *drawable)
123 {
124   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
125   
126   if (impl->cairo_surface)
127     {
128       int width, height;
129       
130       gdk_drawable_get_size (drawable, &width, &height);
131       cairo_xlib_surface_set_size (impl->cairo_surface, width, height);
132     }
133 }
134
135 /*****************************************************
136  * X11 specific implementations of generic functions *
137  *****************************************************/
138
139 static GdkColormap*
140 gdk_x11_get_colormap (GdkDrawable *drawable)
141 {
142   GdkDrawableImplX11 *impl;
143
144   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
145
146   return impl->colormap;
147 }
148
149 static void
150 gdk_x11_set_colormap (GdkDrawable *drawable,
151                       GdkColormap *colormap)
152 {
153   GdkDrawableImplX11 *impl;
154
155   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
156
157   if (impl->colormap == colormap)
158     return;
159   
160   if (impl->colormap)
161     g_object_unref (impl->colormap);
162   impl->colormap = colormap;
163   if (impl->colormap)
164     g_object_ref (impl->colormap);
165 }
166
167 static gint
168 gdk_x11_get_depth (GdkDrawable *drawable)
169 {
170   /* This is a bit bogus but I'm not sure the other way is better */
171
172   return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
173 }
174
175 static GdkDrawable *
176 get_impl_drawable (GdkDrawable *drawable)
177 {
178   if (GDK_IS_WINDOW (drawable))
179     return ((GdkWindowObject *)drawable)->impl;
180   else if (GDK_IS_PIXMAP (drawable))
181     return ((GdkPixmapObject *)drawable)->impl;
182   else
183     {
184       g_warning (G_STRLOC " drawable is not a pixmap or window");
185       return NULL;
186     }
187 }
188
189 static GdkScreen*
190 gdk_x11_get_screen (GdkDrawable *drawable)
191 {
192   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
193     return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
194   else
195     return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
196 }
197
198 static GdkVisual*
199 gdk_x11_get_visual (GdkDrawable    *drawable)
200 {
201   return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
202 }
203
204 /**
205  * gdk_x11_drawable_get_xdisplay:
206  * @drawable: a #GdkDrawable.
207  * 
208  * Returns the display of a #GdkDrawable.
209  * 
210  * Return value: an Xlib <type>Display*</type>.
211  **/
212 Display *
213 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
214 {
215   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
216     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
217   else
218     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
219 }
220
221 /**
222  * gdk_x11_drawable_get_xid:
223  * @drawable: a #GdkDrawable.
224  * 
225  * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
226  * 
227  * Return value: the ID of @drawable's X resource.
228  **/
229 XID
230 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
231 {
232   GdkDrawable *impl;
233   
234   if (GDK_IS_WINDOW (drawable))
235     {
236       GdkWindow *window = (GdkWindow *)drawable;
237       
238       /* Try to ensure the window has a native window */
239       if (!_gdk_window_has_impl (window))
240         {
241           gdk_window_ensure_native (window);
242
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));
248         }
249       
250       if (!GDK_WINDOW_IS_X11 (window))
251         {
252           g_warning (G_STRLOC " drawable is not a native X11 window");
253           return None;
254         }
255       
256       impl = ((GdkWindowObject *)drawable)->impl;
257     }
258   else if (GDK_IS_PIXMAP (drawable))
259     impl = ((GdkPixmapObject *)drawable)->impl;
260   else
261     {
262       g_warning (G_STRLOC " drawable is not a pixmap or window");
263       return None;
264     }
265
266   return ((GdkDrawableImplX11 *)impl)->xid;
267 }
268
269 GdkDrawable *
270 gdk_x11_window_get_drawable_impl (GdkWindow *window)
271 {
272   return ((GdkWindowObject *)window)->impl;
273 }
274 GdkDrawable *
275 gdk_x11_pixmap_get_drawable_impl (GdkPixmap *pixmap)
276 {
277   return ((GdkPixmapObject *)pixmap)->impl;
278 }
279
280 static void
281 gdk_x11_cairo_surface_destroy (void *data)
282 {
283   GdkDrawableImplX11 *impl = data;
284
285   impl->cairo_surface = NULL;
286 }
287
288 gboolean
289 _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
290                                        int width,
291                                        int height)
292 {
293   cairo_xlib_surface_set_size (surface, width, height);
294   return TRUE;
295 }
296
297 static cairo_surface_t *
298 gdk_x11_create_cairo_surface (GdkDrawable *drawable,
299                               int width,
300                               int height)
301 {
302   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
303   GdkVisual *visual;
304     
305   visual = gdk_drawable_get_visual (drawable);
306   if (visual) 
307     return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
308                                       impl->xid,
309                                       GDK_VISUAL_XVISUAL (visual),
310                                       width, height);
311   else if (gdk_drawable_get_depth (drawable) == 1)
312     return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
313                                                     impl->xid,
314                                                     GDK_SCREEN_XSCREEN (impl->screen),
315                                                     width, height);
316   else
317     {
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");
323       return NULL;
324     }
325   
326 }
327
328 static cairo_surface_t *
329 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
330 {
331   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
332
333   if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
334       GDK_WINDOW_DESTROYED (impl->wrapper))
335     return NULL;
336
337   if (!impl->cairo_surface)
338     {
339       int width, height;
340   
341       gdk_drawable_get_size (impl->wrapper, &width, &height);
342
343       impl->cairo_surface = gdk_x11_create_cairo_surface (drawable, width, height);
344       
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);
348     }
349   else
350     cairo_surface_reference (impl->cairo_surface);
351
352   return impl->cairo_surface;
353 }