xref: /aosp_15_r20/external/libxkbcommon/src/x11/util.c (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker /*
2*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2013 Ran Benita
3*2b949d04SAndroid Build Coastguard Worker  *
4*2b949d04SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*2b949d04SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*2b949d04SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*2b949d04SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*2b949d04SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*2b949d04SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*2b949d04SAndroid Build Coastguard Worker  *
11*2b949d04SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*2b949d04SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*2b949d04SAndroid Build Coastguard Worker  * Software.
14*2b949d04SAndroid Build Coastguard Worker  *
15*2b949d04SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*2b949d04SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*2b949d04SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*2b949d04SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*2b949d04SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*2b949d04SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*2b949d04SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*2b949d04SAndroid Build Coastguard Worker  */
23*2b949d04SAndroid Build Coastguard Worker 
24*2b949d04SAndroid Build Coastguard Worker #include "config.h"
25*2b949d04SAndroid Build Coastguard Worker 
26*2b949d04SAndroid Build Coastguard Worker #include "x11-priv.h"
27*2b949d04SAndroid Build Coastguard Worker 
28*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_x11_setup_xkb_extension(xcb_connection_t * conn,uint16_t major_xkb_version,uint16_t minor_xkb_version,enum xkb_x11_setup_xkb_extension_flags flags,uint16_t * major_xkb_version_out,uint16_t * minor_xkb_version_out,uint8_t * base_event_out,uint8_t * base_error_out)29*2b949d04SAndroid Build Coastguard Worker xkb_x11_setup_xkb_extension(xcb_connection_t *conn,
30*2b949d04SAndroid Build Coastguard Worker                             uint16_t major_xkb_version,
31*2b949d04SAndroid Build Coastguard Worker                             uint16_t minor_xkb_version,
32*2b949d04SAndroid Build Coastguard Worker                             enum xkb_x11_setup_xkb_extension_flags flags,
33*2b949d04SAndroid Build Coastguard Worker                             uint16_t *major_xkb_version_out,
34*2b949d04SAndroid Build Coastguard Worker                             uint16_t *minor_xkb_version_out,
35*2b949d04SAndroid Build Coastguard Worker                             uint8_t *base_event_out,
36*2b949d04SAndroid Build Coastguard Worker                             uint8_t *base_error_out)
37*2b949d04SAndroid Build Coastguard Worker {
38*2b949d04SAndroid Build Coastguard Worker     uint8_t base_event, base_error;
39*2b949d04SAndroid Build Coastguard Worker     uint16_t server_major, server_minor;
40*2b949d04SAndroid Build Coastguard Worker 
41*2b949d04SAndroid Build Coastguard Worker     if (flags & ~(XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS)) {
42*2b949d04SAndroid Build Coastguard Worker         /* log_err_func(ctx, "unrecognized flags: %#x\n", flags); */
43*2b949d04SAndroid Build Coastguard Worker         return 0;
44*2b949d04SAndroid Build Coastguard Worker     }
45*2b949d04SAndroid Build Coastguard Worker 
46*2b949d04SAndroid Build Coastguard Worker     {
47*2b949d04SAndroid Build Coastguard Worker         const xcb_query_extension_reply_t *reply =
48*2b949d04SAndroid Build Coastguard Worker             xcb_get_extension_data(conn, &xcb_xkb_id);
49*2b949d04SAndroid Build Coastguard Worker         if (!reply) {
50*2b949d04SAndroid Build Coastguard Worker             /* log_err_func(ctx, "failed to query for XKB extension\n"); */
51*2b949d04SAndroid Build Coastguard Worker             return 0;
52*2b949d04SAndroid Build Coastguard Worker         }
53*2b949d04SAndroid Build Coastguard Worker 
54*2b949d04SAndroid Build Coastguard Worker         if (!reply->present) {
55*2b949d04SAndroid Build Coastguard Worker             /* log_err_func(ctx, "failed to start using XKB extension: not available in server\n"); */
56*2b949d04SAndroid Build Coastguard Worker             return 0;
57*2b949d04SAndroid Build Coastguard Worker         }
58*2b949d04SAndroid Build Coastguard Worker 
59*2b949d04SAndroid Build Coastguard Worker         base_event = reply->first_event;
60*2b949d04SAndroid Build Coastguard Worker         base_error = reply->first_error;
61*2b949d04SAndroid Build Coastguard Worker     }
62*2b949d04SAndroid Build Coastguard Worker 
63*2b949d04SAndroid Build Coastguard Worker     {
64*2b949d04SAndroid Build Coastguard Worker         xcb_generic_error_t *error = NULL;
65*2b949d04SAndroid Build Coastguard Worker         xcb_xkb_use_extension_cookie_t cookie =
66*2b949d04SAndroid Build Coastguard Worker             xcb_xkb_use_extension(conn, major_xkb_version, minor_xkb_version);
67*2b949d04SAndroid Build Coastguard Worker         xcb_xkb_use_extension_reply_t *reply =
68*2b949d04SAndroid Build Coastguard Worker             xcb_xkb_use_extension_reply(conn, cookie, &error);
69*2b949d04SAndroid Build Coastguard Worker 
70*2b949d04SAndroid Build Coastguard Worker         if (!reply) {
71*2b949d04SAndroid Build Coastguard Worker             /* log_err_func(ctx, */
72*2b949d04SAndroid Build Coastguard Worker             /*              "failed to start using XKB extension: error code %d\n", */
73*2b949d04SAndroid Build Coastguard Worker             /*              error ? error->error_code : -1); */
74*2b949d04SAndroid Build Coastguard Worker             free(error);
75*2b949d04SAndroid Build Coastguard Worker             return 0;
76*2b949d04SAndroid Build Coastguard Worker         }
77*2b949d04SAndroid Build Coastguard Worker 
78*2b949d04SAndroid Build Coastguard Worker         if (!reply->supported) {
79*2b949d04SAndroid Build Coastguard Worker             /* log_err_func(ctx, */
80*2b949d04SAndroid Build Coastguard Worker             /*              "failed to start using XKB extension: server doesn't support version %d.%d\n", */
81*2b949d04SAndroid Build Coastguard Worker             /*              major_xkb_version, minor_xkb_version); */
82*2b949d04SAndroid Build Coastguard Worker             free(reply);
83*2b949d04SAndroid Build Coastguard Worker             return 0;
84*2b949d04SAndroid Build Coastguard Worker         }
85*2b949d04SAndroid Build Coastguard Worker 
86*2b949d04SAndroid Build Coastguard Worker         server_major = reply->serverMajor;
87*2b949d04SAndroid Build Coastguard Worker         server_minor = reply->serverMinor;
88*2b949d04SAndroid Build Coastguard Worker 
89*2b949d04SAndroid Build Coastguard Worker         free(reply);
90*2b949d04SAndroid Build Coastguard Worker     }
91*2b949d04SAndroid Build Coastguard Worker 
92*2b949d04SAndroid Build Coastguard Worker     /*
93*2b949d04SAndroid Build Coastguard Worker     * The XkbUseExtension() in libX11 has a *bunch* of legacy stuff, but
94*2b949d04SAndroid Build Coastguard Worker     * it doesn't seem like any of it is useful to us.
95*2b949d04SAndroid Build Coastguard Worker     */
96*2b949d04SAndroid Build Coastguard Worker 
97*2b949d04SAndroid Build Coastguard Worker     if (major_xkb_version_out)
98*2b949d04SAndroid Build Coastguard Worker         *major_xkb_version_out = server_major;
99*2b949d04SAndroid Build Coastguard Worker     if (minor_xkb_version_out)
100*2b949d04SAndroid Build Coastguard Worker         *minor_xkb_version_out = server_minor;
101*2b949d04SAndroid Build Coastguard Worker     if (base_event_out)
102*2b949d04SAndroid Build Coastguard Worker         *base_event_out = base_event;
103*2b949d04SAndroid Build Coastguard Worker     if (base_error_out)
104*2b949d04SAndroid Build Coastguard Worker         *base_error_out = base_error;
105*2b949d04SAndroid Build Coastguard Worker 
106*2b949d04SAndroid Build Coastguard Worker     return 1;
107*2b949d04SAndroid Build Coastguard Worker }
108*2b949d04SAndroid Build Coastguard Worker 
109*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int32_t
xkb_x11_get_core_keyboard_device_id(xcb_connection_t * conn)110*2b949d04SAndroid Build Coastguard Worker xkb_x11_get_core_keyboard_device_id(xcb_connection_t *conn)
111*2b949d04SAndroid Build Coastguard Worker {
112*2b949d04SAndroid Build Coastguard Worker     int32_t device_id;
113*2b949d04SAndroid Build Coastguard Worker     xcb_xkb_get_device_info_cookie_t cookie =
114*2b949d04SAndroid Build Coastguard Worker         xcb_xkb_get_device_info(conn, XCB_XKB_ID_USE_CORE_KBD,
115*2b949d04SAndroid Build Coastguard Worker                                 0, 0, 0, 0, 0, 0);
116*2b949d04SAndroid Build Coastguard Worker     xcb_xkb_get_device_info_reply_t *reply =
117*2b949d04SAndroid Build Coastguard Worker         xcb_xkb_get_device_info_reply(conn, cookie, NULL);
118*2b949d04SAndroid Build Coastguard Worker 
119*2b949d04SAndroid Build Coastguard Worker     if (!reply)
120*2b949d04SAndroid Build Coastguard Worker         return -1;
121*2b949d04SAndroid Build Coastguard Worker 
122*2b949d04SAndroid Build Coastguard Worker     device_id = reply->deviceID;
123*2b949d04SAndroid Build Coastguard Worker     free(reply);
124*2b949d04SAndroid Build Coastguard Worker     return device_id;
125*2b949d04SAndroid Build Coastguard Worker }
126*2b949d04SAndroid Build Coastguard Worker 
127*2b949d04SAndroid Build Coastguard Worker struct x11_atom_cache {
128*2b949d04SAndroid Build Coastguard Worker     /*
129*2b949d04SAndroid Build Coastguard Worker      * Invalidate the cache based on the XCB connection.
130*2b949d04SAndroid Build Coastguard Worker      * X11 atoms are actually not per connection or client, but per X server
131*2b949d04SAndroid Build Coastguard Worker      * session. But better be safe just in case we survive an X server restart.
132*2b949d04SAndroid Build Coastguard Worker      */
133*2b949d04SAndroid Build Coastguard Worker     xcb_connection_t *conn;
134*2b949d04SAndroid Build Coastguard Worker     struct {
135*2b949d04SAndroid Build Coastguard Worker         xcb_atom_t from;
136*2b949d04SAndroid Build Coastguard Worker         xkb_atom_t to;
137*2b949d04SAndroid Build Coastguard Worker     } cache[256];
138*2b949d04SAndroid Build Coastguard Worker     size_t len;
139*2b949d04SAndroid Build Coastguard Worker };
140*2b949d04SAndroid Build Coastguard Worker 
141*2b949d04SAndroid Build Coastguard Worker static struct x11_atom_cache *
get_cache(struct xkb_context * ctx,xcb_connection_t * conn)142*2b949d04SAndroid Build Coastguard Worker get_cache(struct xkb_context *ctx, xcb_connection_t *conn)
143*2b949d04SAndroid Build Coastguard Worker {
144*2b949d04SAndroid Build Coastguard Worker     if (!ctx->x11_atom_cache) {
145*2b949d04SAndroid Build Coastguard Worker         ctx->x11_atom_cache = calloc(1, sizeof(struct x11_atom_cache));
146*2b949d04SAndroid Build Coastguard Worker     }
147*2b949d04SAndroid Build Coastguard Worker     /* Can be NULL in case the malloc failed. */
148*2b949d04SAndroid Build Coastguard Worker     struct x11_atom_cache *cache = ctx->x11_atom_cache;
149*2b949d04SAndroid Build Coastguard Worker     if (cache && cache->conn != conn) {
150*2b949d04SAndroid Build Coastguard Worker         cache->conn = conn;
151*2b949d04SAndroid Build Coastguard Worker         cache->len = 0;
152*2b949d04SAndroid Build Coastguard Worker     }
153*2b949d04SAndroid Build Coastguard Worker     return cache;
154*2b949d04SAndroid Build Coastguard Worker }
155*2b949d04SAndroid Build Coastguard Worker 
156*2b949d04SAndroid Build Coastguard Worker void
x11_atom_interner_init(struct x11_atom_interner * interner,struct xkb_context * ctx,xcb_connection_t * conn)157*2b949d04SAndroid Build Coastguard Worker x11_atom_interner_init(struct x11_atom_interner *interner,
158*2b949d04SAndroid Build Coastguard Worker                        struct xkb_context *ctx, xcb_connection_t *conn)
159*2b949d04SAndroid Build Coastguard Worker {
160*2b949d04SAndroid Build Coastguard Worker     interner->had_error = false;
161*2b949d04SAndroid Build Coastguard Worker     interner->ctx = ctx;
162*2b949d04SAndroid Build Coastguard Worker     interner->conn = conn;
163*2b949d04SAndroid Build Coastguard Worker     interner->num_pending = 0;
164*2b949d04SAndroid Build Coastguard Worker     interner->num_copies = 0;
165*2b949d04SAndroid Build Coastguard Worker     interner->num_escaped = 0;
166*2b949d04SAndroid Build Coastguard Worker }
167*2b949d04SAndroid Build Coastguard Worker 
168*2b949d04SAndroid Build Coastguard Worker void
x11_atom_interner_adopt_atom(struct x11_atom_interner * interner,const xcb_atom_t atom,xkb_atom_t * out)169*2b949d04SAndroid Build Coastguard Worker x11_atom_interner_adopt_atom(struct x11_atom_interner *interner,
170*2b949d04SAndroid Build Coastguard Worker                              const xcb_atom_t atom, xkb_atom_t *out)
171*2b949d04SAndroid Build Coastguard Worker {
172*2b949d04SAndroid Build Coastguard Worker     *out = XKB_ATOM_NONE;
173*2b949d04SAndroid Build Coastguard Worker 
174*2b949d04SAndroid Build Coastguard Worker     if (atom == XCB_ATOM_NONE)
175*2b949d04SAndroid Build Coastguard Worker         return;
176*2b949d04SAndroid Build Coastguard Worker 
177*2b949d04SAndroid Build Coastguard Worker     /* Can be NULL in case the malloc failed. */
178*2b949d04SAndroid Build Coastguard Worker     struct x11_atom_cache *cache = get_cache(interner->ctx, interner->conn);
179*2b949d04SAndroid Build Coastguard Worker 
180*2b949d04SAndroid Build Coastguard Worker retry:
181*2b949d04SAndroid Build Coastguard Worker 
182*2b949d04SAndroid Build Coastguard Worker     /* Already in the cache? */
183*2b949d04SAndroid Build Coastguard Worker     if (cache) {
184*2b949d04SAndroid Build Coastguard Worker         for (size_t c = 0; c < cache->len; c++) {
185*2b949d04SAndroid Build Coastguard Worker             if (cache->cache[c].from == atom) {
186*2b949d04SAndroid Build Coastguard Worker                 *out = cache->cache[c].to;
187*2b949d04SAndroid Build Coastguard Worker                 return;
188*2b949d04SAndroid Build Coastguard Worker             }
189*2b949d04SAndroid Build Coastguard Worker         }
190*2b949d04SAndroid Build Coastguard Worker     }
191*2b949d04SAndroid Build Coastguard Worker 
192*2b949d04SAndroid Build Coastguard Worker     /* Already pending? */
193*2b949d04SAndroid Build Coastguard Worker     for (size_t i = 0; i < interner->num_pending; i++) {
194*2b949d04SAndroid Build Coastguard Worker         if (interner->pending[i].from == atom) {
195*2b949d04SAndroid Build Coastguard Worker             if (interner->num_copies == ARRAY_SIZE(interner->copies)) {
196*2b949d04SAndroid Build Coastguard Worker                 x11_atom_interner_round_trip(interner);
197*2b949d04SAndroid Build Coastguard Worker                 goto retry;
198*2b949d04SAndroid Build Coastguard Worker             }
199*2b949d04SAndroid Build Coastguard Worker 
200*2b949d04SAndroid Build Coastguard Worker             size_t idx = interner->num_copies++;
201*2b949d04SAndroid Build Coastguard Worker             interner->copies[idx].from = atom;
202*2b949d04SAndroid Build Coastguard Worker             interner->copies[idx].out = out;
203*2b949d04SAndroid Build Coastguard Worker             return;
204*2b949d04SAndroid Build Coastguard Worker         }
205*2b949d04SAndroid Build Coastguard Worker     }
206*2b949d04SAndroid Build Coastguard Worker 
207*2b949d04SAndroid Build Coastguard Worker     /* We have to send a GetAtomName request */
208*2b949d04SAndroid Build Coastguard Worker     if (interner->num_pending == ARRAY_SIZE(interner->pending)) {
209*2b949d04SAndroid Build Coastguard Worker         x11_atom_interner_round_trip(interner);
210*2b949d04SAndroid Build Coastguard Worker         assert(interner->num_pending < ARRAY_SIZE(interner->pending));
211*2b949d04SAndroid Build Coastguard Worker     }
212*2b949d04SAndroid Build Coastguard Worker     size_t idx = interner->num_pending++;
213*2b949d04SAndroid Build Coastguard Worker     interner->pending[idx].from = atom;
214*2b949d04SAndroid Build Coastguard Worker     interner->pending[idx].out = out;
215*2b949d04SAndroid Build Coastguard Worker     interner->pending[idx].cookie = xcb_get_atom_name(interner->conn, atom);
216*2b949d04SAndroid Build Coastguard Worker }
217*2b949d04SAndroid Build Coastguard Worker 
218*2b949d04SAndroid Build Coastguard Worker void
x11_atom_interner_round_trip(struct x11_atom_interner * interner)219*2b949d04SAndroid Build Coastguard Worker x11_atom_interner_round_trip(struct x11_atom_interner *interner) {
220*2b949d04SAndroid Build Coastguard Worker     struct xkb_context *ctx = interner->ctx;
221*2b949d04SAndroid Build Coastguard Worker     xcb_connection_t *conn = interner->conn;
222*2b949d04SAndroid Build Coastguard Worker 
223*2b949d04SAndroid Build Coastguard Worker     /* Can be NULL in case the malloc failed. */
224*2b949d04SAndroid Build Coastguard Worker     struct x11_atom_cache *cache = get_cache(ctx, conn);
225*2b949d04SAndroid Build Coastguard Worker 
226*2b949d04SAndroid Build Coastguard Worker     for (size_t i = 0; i < interner->num_pending; i++) {
227*2b949d04SAndroid Build Coastguard Worker         xcb_get_atom_name_reply_t *reply;
228*2b949d04SAndroid Build Coastguard Worker 
229*2b949d04SAndroid Build Coastguard Worker         reply = xcb_get_atom_name_reply(conn, interner->pending[i].cookie, NULL);
230*2b949d04SAndroid Build Coastguard Worker         if (!reply) {
231*2b949d04SAndroid Build Coastguard Worker             interner->had_error = true;
232*2b949d04SAndroid Build Coastguard Worker             continue;
233*2b949d04SAndroid Build Coastguard Worker         }
234*2b949d04SAndroid Build Coastguard Worker         xcb_atom_t x11_atom = interner->pending[i].from;
235*2b949d04SAndroid Build Coastguard Worker         xkb_atom_t atom = xkb_atom_intern(ctx,
236*2b949d04SAndroid Build Coastguard Worker                                           xcb_get_atom_name_name(reply),
237*2b949d04SAndroid Build Coastguard Worker                                           xcb_get_atom_name_name_length(reply));
238*2b949d04SAndroid Build Coastguard Worker         free(reply);
239*2b949d04SAndroid Build Coastguard Worker 
240*2b949d04SAndroid Build Coastguard Worker         if (cache && cache->len < ARRAY_SIZE(cache->cache)) {
241*2b949d04SAndroid Build Coastguard Worker             size_t idx = cache->len++;
242*2b949d04SAndroid Build Coastguard Worker             cache->cache[idx].from = x11_atom;
243*2b949d04SAndroid Build Coastguard Worker             cache->cache[idx].to = atom;
244*2b949d04SAndroid Build Coastguard Worker         }
245*2b949d04SAndroid Build Coastguard Worker 
246*2b949d04SAndroid Build Coastguard Worker         *interner->pending[i].out = atom;
247*2b949d04SAndroid Build Coastguard Worker 
248*2b949d04SAndroid Build Coastguard Worker         for (size_t j = 0; j < interner->num_copies; j++) {
249*2b949d04SAndroid Build Coastguard Worker             if (interner->copies[j].from == x11_atom)
250*2b949d04SAndroid Build Coastguard Worker                 *interner->copies[j].out = atom;
251*2b949d04SAndroid Build Coastguard Worker         }
252*2b949d04SAndroid Build Coastguard Worker     }
253*2b949d04SAndroid Build Coastguard Worker 
254*2b949d04SAndroid Build Coastguard Worker     for (size_t i = 0; i < interner->num_escaped; i++) {
255*2b949d04SAndroid Build Coastguard Worker         xcb_get_atom_name_reply_t *reply;
256*2b949d04SAndroid Build Coastguard Worker         int length;
257*2b949d04SAndroid Build Coastguard Worker         char *name;
258*2b949d04SAndroid Build Coastguard Worker         char **out = interner->escaped[i].out;
259*2b949d04SAndroid Build Coastguard Worker 
260*2b949d04SAndroid Build Coastguard Worker         reply = xcb_get_atom_name_reply(conn, interner->escaped[i].cookie, NULL);
261*2b949d04SAndroid Build Coastguard Worker         *interner->escaped[i].out = NULL;
262*2b949d04SAndroid Build Coastguard Worker         if (!reply) {
263*2b949d04SAndroid Build Coastguard Worker             interner->had_error = true;
264*2b949d04SAndroid Build Coastguard Worker         } else {
265*2b949d04SAndroid Build Coastguard Worker             length = xcb_get_atom_name_name_length(reply);
266*2b949d04SAndroid Build Coastguard Worker             name = xcb_get_atom_name_name(reply);
267*2b949d04SAndroid Build Coastguard Worker 
268*2b949d04SAndroid Build Coastguard Worker             *out = strndup(name, length);
269*2b949d04SAndroid Build Coastguard Worker             free(reply);
270*2b949d04SAndroid Build Coastguard Worker             if (*out == NULL) {
271*2b949d04SAndroid Build Coastguard Worker                 interner->had_error = true;
272*2b949d04SAndroid Build Coastguard Worker             } else {
273*2b949d04SAndroid Build Coastguard Worker                 XkbEscapeMapName(*out);
274*2b949d04SAndroid Build Coastguard Worker             }
275*2b949d04SAndroid Build Coastguard Worker         }
276*2b949d04SAndroid Build Coastguard Worker     }
277*2b949d04SAndroid Build Coastguard Worker 
278*2b949d04SAndroid Build Coastguard Worker     interner->num_pending = 0;
279*2b949d04SAndroid Build Coastguard Worker     interner->num_copies = 0;
280*2b949d04SAndroid Build Coastguard Worker     interner->num_escaped = 0;
281*2b949d04SAndroid Build Coastguard Worker }
282*2b949d04SAndroid Build Coastguard Worker 
283*2b949d04SAndroid Build Coastguard Worker void
x11_atom_interner_get_escaped_atom_name(struct x11_atom_interner * interner,xcb_atom_t atom,char ** out)284*2b949d04SAndroid Build Coastguard Worker x11_atom_interner_get_escaped_atom_name(struct x11_atom_interner *interner,
285*2b949d04SAndroid Build Coastguard Worker                                         xcb_atom_t atom, char **out)
286*2b949d04SAndroid Build Coastguard Worker {
287*2b949d04SAndroid Build Coastguard Worker     if (atom == 0) {
288*2b949d04SAndroid Build Coastguard Worker         *out = NULL;
289*2b949d04SAndroid Build Coastguard Worker         return;
290*2b949d04SAndroid Build Coastguard Worker     }
291*2b949d04SAndroid Build Coastguard Worker     size_t idx = interner->num_escaped++;
292*2b949d04SAndroid Build Coastguard Worker     /* There can only be a fixed number of calls to this function "in-flight",
293*2b949d04SAndroid Build Coastguard Worker      * thus we assert this number. Increase the array size if this assert fails.
294*2b949d04SAndroid Build Coastguard Worker      */
295*2b949d04SAndroid Build Coastguard Worker     assert(idx < ARRAY_SIZE(interner->escaped));
296*2b949d04SAndroid Build Coastguard Worker     interner->escaped[idx].out = out;
297*2b949d04SAndroid Build Coastguard Worker     interner->escaped[idx].cookie = xcb_get_atom_name(interner->conn, atom);
298*2b949d04SAndroid Build Coastguard Worker }
299