]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkpixmap-x11.c
Merge branch 'master' into client-side-windows
[~andy/gtk] / gdk / x11 / gdkpixmap-x11.c
1 /* GDK - The 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 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 /* Needed for SEEK_END in SunOS */
32 #include <unistd.h>
33 #include <X11/Xlib.h>
34
35 #include "gdkx.h"
36
37 #include "gdkpixmap-x11.h"
38 #include "gdkprivate-x11.h"
39 #include "gdkscreen-x11.h"
40 #include "gdkdisplay-x11.h"
41
42 #include <gdk/gdkinternals.h>
43 #include "gdkalias.h"
44
45 typedef struct
46 {
47   gchar *color_string;
48   GdkColor color;
49   gint transparent;
50 } _GdkPixmapColor;
51
52 typedef struct
53 {
54   guint ncolors;
55   GdkColormap *colormap;
56   gulong pixels[1];
57 } _GdkPixmapInfo;
58
59 static void gdk_pixmap_impl_x11_get_size   (GdkDrawable        *drawable,
60                                             gint               *width,
61                                             gint               *height);
62
63 static void gdk_pixmap_impl_x11_dispose    (GObject            *object);
64 static void gdk_pixmap_impl_x11_finalize   (GObject            *object);
65
66 G_DEFINE_TYPE (GdkPixmapImplX11, gdk_pixmap_impl_x11, GDK_TYPE_DRAWABLE_IMPL_X11)
67
68 GType
69 _gdk_pixmap_impl_get_type (void)
70 {
71   return gdk_pixmap_impl_x11_get_type ();
72 }
73
74 static void
75 gdk_pixmap_impl_x11_init (GdkPixmapImplX11 *impl)
76 {
77   impl->width = 1;
78   impl->height = 1;
79 }
80
81 static void
82 gdk_pixmap_impl_x11_class_init (GdkPixmapImplX11Class *klass)
83 {
84   GObjectClass *object_class = G_OBJECT_CLASS (klass);
85   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
86   
87   object_class->dispose  = gdk_pixmap_impl_x11_dispose;
88   object_class->finalize = gdk_pixmap_impl_x11_finalize;
89
90   drawable_class->get_size = gdk_pixmap_impl_x11_get_size;
91 }
92
93 static void
94 gdk_pixmap_impl_x11_dispose (GObject *object)
95 {
96   GdkPixmapImplX11 *impl = GDK_PIXMAP_IMPL_X11 (object);
97   GdkPixmap *wrapper = GDK_PIXMAP (GDK_DRAWABLE_IMPL_X11 (impl)->wrapper);
98   GdkDisplay *display = GDK_PIXMAP_DISPLAY (wrapper);
99
100   if (!display->closed)
101     {
102       if (!impl->is_foreign)
103         XFreePixmap (GDK_DISPLAY_XDISPLAY (display), GDK_PIXMAP_XID (wrapper));
104     }
105
106   _gdk_xid_table_remove (display, GDK_PIXMAP_XID (wrapper));
107
108   G_OBJECT_CLASS (gdk_pixmap_impl_x11_parent_class)->dispose (object);
109 }
110
111 static void
112 gdk_pixmap_impl_x11_finalize (GObject *object)
113 {
114   GdkPixmapImplX11 *impl = GDK_PIXMAP_IMPL_X11 (object);
115   GdkPixmap *wrapper = GDK_PIXMAP (GDK_DRAWABLE_IMPL_X11 (impl)->wrapper);
116   GdkDisplay *display = GDK_PIXMAP_DISPLAY (wrapper);
117
118   if (!display->closed)
119     {
120       GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
121
122       _gdk_x11_drawable_finish (GDK_DRAWABLE (draw_impl));
123     }
124
125   G_OBJECT_CLASS (gdk_pixmap_impl_x11_parent_class)->finalize (object);
126 }
127
128 static void
129 gdk_pixmap_impl_x11_get_size   (GdkDrawable *drawable,
130                                 gint        *width,
131                                 gint        *height)
132 {
133   if (width)
134     *width = GDK_PIXMAP_IMPL_X11 (drawable)->width;
135   if (height)
136     *height = GDK_PIXMAP_IMPL_X11 (drawable)->height;
137 }
138
139 GdkPixmap*
140 _gdk_pixmap_new (GdkDrawable *drawable,
141                  gint         width,
142                  gint         height,
143                  gint         depth)
144 {
145   GdkPixmap *pixmap;
146   GdkDrawableImplX11 *draw_impl;
147   GdkPixmapImplX11 *pix_impl;
148   GdkColormap *cmap;
149   gint window_depth;
150   
151   g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
152   g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
153   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
154   
155   if (!drawable)
156     {
157       GDK_NOTE (MULTIHEAD, g_message ("need to specify the screen parent window "
158                                       "for gdk_pixmap_new() to be multihead safe"));
159       drawable = gdk_screen_get_root_window (gdk_screen_get_default ());
160     }
161
162   if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
163     return NULL;
164
165   window_depth = gdk_drawable_get_depth (GDK_DRAWABLE (drawable));
166   if (depth == -1)
167     depth = window_depth;
168
169   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
170   draw_impl = GDK_DRAWABLE_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
171   pix_impl = GDK_PIXMAP_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
172   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
173   
174   draw_impl->screen = GDK_WINDOW_SCREEN (drawable);
175   draw_impl->xid = XCreatePixmap (GDK_PIXMAP_XDISPLAY (pixmap),
176                                   GDK_WINDOW_XID (drawable),
177                                   width, height, depth);
178   
179   pix_impl->is_foreign = FALSE;
180   pix_impl->width = width;
181   pix_impl->height = height;
182   GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
183
184   if (depth == window_depth)
185     {
186       cmap = gdk_drawable_get_colormap (drawable);
187       if (cmap)
188         gdk_drawable_set_colormap (pixmap, cmap);
189     }
190   
191   _gdk_xid_table_insert (GDK_WINDOW_DISPLAY (drawable), 
192                          &GDK_PIXMAP_XID (pixmap), pixmap);
193   return pixmap;
194 }
195
196 GdkPixmap *
197 _gdk_bitmap_create_from_data (GdkDrawable *drawable,
198                               const gchar *data,
199                               gint         width,
200                               gint         height)
201 {
202   GdkPixmap *pixmap;
203   GdkDrawableImplX11 *draw_impl;
204   GdkPixmapImplX11 *pix_impl;
205   
206   g_return_val_if_fail (data != NULL, NULL);
207   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
208   g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
209
210   if (!drawable)
211     {
212       GDK_NOTE (MULTIHEAD, g_message ("need to specify the screen parent window "
213                                      "for gdk_bitmap_create_from_data() to be multihead safe"));
214       drawable = gdk_screen_get_root_window (gdk_screen_get_default ());
215     }
216   
217   if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
218     return NULL;
219
220   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
221   draw_impl = GDK_DRAWABLE_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
222   pix_impl = GDK_PIXMAP_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
223   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
224
225   pix_impl->is_foreign = FALSE;
226   pix_impl->width = width;
227   pix_impl->height = height;
228   GDK_PIXMAP_OBJECT (pixmap)->depth = 1;
229
230   draw_impl->screen = GDK_WINDOW_SCREEN (drawable);
231   draw_impl->xid = XCreateBitmapFromData (GDK_WINDOW_XDISPLAY (drawable),
232                                           GDK_WINDOW_XID (drawable),
233                                           (char *)data, width, height);
234
235   _gdk_xid_table_insert (GDK_WINDOW_DISPLAY (drawable), 
236                          &GDK_PIXMAP_XID (pixmap), pixmap);
237   return pixmap;
238 }
239
240 GdkPixmap*
241 _gdk_pixmap_create_from_data (GdkDrawable    *drawable,
242                               const gchar    *data,
243                               gint            width,
244                               gint            height,
245                               gint            depth,
246                               const GdkColor *fg,
247                               const GdkColor *bg)
248 {
249   GdkPixmap *pixmap;
250   GdkDrawableImplX11 *draw_impl;
251   GdkPixmapImplX11 *pix_impl;
252
253   g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
254   g_return_val_if_fail (data != NULL, NULL);
255   g_return_val_if_fail (fg != NULL, NULL);
256   g_return_val_if_fail (bg != NULL, NULL);
257   g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
258   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
259
260   if (!drawable)
261     {
262       GDK_NOTE (MULTIHEAD, g_message ("need to specify the screen parent window"
263                                       "for gdk_pixmap_create_from_data() to be multihead safe"));
264       drawable = gdk_screen_get_root_window (gdk_screen_get_default ());
265     }
266
267   if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
268     return NULL;
269
270   if (depth == -1)
271     depth = gdk_drawable_get_visual (drawable)->depth;
272
273   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
274   draw_impl = GDK_DRAWABLE_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
275   pix_impl = GDK_PIXMAP_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
276   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
277   
278   pix_impl->is_foreign = FALSE;
279   pix_impl->width = width;
280   pix_impl->height = height;
281   GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
282
283   draw_impl->screen = GDK_DRAWABLE_SCREEN (drawable);
284   draw_impl->xid = XCreatePixmapFromBitmapData (GDK_WINDOW_XDISPLAY (drawable),
285                                                 GDK_WINDOW_XID (drawable),
286                                                 (char *)data, width, height,
287                                                 fg->pixel, bg->pixel, depth);
288
289   _gdk_xid_table_insert (GDK_WINDOW_DISPLAY (drawable),
290                          &GDK_PIXMAP_XID (pixmap), pixmap);
291   return pixmap;
292 }
293
294 /**
295  * gdk_pixmap_foreign_new_for_display:
296  * @display: The #GdkDisplay where @anid is located.
297  * @anid: a native pixmap handle.
298  * 
299  * Wraps a native pixmap in a #GdkPixmap.
300  * This may fail if the pixmap has been destroyed.
301  *
302  * For example in the X backend, a native pixmap handle is an Xlib
303  * <type>XID</type>.
304  *
305  * Return value: the newly-created #GdkPixmap wrapper for the 
306  *    native pixmap or %NULL if the pixmap has been destroyed.
307  *
308  * Since: 2.2
309  **/
310 GdkPixmap *
311 gdk_pixmap_foreign_new_for_display (GdkDisplay      *display,
312                                     GdkNativeWindow  anid)
313 {
314   Pixmap xpixmap;
315   Window root_return;
316   GdkScreen *screen;
317   int x_ret, y_ret;
318   unsigned int w_ret, h_ret, bw_ret, depth_ret;
319
320   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
321
322   /* check to make sure we were passed something at
323    * least a little sane */
324   g_return_val_if_fail ((anid != 0), NULL);
325   
326   /* set the pixmap to the passed in value */
327   xpixmap = anid;
328
329   /* get information about the Pixmap to fill in the structure for
330      the gdk window */
331   if (!XGetGeometry (GDK_DISPLAY_XDISPLAY (display),
332                      xpixmap, &root_return,
333                      &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
334     return NULL;
335   
336   screen = _gdk_x11_display_screen_for_xrootwin (display, root_return);
337   return gdk_pixmap_foreign_new_for_screen (screen, anid, w_ret, h_ret, depth_ret);
338 }
339
340 /**
341  * gdk_pixmap_foreign_new_for_screen:
342  * @screen: a #GdkScreen
343  * @anid: a native pixmap handle
344  * @width: the width of the pixmap identified by @anid
345  * @height: the height of the pixmap identified by @anid
346  * @depth: the depth of the pixmap identified by @anid
347  *
348  * Wraps a native pixmap in a #GdkPixmap.
349  * This may fail if the pixmap has been destroyed.
350  *
351  * For example in the X backend, a native pixmap handle is an Xlib
352  * <type>XID</type>.
353  *
354  * This function is an alternative to gdk_pixmap_foreign_new_for_display()
355  * for cases where the dimensions of the pixmap are known. For the X
356  * backend, this avoids a roundtrip to the server.
357  *
358  * Return value: the newly-created #GdkPixmap wrapper for the 
359  *    native pixmap or %NULL if the pixmap has been destroyed.
360  * 
361  * Since: 2.10
362  */
363 GdkPixmap *
364 gdk_pixmap_foreign_new_for_screen (GdkScreen       *screen,
365                                    GdkNativeWindow  anid,
366                                    gint             width,
367                                    gint             height,
368                                    gint             depth)
369 {
370   Pixmap xpixmap;
371   GdkPixmap *pixmap;
372   GdkDrawableImplX11 *draw_impl;
373   GdkPixmapImplX11 *pix_impl;
374
375   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
376   g_return_val_if_fail (anid != 0, NULL);
377   g_return_val_if_fail (width > 0, NULL);
378   g_return_val_if_fail (height > 0, NULL);
379   g_return_val_if_fail (depth > 0, NULL);
380
381   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
382   draw_impl = GDK_DRAWABLE_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
383   pix_impl = GDK_PIXMAP_IMPL_X11 (GDK_PIXMAP_OBJECT (pixmap)->impl);
384   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
385
386   xpixmap = anid;
387   
388   draw_impl->screen = screen;
389   draw_impl->xid = xpixmap;
390
391   pix_impl->is_foreign = TRUE;
392   pix_impl->width = width;
393   pix_impl->height = height;
394   GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
395   
396   _gdk_xid_table_insert (gdk_screen_get_display (screen), 
397                          &GDK_PIXMAP_XID (pixmap), pixmap);
398
399   return pixmap;
400 }
401
402 /**
403  * gdk_pixmap_foreign_new:
404  * @anid: a native pixmap handle.
405  * 
406  * Wraps a native window for the default display in a #GdkPixmap.
407  * This may fail if the pixmap has been destroyed.
408  *
409  * For example in the X backend, a native pixmap handle is an Xlib
410  * <type>XID</type>.
411  *
412  * Return value: the newly-created #GdkPixmap wrapper for the 
413  *    native pixmap or %NULL if the pixmap has been destroyed.
414  **/
415 GdkPixmap*
416 gdk_pixmap_foreign_new (GdkNativeWindow anid)
417 {
418    return gdk_pixmap_foreign_new_for_display (gdk_display_get_default (), anid);
419 }
420
421 /**
422  * gdk_pixmap_lookup:
423  * @anid: a native pixmap handle.
424  * 
425  * Looks up the #GdkPixmap that wraps the given native pixmap handle.
426  *
427  * For example in the X backend, a native pixmap handle is an Xlib
428  * <type>XID</type>.
429  *
430  * Return value: the #GdkWindow wrapper for the native window,
431  *    or %NULL if there is none.
432  **/
433 GdkPixmap*
434 gdk_pixmap_lookup (GdkNativeWindow anid)
435 {
436   return (GdkPixmap*) gdk_xid_table_lookup_for_display (gdk_display_get_default (), anid);
437 }
438
439 /**
440  * gdk_pixmap_lookup_for_display:
441  * @display: the #GdkDisplay associated with @anid
442  * @anid: a native pixmap handle.
443  * 
444  * Looks up the #GdkPixmap that wraps the given native pixmap handle.
445  *
446  * For example in the X backend, a native pixmap handle is an Xlib
447  * <type>XID</type>.
448  *
449  * Return value: the #GdkPixmap wrapper for the native pixmap,
450  *    or %NULL if there is none.
451  *
452  * Since: 2.2
453  **/
454 GdkPixmap*
455 gdk_pixmap_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
456 {
457   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
458   return (GdkPixmap*) gdk_xid_table_lookup_for_display (display, anid);
459 }
460
461 #define __GDK_PIXMAP_X11_C__
462 #include  "gdkaliasdef.c"