Bug Summary

File:cdk/x11/cdkasync.c
Warning:line 142, column 27
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cdkasync.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/cdk/x11 -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -D G_LOG_DOMAIN="Cdk" -D G_LOG_USE_STRUCTURED=1 -D CDK_COMPILATION -I ../.. -I ../../cdk -I ../../cdk -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/cdk/x11 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-170037-43636-1 -x c cdkasync.c
1/* CTK - The GIMP Toolkit
2 * cdkasync.c: Utility functions using the Xlib asynchronous interfaces
3 * Copyright (C) 2003, Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18/* Portions of code in this file are based on code from Xlib
19 */
20/*
21Copyright 1986, 1998 The Open Group
22
23Permission to use, copy, modify, distribute, and sell this software and its
24documentation for any purpose is hereby granted without fee, provided that
25the above copyright notice appear in all copies and that both that
26copyright notice and this permission notice appear in supporting
27documentation.
28
29The above copyright notice and this permission notice shall be included in
30all copies or substantial portions of the Software.
31
32THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
36AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
37CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38
39Except as contained in this notice, the name of The Open Group shall not be
40used in advertising or otherwise to promote the sale, use or other dealings
41in this Software without prior written authorization from The Open Group.
42
43*/
44#include "config.h"
45
46#include "cdkasync.h"
47#include "cdkprivate-x11.h"
48
49#include <X11/Xlibint.h>
50
51
52typedef struct _ChildInfoChildState ChildInfoChildState;
53typedef struct _ChildInfoState ChildInfoState;
54typedef struct _ListChildrenState ListChildrenState;
55typedef struct _SendEventState SendEventState;
56typedef struct _SetInputFocusState SetInputFocusState;
57typedef struct _RoundtripState RoundtripState;
58
59typedef enum {
60 CHILD_INFO_GET_PROPERTY,
61 CHILD_INFO_GET_WA,
62 CHILD_INFO_GET_GEOMETRY
63} ChildInfoReq;
64
65struct _ChildInfoChildState
66{
67 gulong seq[3];
68};
69
70struct _ChildInfoState
71{
72 gboolean get_wm_state;
73 Window *children;
74 guint nchildren;
75 CdkChildInfoX11 *child_info;
76 ChildInfoChildState *child_states;
77
78 guint current_child;
79 guint n_children_found;
80 gint current_request;
81 gboolean have_error;
82 gboolean child_has_error;
83};
84
85struct _ListChildrenState
86{
87 Display *dpy;
88 gulong get_property_req;
89 gboolean have_error;
90 gboolean has_wm_state;
91};
92
93struct _SendEventState
94{
95 Display *dpy;
96 Window window;
97 _XAsyncHandler async;
98 gulong send_event_req;
99 gulong get_input_focus_req;
100 gboolean have_error;
101 CdkSendXEventCallback callback;
102 gpointer data;
103};
104
105struct _SetInputFocusState
106{
107 Display *dpy;
108 _XAsyncHandler async;
109 gulong set_input_focus_req;
110 gulong get_input_focus_req;
111};
112
113struct _RoundtripState
114{
115 Display *dpy;
116 _XAsyncHandler async;
117 gulong get_input_focus_req;
118 CdkDisplay *display;
119 CdkRoundTripCallback callback;
120 gpointer data;
121};
122
123static gboolean
124callback_idle (gpointer data)
125{
126 SendEventState *state = (SendEventState *)data;
127
128 state->callback (state->window, !state->have_error, state->data);
129
130 g_free (state);
131
132 return FALSE(0);
133}
134
135static Boolint
136send_event_handler (Display *dpy,
137 xReply *rep,
138 char *buf,
139 int len,
140 XPointer data)
141{
142 SendEventState *state = (SendEventState *)data;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
143
144 if (dpy->last_request_read == state->send_event_req)
145 {
146 if (rep->generic.type == X_Error0 &&
147 rep->error.errorCode == BadWindow3)
148 {
149 state->have_error = TRUE(!(0));
150 return True1;
151 }
152 }
153 else if (dpy->last_request_read == state->get_input_focus_req)
154 {
155 xGetInputFocusReply replbuf;
156 xGetInputFocusReply *repl G_GNUC_UNUSED__attribute__ ((__unused__));
157
158 if (rep->generic.type != X_Error0)
159 {
160 /* Actually does nothing, since there are no additional bytes
161 * to read, but maintain good form.
162 */
163 repl = (xGetInputFocusReply *)
164 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
165 (sizeof(xGetInputFocusReply) - sizeof(xReply)) >> 2,
166 True1);
167 }
168
169 if (state->callback)
170 {
171 guint id;
172 id = cdk_threads_add_idle (callback_idle, state);
173 g_source_set_name_by_id (id, "[ctk+] callback_idle");
174 }
175
176 DeqAsyncHandler(state->dpy, &state->async){ if (state->dpy->async_handlers == (&state->async
)) state->dpy->async_handlers = (&state->async)->
next; else _XDeqAsyncHandler(state->dpy, &state->async
); }
;
177
178 return (rep->generic.type != X_Error0);
179 }
180
181 return False0;
182}
183
184static void
185client_message_to_wire (XClientMessageEvent *ev,
186 xEvent *event)
187{
188 int i;
189 event->u.clientMessage.window = ev->window;
190 event->u.u.type = ev->type;
191 event->u.u.detail = ev->format;
192 switch (ev->format)
193 {
194 case 8:
195 event->u.clientMessage.u.b.type = ev->message_type;
196 for (i = 0; i < 20; i++)
197 event->u.clientMessage.u.b.bytes[i] = ev->data.b[i];
198 break;
199 case 16:
200 event->u.clientMessage.u.s.type = ev->message_type;
201 event->u.clientMessage.u.s.shorts0 = ev->data.s[0];
202 event->u.clientMessage.u.s.shorts1 = ev->data.s[1];
203 event->u.clientMessage.u.s.shorts2 = ev->data.s[2];
204 event->u.clientMessage.u.s.shorts3 = ev->data.s[3];
205 event->u.clientMessage.u.s.shorts4 = ev->data.s[4];
206 event->u.clientMessage.u.s.shorts5 = ev->data.s[5];
207 event->u.clientMessage.u.s.shorts6 = ev->data.s[6];
208 event->u.clientMessage.u.s.shorts7 = ev->data.s[7];
209 event->u.clientMessage.u.s.shorts8 = ev->data.s[8];
210 event->u.clientMessage.u.s.shorts9 = ev->data.s[9];
211 break;
212 case 32:
213 event->u.clientMessage.u.l.type = ev->message_type;
214 event->u.clientMessage.u.l.longs0 = ev->data.l[0];
215 event->u.clientMessage.u.l.longs1 = ev->data.l[1];
216 event->u.clientMessage.u.l.longs2 = ev->data.l[2];
217 event->u.clientMessage.u.l.longs3 = ev->data.l[3];
218 event->u.clientMessage.u.l.longs4 = ev->data.l[4];
219 break;
220 default:
221 /* client passing bogus data, let server complain */
222 break;
223 }
224}
225
226void
227_cdk_x11_send_client_message_async (CdkDisplay *display,
228 Window window,
229 gboolean propagate,
230 glong event_mask,
231 XClientMessageEvent *event_send,
232 CdkSendXEventCallback callback,
233 gpointer data)
234{
235 Display *dpy;
236 SendEventState *state;
237
238 dpy = CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
;
239
240 state = g_new (SendEventState, 1)((SendEventState *) g_malloc_n ((1), sizeof (SendEventState))
)
;
241
242 state->dpy = dpy;
243 state->window = window;
244 state->callback = callback;
245 state->data = data;
246 state->have_error = FALSE(0);
247
248 LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display
)(dpy)
;
249
250 state->async.next = dpy->async_handlers;
251 state->async.handler = send_event_handler;
252 state->async.data = (XPointer) state;
253 dpy->async_handlers = &state->async;
254
255 {
256 register xSendEventReq *req;
257 xEvent ev;
258
259 client_message_to_wire (event_send, &ev);
260
261 GetReq(SendEvent, req)req = (xSendEventReq *) _XGetRequest(dpy, 25, 44);
262 req->destination = window;
263 req->propagate = propagate;
264 req->eventMask = event_mask;
265 /* gross, matches Xproto.h */
266#ifdef WORD64
267 memcpy ((char *) req->eventdata, (char *) &ev, SIZEOF(xEvent)32);
268#else
269 memcpy ((char *) &req->event, (char *) &ev, SIZEOF(xEvent)32);
270#endif
271
272 state->send_event_req = dpy->request;
273 }
274
275 /*
276 * XSync (dpy, 0)
277 */
278 {
279 G_GNUC_UNUSED__attribute__ ((__unused__)) xReq *req;
280
281 GetEmptyReq(GetInputFocus, req)req = (xReq *) _XGetRequest(dpy, 43, 4);
282 state->get_input_focus_req = dpy->request;
283 }
284
285 UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display
)(dpy)
;
286 SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy);
287}
288
289static Boolint
290list_children_handler (Display *dpy,
291 xReply *rep,
292 char *buf,
293 int len,
294 XPointer data)
295{
296 ListChildrenState *state = (ListChildrenState *)data;
297
298 if (dpy->last_request_read != state->get_property_req)
299 return False0;
300
301 if (rep->generic.type == X_Error0)
302 {
303 state->have_error = TRUE(!(0));
304 return False0;
305 }
306 else
307 {
308 xGetPropertyReply replbuf;
309 xGetPropertyReply *repl;
310
311 repl = (xGetPropertyReply *)
312 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
313 (sizeof(xGetPropertyReply) - sizeof(xReply)) >> 2,
314 True1);
315
316 state->has_wm_state = repl->propertyType != None0L;
317 /* Since we called GetProperty with longLength of 0, we don't
318 * have to worry about consuming the property data that would
319 * normally follow after the reply
320 */
321
322 return True1;
323 }
324}
325
326static gboolean
327list_children_and_wm_state (Display *dpy,
328 Window w,
329 Atom wm_state_atom,
330 gboolean *has_wm_state,
331 Window **children,
332 unsigned int *nchildren)
333{
334 ListChildrenState state;
335 _XAsyncHandler async;
336 long nbytes;
337 xQueryTreeReply rep;
338 register xResourceReq *req;
339 xGetPropertyReq *prop_req;
340
341 LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display
)(dpy)
;
342
343 *children = NULL((void*)0);
344 *nchildren = 0;
345 *has_wm_state = FALSE(0);
346
347 state.have_error = FALSE(0);
348 state.has_wm_state = FALSE(0);
349
350 if (wm_state_atom)
351 {
352 async.next = dpy->async_handlers;
353 async.handler = list_children_handler;
354 async.data = (XPointer) &state;
355 dpy->async_handlers = &async;
356
357 GetReq (GetProperty, prop_req)prop_req = (xGetPropertyReq *) _XGetRequest(dpy, 20, 24);
358 prop_req->window = w;
359 prop_req->property = wm_state_atom;
360 prop_req->type = AnyPropertyType0L;
361 prop_req->delete = False0;
362 prop_req->longOffset = 0;
363 prop_req->longLength = 0;
364
365 state.get_property_req = dpy->request;
366 }
367
368 GetResReq(QueryTree, w, req)req = (xResourceReq *) _XGetRequest(dpy, 15, 8); if (req) req
->id = (w)
;
369 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse0))
370 {
371 state.have_error = TRUE(!(0));
372 goto out;
373 }
374
375 if (rep.nChildren != 0)
376 {
377 nbytes = rep.nChildren << 2;
378 if (state.have_error)
379 {
380 _XEatData(dpy, (unsigned long) nbytes);
381 goto out;
382 }
383 *children = g_new (Window, rep.nChildren)((Window *) g_malloc_n ((rep.nChildren), sizeof (Window)));
384 _XRead32 (dpy, (long *) *children, nbytes);
385 }
386
387 *nchildren = rep.nChildren;
388 *has_wm_state = state.has_wm_state;
389
390 out:
391 if (wm_state_atom)
392 DeqAsyncHandler(dpy, &async){ if (dpy->async_handlers == (&async)) dpy->async_handlers
= (&async)->next; else _XDeqAsyncHandler(dpy, &async
); }
;
393 UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display
)(dpy)
;
394 SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy);
395
396 return !state.have_error;
397}
398
399static void
400handle_get_wa_reply (Display *dpy G_GNUC_UNUSED__attribute__ ((__unused__)),
401 ChildInfoState *state,
402 xGetWindowAttributesReply *repl)
403{
404 CdkChildInfoX11 *child = &state->child_info[state->n_children_found];
405 child->is_mapped = repl->mapState != IsUnmapped0;
406 child->window_class = repl->class;
407}
408
409static void
410handle_get_geometry_reply (Display *dpy G_GNUC_UNUSED__attribute__ ((__unused__)),
411 ChildInfoState *state,
412 xGetGeometryReply *repl)
413{
414 CdkChildInfoX11 *child = &state->child_info[state->n_children_found];
415
416 child->x = cvtINT16toInt (repl->x)(repl->x);
417 child->y = cvtINT16toInt (repl->y)(repl->y);
418 child->width = repl->width;
419 child->height = repl->height;
420}
421
422static void
423handle_get_property_reply (Display *dpy G_GNUC_UNUSED__attribute__ ((__unused__)),
424 ChildInfoState *state,
425 xGetPropertyReply *repl)
426{
427 CdkChildInfoX11 *child = &state->child_info[state->n_children_found];
428 child->has_wm_state = repl->propertyType != None0L;
429
430 /* Since we called GetProperty with longLength of 0, we don't
431 * have to worry about consuming the property data that would
432 * normally follow after the reply
433 */
434}
435
436static void
437next_child (ChildInfoState *state)
438{
439 if (state->current_request == CHILD_INFO_GET_GEOMETRY)
440 {
441 if (!state->have_error && !state->child_has_error)
442 {
443 state->child_info[state->n_children_found].window = state->children[state->current_child];
444 state->n_children_found++;
445 }
446 state->current_child++;
447 if (state->get_wm_state)
448 state->current_request = CHILD_INFO_GET_PROPERTY;
449 else
450 state->current_request = CHILD_INFO_GET_WA;
451 state->child_has_error = FALSE(0);
452 state->have_error = FALSE(0);
453 }
454 else
455 state->current_request++;
456}
457
458static Boolint
459get_child_info_handler (Display *dpy,
460 xReply *rep,
461 char *buf,
462 int len,
463 XPointer data)
464{
465 Boolint result = True1;
466
467 ChildInfoState *state = (ChildInfoState *)data;
468
469 if (dpy->last_request_read != state->child_states[state->current_child].seq[state->current_request])
470 return False0;
471
472 if (rep->generic.type == X_Error0)
473 {
474 state->child_has_error = TRUE(!(0));
475 if (rep->error.errorCode != BadDrawable9 &&
476 rep->error.errorCode != BadWindow3)
477 {
478 state->have_error = TRUE(!(0));
479 result = False0;
480 }
481 }
482 else
483 {
484 switch (state->current_request)
485 {
486 case CHILD_INFO_GET_PROPERTY:
487 {
488 xGetPropertyReply replbuf;
489 xGetPropertyReply *repl;
490
491 repl = (xGetPropertyReply *)
492 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
493 (sizeof(xGetPropertyReply) - sizeof(xReply)) >> 2,
494 True1);
495
496 handle_get_property_reply (dpy, state, repl);
497 }
498 break;
499 case CHILD_INFO_GET_WA:
500 {
501 xGetWindowAttributesReply replbuf;
502 xGetWindowAttributesReply *repl;
503
504 repl = (xGetWindowAttributesReply *)
505 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
506 (sizeof(xGetWindowAttributesReply) - sizeof(xReply)) >> 2,
507 True1);
508
509 handle_get_wa_reply (dpy, state, repl);
510 }
511 break;
512 case CHILD_INFO_GET_GEOMETRY:
513 {
514 xGetGeometryReply replbuf;
515 xGetGeometryReply *repl;
516
517 repl = (xGetGeometryReply *)
518 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
519 (sizeof(xGetGeometryReply) - sizeof(xReply)) >> 2,
520 True1);
521
522 handle_get_geometry_reply (dpy, state, repl);
523 }
524 break;
525 }
526 }
527
528 next_child (state);
529
530 return result;
531}
532
533gboolean
534_cdk_x11_get_window_child_info (CdkDisplay *display,
535 Window window,
536 gboolean get_wm_state,
537 gboolean *win_has_wm_state,
538 CdkChildInfoX11 **children,
539 guint *nchildren)
540{
541 Display *dpy;
542 _XAsyncHandler async;
543 ChildInfoState state;
544 Atom wm_state_atom;
545 gboolean has_wm_state;
546 Boolint result;
547 guint i;
548
549 *children = NULL((void*)0);
550 *nchildren = 0;
551
552 dpy = CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
;
553 if (get_wm_state)
554 wm_state_atom = cdk_x11_get_xatom_by_name_for_display (display, "WM_STATE");
555 else
556 wm_state_atom = None0L;
557
558 state.children = NULL((void*)0);
559 state.nchildren = 0;
560
561 cdk_x11_display_error_trap_push (display);
562 result = list_children_and_wm_state (dpy, window,
563 win_has_wm_state ? wm_state_atom : None0L,
564 &has_wm_state,
565 &state.children, &state.nchildren);
566 cdk_x11_display_error_trap_pop_ignored (display);
567 if (!result)
568 {
569 g_free (state.children);
570 return FALSE(0);
571 }
572
573 if (has_wm_state)
574 {
575 if (win_has_wm_state)
576 *win_has_wm_state = TRUE(!(0));
577 g_free (state.children);
578 return TRUE(!(0));
579 }
580 else
581 {
582 if (win_has_wm_state)
583 *win_has_wm_state = FALSE(0);
584 }
585
586 state.get_wm_state = get_wm_state;
587 state.child_info = g_new (CdkChildInfoX11, state.nchildren)((CdkChildInfoX11 *) g_malloc_n ((state.nchildren), sizeof (CdkChildInfoX11
)))
;
588 state.child_states = g_new (ChildInfoChildState, state.nchildren)((ChildInfoChildState *) g_malloc_n ((state.nchildren), sizeof
(ChildInfoChildState)))
;
589 state.current_child = 0;
590 state.n_children_found = 0;
591 if (get_wm_state)
592 state.current_request = CHILD_INFO_GET_PROPERTY;
593 else
594 state.current_request = CHILD_INFO_GET_WA;
595 state.have_error = FALSE(0);
596 state.child_has_error = FALSE(0);
597
598 LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display
)(dpy)
;
599
600 async.next = dpy->async_handlers;
601 async.handler = get_child_info_handler;
602 async.data = (XPointer) &state;
603 dpy->async_handlers = &async;
604
605 for (i = 0; i < state.nchildren; i++)
606 {
607 xResourceReq *resource_req;
608 Window win = state.children[i];
609
610 if (get_wm_state)
611 {
612 xGetPropertyReq *prop_req;
613
614 GetReq (GetProperty, prop_req)prop_req = (xGetPropertyReq *) _XGetRequest(dpy, 20, 24);
615 prop_req->window = win;
616 prop_req->property = wm_state_atom;
617 prop_req->type = AnyPropertyType0L;
618 prop_req->delete = False0;
619 prop_req->longOffset = 0;
620 prop_req->longLength = 0;
621
622 state.child_states[i].seq[CHILD_INFO_GET_PROPERTY] = dpy->request;
623 }
624
625 GetResReq(GetWindowAttributes, win, resource_req)resource_req = (xResourceReq *) _XGetRequest(dpy, 3, 8); if (
resource_req) resource_req->id = (win)
;
626 state.child_states[i].seq[CHILD_INFO_GET_WA] = dpy->request;
627
628 GetResReq(GetGeometry, win, resource_req)resource_req = (xResourceReq *) _XGetRequest(dpy, 14, 8); if (
resource_req) resource_req->id = (win)
;
629 state.child_states[i].seq[CHILD_INFO_GET_GEOMETRY] = dpy->request;
630 }
631
632 if (i != 0)
633 {
634 /* Wait for the last reply
635 */
636 xGetGeometryReply rep;
637
638 /* On error, our async handler will get called
639 */
640 if (_XReply (dpy, (xReply *)&rep, 0, xTrue1))
641 handle_get_geometry_reply (dpy, &state, &rep);
642
643 next_child (&state);
644 }
645
646 if (!state.have_error)
647 {
648 *children = state.child_info;
649 *nchildren = state.n_children_found;
650 }
651 else
652 {
653 g_free (state.child_info);
654 }
655
656 g_free (state.children);
657 g_free (state.child_states);
658
659 DeqAsyncHandler(dpy, &async){ if (dpy->async_handlers == (&async)) dpy->async_handlers
= (&async)->next; else _XDeqAsyncHandler(dpy, &async
); }
;
660 UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display
)(dpy)
;
661 SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy);
662
663 return !state.have_error;
664}
665
666static gboolean
667roundtrip_callback_idle (gpointer data)
668{
669 RoundtripState *state = (RoundtripState *)data;
670
671 state->callback (state->display, state->data, state->get_input_focus_req);
672
673 g_free (state);
674
675 return FALSE(0);
676}
677
678static Boolint
679roundtrip_handler (Display *dpy,
680 xReply *rep,
681 char *buf,
682 int len,
683 XPointer data)
684{
685 RoundtripState *state = (RoundtripState *)data;
686
687 if (dpy->last_request_read == state->get_input_focus_req)
688 {
689 xGetInputFocusReply replbuf;
690 xGetInputFocusReply *repl G_GNUC_UNUSED__attribute__ ((__unused__));
691
692 if (rep->generic.type != X_Error0)
693 {
694 /* Actually does nothing, since there are no additional bytes
695 * to read, but maintain good form.
696 */
697 repl = (xGetInputFocusReply *)
698 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
699 (sizeof(xGetInputFocusReply) - sizeof(xReply)) >> 2,
700 True1);
701 }
702
703
704 if (state->callback)
705 {
706 guint id;
707 id = cdk_threads_add_idle (roundtrip_callback_idle, state);
708 g_source_set_name_by_id (id, "[ctk+] roundtrip_callback_idle");
709 }
710
711 DeqAsyncHandler(state->dpy, &state->async){ if (state->dpy->async_handlers == (&state->async
)) state->dpy->async_handlers = (&state->async)->
next; else _XDeqAsyncHandler(state->dpy, &state->async
); }
;
712
713 return (rep->generic.type != X_Error0);
714 }
715
716 return False0;
717}
718
719void
720_cdk_x11_roundtrip_async (CdkDisplay *display,
721 CdkRoundTripCallback callback,
722 gpointer data)
723{
724 Display *dpy;
725 RoundtripState *state;
726
727 dpy = CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
;
728
729 state = g_new (RoundtripState, 1)((RoundtripState *) g_malloc_n ((1), sizeof (RoundtripState))
)
;
730
731 state->display = display;
732 state->dpy = dpy;
733 state->callback = callback;
734 state->data = data;
735
736 LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display
)(dpy)
;
737
738 state->async.next = dpy->async_handlers;
739 state->async.handler = roundtrip_handler;
740 state->async.data = (XPointer) state;
741 dpy->async_handlers = &state->async;
742
743 /*
744 * XSync (dpy, 0)
745 */
746 {
747 G_GNUC_UNUSED__attribute__ ((__unused__)) xReq *req;
748
749 GetEmptyReq(GetInputFocus, req)req = (xReq *) _XGetRequest(dpy, 43, 4);
750 state->get_input_focus_req = dpy->request;
751 }
752
753 UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display
)(dpy)
;
754 SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy);
755}