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, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25 #include "config.h"
26
27 #include "gdkinternals.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkdisplay-x11.h"
30 #include "gdkscreen-x11.h"
31
32 #include <X11/Xlib.h>
33 #include <X11/Xatom.h>
34 #include <string.h>
35
36 static void
insert_atom_pair(GdkDisplay * display,const char * string,Atom xatom)37 insert_atom_pair (GdkDisplay *display,
38 const char *string,
39 Atom xatom)
40 {
41 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
42 char *s;
43
44 if (!display_x11->atom_from_string)
45 {
46 display_x11->atom_from_string = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
47 display_x11->atom_to_string = g_hash_table_new (NULL, NULL);
48 }
49
50 s = g_strdup (string);
51 g_hash_table_insert (display_x11->atom_from_string, s, GUINT_TO_POINTER (xatom));
52 g_hash_table_insert (display_x11->atom_to_string, GUINT_TO_POINTER (xatom), s);
53 }
54
55 static Atom
lookup_cached_xatom(GdkDisplay * display,const char * string)56 lookup_cached_xatom (GdkDisplay *display,
57 const char *string)
58 {
59 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
60
61 if (display_x11->atom_from_string)
62 return GPOINTER_TO_UINT (g_hash_table_lookup (display_x11->atom_from_string, string));
63
64 return None;
65 }
66
67 /**
68 * gdk_x11_get_xatom_by_name_for_display:
69 * @display: (type GdkX11Display): a `GdkDisplay`
70 * @atom_name: a string
71 *
72 * Returns the X atom for a `GdkDisplay` corresponding to @atom_name.
73 * This function caches the result, so if called repeatedly it is much
74 * faster than XInternAtom(), which is a round trip to the server each time.
75 *
76 * Returns: a X atom for a `GdkDisplay`
77 **/
78 Atom
gdk_x11_get_xatom_by_name_for_display(GdkDisplay * display,const char * atom_name)79 gdk_x11_get_xatom_by_name_for_display (GdkDisplay *display,
80 const char *atom_name)
81 {
82 Atom xatom = None;
83
84 g_return_val_if_fail (GDK_IS_DISPLAY (display), None);
85
86 if (atom_name == NULL)
87 return None;
88
89 if (gdk_display_is_closed (display))
90 return None;
91
92 xatom = lookup_cached_xatom (display, atom_name);
93
94 if (!xatom)
95 {
96 xatom = XInternAtom (GDK_DISPLAY_XDISPLAY (display), atom_name, FALSE);
97 insert_atom_pair (display, atom_name, xatom);
98 }
99
100 return xatom;
101 }
102
103 void
_gdk_x11_precache_atoms(GdkDisplay * display,const char * const * atom_names,int n_atoms)104 _gdk_x11_precache_atoms (GdkDisplay *display,
105 const char * const *atom_names,
106 int n_atoms)
107 {
108 Atom *xatoms;
109 const char **xatom_names;
110 int n_xatoms;
111 int i;
112
113 xatoms = g_new (Atom, n_atoms);
114 xatom_names = g_new (const char *, n_atoms);
115
116 n_xatoms = 0;
117 for (i = 0; i < n_atoms; i++)
118 {
119 if (lookup_cached_xatom (display, atom_names[i]) == None)
120 {
121 xatom_names[n_xatoms] = atom_names[i];
122 n_xatoms++;
123 }
124 }
125
126 if (n_xatoms)
127 XInternAtoms (GDK_DISPLAY_XDISPLAY (display),
128 (char **) xatom_names, n_xatoms, False, xatoms);
129
130 for (i = 0; i < n_xatoms; i++)
131 insert_atom_pair (display, xatom_names[i], xatoms[i]);
132
133 g_free (xatoms);
134 g_free (xatom_names);
135 }
136
137 /**
138 * gdk_x11_get_xatom_name_for_display:
139 * @display: (type GdkX11Display): the `GdkDisplay` where @xatom is defined
140 * @xatom: an X atom
141 *
142 * Returns the name of an X atom for its display. This
143 * function is meant mainly for debugging, so for convenience, unlike
144 * XAtomName() and the result doesn’t need to
145 * be freed.
146 *
147 * Returns: name of the X atom; this string is owned by GDK,
148 * so it shouldn’t be modified or freed.
149 **/
150 const char *
gdk_x11_get_xatom_name_for_display(GdkDisplay * display,Atom xatom)151 gdk_x11_get_xatom_name_for_display (GdkDisplay *display,
152 Atom xatom)
153
154 {
155 GdkX11Display *display_x11;
156 const char *string;
157
158 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
159
160 if (xatom == None)
161 return NULL;
162
163 if (gdk_display_is_closed (display))
164 return NULL;
165
166 display_x11 = GDK_X11_DISPLAY (display);
167
168 if (display_x11->atom_to_string)
169 string = g_hash_table_lookup (display_x11->atom_to_string,
170 GUINT_TO_POINTER (xatom));
171 else
172 string = NULL;
173
174 if (!string)
175 {
176 /* If this atom doesn't exist, we'll die with an X error unless
177 * we take precautions
178 */
179 char *name;
180 gdk_x11_display_error_trap_push (display);
181 name = XGetAtomName (GDK_DISPLAY_XDISPLAY (display), xatom);
182 if (gdk_x11_display_error_trap_pop (display))
183 {
184 g_warning (G_STRLOC " invalid X atom: %ld", xatom);
185 }
186 else
187 {
188 insert_atom_pair (display, name, xatom);
189 XFree (name);
190 string = g_hash_table_lookup (display_x11->atom_to_string,
191 GUINT_TO_POINTER (xatom));
192 }
193 }
194
195 return string;
196 }
197
198 Atom
_gdk_x11_get_xatom_for_display_printf(GdkDisplay * display,const char * format,...)199 _gdk_x11_get_xatom_for_display_printf (GdkDisplay *display,
200 const char *format,
201 ...)
202 {
203 va_list args;
204 char *atom_name;
205 Atom atom;
206
207 va_start (args, format);
208 atom_name = g_strdup_vprintf (format, args);
209 va_end (args);
210
211 atom = gdk_x11_get_xatom_by_name_for_display (display, atom_name);
212
213 g_free (atom_name);
214
215 return atom;
216 }
217
218