]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdrawable-x11.c
a35a54b40e6d9b9856a39827440f0cf09d4572a1
[~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 "gdkdrawable-x11.h"
30
31 #include "gdkx.h"
32 #include "gdkprivate-x11.h"
33 #include "gdkscreen-x11.h"
34 #include "gdkdisplay-x11.h"
35
36 #include <cairo-xlib.h>
37
38 #include <stdlib.h>
39 #include <string.h>
40
41
42 static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable);
43 static cairo_surface_t *gdk_x11_create_cairo_surface (GdkDrawable *drawable,
44                                                       int          width,
45                                                       int          height);
46      
47 static const cairo_user_data_key_t gdk_x11_cairo_key;
48
49 G_DEFINE_TYPE (GdkDrawableImplX11, _gdk_drawable_impl_x11, GDK_TYPE_DRAWABLE)
50
51 static void
52 _gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
53 {
54   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
55   
56   drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
57   drawable_class->create_cairo_surface = gdk_x11_create_cairo_surface;
58 }
59
60 static void
61 _gdk_drawable_impl_x11_init (GdkDrawableImplX11 *impl)
62 {
63 }
64
65 /**
66  * _gdk_x11_drawable_finish:
67  * @drawable: a #GdkDrawableImplX11.
68  * 
69  * Performs necessary cleanup prior to destroying a window.
70  **/
71 void
72 _gdk_x11_drawable_finish (GdkDrawable *drawable)
73 {
74   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
75   
76   if (impl->cairo_surface)
77     {
78       cairo_surface_finish (impl->cairo_surface);
79       cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
80                                    NULL, NULL);
81     }
82 }
83
84 /**
85  * _gdk_x11_drawable_update_size:
86  * @drawable: a #GdkDrawableImplX11.
87  * 
88  * Updates the state of the drawable (in particular the drawable's
89  * cairo surface) when its size has changed.
90  **/
91 void
92 _gdk_x11_drawable_update_size (GdkDrawable *drawable)
93 {
94   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
95   
96   if (impl->cairo_surface)
97     {
98       cairo_xlib_surface_set_size (impl->cairo_surface,
99                                    gdk_window_get_width (impl->wrapper),
100                                    gdk_window_get_height (impl->wrapper));
101     }
102 }
103
104 /*****************************************************
105  * X11 specific implementations of generic functions *
106  *****************************************************/
107
108 static GdkDrawable *
109 get_impl_drawable (GdkDrawable *drawable)
110 {
111   if (GDK_IS_WINDOW (drawable))
112     return ((GdkWindowObject *)drawable)->impl;
113   else
114     {
115       g_warning (G_STRLOC " drawable is not a window");
116       return NULL;
117     }
118 }
119
120 /**
121  * gdk_x11_drawable_get_xdisplay:
122  * @drawable: a #GdkDrawable.
123  * 
124  * Returns the display of a #GdkDrawable.
125  * 
126  * Return value: an Xlib <type>Display*</type>.
127  **/
128 Display *
129 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
130 {
131   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
132     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
133   else
134     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
135 }
136
137 /**
138  * gdk_x11_drawable_get_xid:
139  * @drawable: a #GdkDrawable.
140  * 
141  * Returns the X resource (window) belonging to a #GdkDrawable.
142  * 
143  * Return value: the ID of @drawable's X resource.
144  **/
145 XID
146 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
147 {
148   GdkDrawable *impl;
149   
150   if (GDK_IS_WINDOW (drawable))
151     {
152       GdkWindow *window = (GdkWindow *)drawable;
153       
154       /* Try to ensure the window has a native window */
155       if (!_gdk_window_has_impl (window))
156         {
157           gdk_window_ensure_native (window);
158
159           /* We sync here to ensure the window is created in the Xserver when
160            * this function returns. This is required because the returned XID
161            * for this window must be valid immediately, even with another
162            * connection to the Xserver */
163           gdk_display_sync (gdk_window_get_display (window));
164         }
165       
166       if (!GDK_WINDOW_IS_X11 (window))
167         {
168           g_warning (G_STRLOC " drawable is not a native X11 window");
169           return None;
170         }
171       
172       impl = ((GdkWindowObject *)drawable)->impl;
173     }
174   else
175     {
176       g_warning (G_STRLOC " drawable is not a window");
177       return None;
178     }
179
180   return ((GdkDrawableImplX11 *)impl)->xid;
181 }
182
183 GdkDrawable *
184 gdk_x11_window_get_drawable_impl (GdkWindow *window)
185 {
186   return ((GdkWindowObject *)window)->impl;
187 }
188
189 static void
190 gdk_x11_cairo_surface_destroy (void *data)
191 {
192   GdkDrawableImplX11 *impl = data;
193
194   impl->cairo_surface = NULL;
195 }
196
197 static cairo_surface_t *
198 gdk_x11_create_cairo_surface (GdkDrawable *drawable,
199                               int width,
200                               int height)
201 {
202   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
203   GdkVisual *visual;
204     
205   visual = gdk_window_get_visual (impl->wrapper);
206   return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
207                                     impl->xid,
208                                     GDK_VISUAL_XVISUAL (visual),
209                                     width, height);
210 }
211
212 static cairo_surface_t *
213 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
214 {
215   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
216
217   if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
218       GDK_WINDOW_DESTROYED (impl->wrapper))
219     return NULL;
220
221   if (!impl->cairo_surface)
222     {
223       impl->cairo_surface = gdk_x11_create_cairo_surface (drawable,
224                                                           gdk_window_get_width (impl->wrapper),
225                                                           gdk_window_get_height (impl->wrapper));
226       
227       if (impl->cairo_surface)
228         cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
229                                      drawable, gdk_x11_cairo_surface_destroy);
230     }
231   else
232     cairo_surface_reference (impl->cairo_surface);
233
234   return impl->cairo_surface;
235 }