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

source code of gtk/gdk/x11/gdkproperty-x11.c