]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkproperty-x11.c
If window == NULL, assume the root window. (restoring the behaviour that
[~andy/gtk] / gdk / x11 / gdkproperty-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 <X11/Xlib.h>
28 #include <X11/Xatom.h>
29 #include <string.h>
30
31 #include "gdkx.h"
32 #include "gdkproperty.h"
33 #include "gdkprivate.h"
34
35 GdkAtom
36 gdk_atom_intern (const gchar *atom_name,
37                  gboolean     only_if_exists)
38 {
39   GdkAtom retval;
40   static GHashTable *atom_hash = NULL;
41   
42   g_return_val_if_fail (atom_name != NULL, GDK_NONE);
43
44   if (!atom_hash)
45     atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
46
47   retval = GPOINTER_TO_UINT (g_hash_table_lookup (atom_hash, atom_name));
48   if (!retval)
49     {
50       retval = XInternAtom (gdk_display, atom_name, only_if_exists);
51
52       if (retval != None)
53         g_hash_table_insert (atom_hash, 
54                              g_strdup (atom_name), 
55                              GUINT_TO_POINTER (retval));
56     }
57
58   return retval;
59 }
60
61 gchar*
62 gdk_atom_name (GdkAtom atom)
63 {
64   gchar *t;
65   gchar *name;
66   gint old_error_warnings;
67
68   /* If this atom doesn't exist, we'll die with an X error unless
69      we take precautions */
70
71   old_error_warnings = gdk_error_warnings;
72   gdk_error_warnings = 0;
73   gdk_error_code = 0;
74   t = XGetAtomName (gdk_display, atom);
75   gdk_error_warnings = old_error_warnings;
76
77   if (gdk_error_code)
78     {
79       if (t)
80         XFree (t);
81
82       return NULL;
83     }
84   else
85     {
86       name = g_strdup (t);
87       if (t)
88         XFree (t);
89       
90       return name;
91     }
92 }
93
94 gboolean
95 gdk_property_get (GdkWindow   *window,
96                   GdkAtom      property,
97                   GdkAtom      type,
98                   gulong       offset,
99                   gulong       length,
100                   gint         pdelete,
101                   GdkAtom     *actual_property_type,
102                   gint        *actual_format_type,
103                   gint        *actual_length,
104                   guchar     **data)
105 {
106   Display *xdisplay;
107   Window xwindow;
108   Atom ret_prop_type;
109   gint ret_format;
110   gulong ret_nitems;
111   gulong ret_bytes_after;
112   gulong ret_length;
113   guchar *ret_data;
114
115   g_return_val_if_fail (!window || GDK_IS_WINDOW (window), FALSE);
116
117   if (window)
118     {
119       if (GDK_WINDOW_DESTROYED (window))
120         return FALSE;
121
122       xdisplay = GDK_WINDOW_XDISPLAY (window);
123       xwindow = GDK_WINDOW_XID (window);
124     }
125   else
126     {
127       xdisplay = gdk_display;
128       xwindow = gdk_root_window;
129     }
130
131   ret_data = NULL;
132   XGetWindowProperty (xdisplay, xwindow, property,
133                       offset, (length + 3) / 4, pdelete,
134                       type, &ret_prop_type, &ret_format,
135                       &ret_nitems, &ret_bytes_after,
136                       &ret_data);
137
138   if ((ret_prop_type == None) && (ret_format == 0)) {
139     return FALSE;
140   }
141
142   if (actual_property_type)
143     *actual_property_type = ret_prop_type;
144   if (actual_format_type)
145     *actual_format_type = ret_format;
146
147   if ((type != AnyPropertyType) && (ret_prop_type != type))
148     {
149       gchar *rn, *pn;
150
151       XFree (ret_data);
152       rn = gdk_atom_name(ret_prop_type);
153       pn = gdk_atom_name(type);
154       g_warning("Couldn't match property type %s to %s\n", rn, pn);
155       g_free(rn); g_free(pn);
156       return FALSE;
157     }
158
159   /* FIXME: ignoring bytes_after could have very bad effects */
160
161   if (data)
162     {
163       switch (ret_format)
164         {
165         case 8:
166           ret_length = ret_nitems;
167           break;
168         case 16:
169           ret_length = sizeof(short) * ret_nitems;
170           break;
171         case 32:
172           ret_length = sizeof(long) * ret_nitems;
173           break;
174         default:
175           g_warning ("unknown property return format: %d", ret_format);
176           XFree (ret_data);
177           return FALSE;
178         }
179
180       *data = g_new (guchar, ret_length);
181       memcpy (*data, ret_data, ret_length);
182       if (actual_length)
183         *actual_length = ret_length;
184     }
185
186   XFree (ret_data);
187
188   return TRUE;
189 }
190
191 void
192 gdk_property_change (GdkWindow    *window,
193                      GdkAtom       property,
194                      GdkAtom       type,
195                      gint          format,
196                      GdkPropMode   mode,
197                      const guchar *data,
198                      gint          nelements)
199 {
200   Display *xdisplay;
201   Window xwindow;
202
203   g_return_if_fail (!window || GDK_IS_WINDOW (window));
204
205   if (window)
206     {
207       if (GDK_WINDOW_DESTROYED (window))
208         return;
209
210       xdisplay = GDK_WINDOW_XDISPLAY (window);
211       xwindow = GDK_WINDOW_XID (window);
212     }
213   else
214     {
215       xdisplay = gdk_display;
216       xwindow = gdk_root_window;
217     }
218
219   XChangeProperty (xdisplay, xwindow, property, type,
220                    format, mode, (guchar *)data, nelements);
221 }
222
223 void
224 gdk_property_delete (GdkWindow *window,
225                      GdkAtom    property)
226 {
227   Display *xdisplay;
228   Window xwindow;
229
230   g_return_if_fail (!window || GDK_IS_WINDOW (window));
231
232   if (window)
233     {
234       if (GDK_WINDOW_DESTROYED (window))
235         return;
236
237       xdisplay = GDK_WINDOW_XDISPLAY (window);
238       xwindow = GDK_WINDOW_XID (window);
239     }
240   else
241     {
242       xdisplay = gdk_display;
243       xwindow = gdk_root_window;
244     }
245
246   XDeleteProperty (xdisplay, xwindow, property);
247 }