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 | |
35 | static void |
36 | insert_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 | |
54 | static Atom |
55 | lookup_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 | **/ |
77 | Atom |
78 | gdk_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 | |
102 | void |
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 | **/ |
149 | const char * |
150 | gdk_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 | |
197 | Atom |
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 | |