File: | cdk/x11/cdkasync.c |
Warning: | line 163, column 11 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | /* |
21 | Copyright 1986, 1998 The Open Group |
22 | |
23 | Permission to use, copy, modify, distribute, and sell this software and its |
24 | documentation for any purpose is hereby granted without fee, provided that |
25 | the above copyright notice appear in all copies and that both that |
26 | copyright notice and this permission notice appear in supporting |
27 | documentation. |
28 | |
29 | The above copyright notice and this permission notice shall be included in |
30 | all copies or substantial portions of the Software. |
31 | |
32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
33 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
34 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
35 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
36 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
37 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
38 | |
39 | Except as contained in this notice, the name of The Open Group shall not be |
40 | used in advertising or otherwise to promote the sale, use or other dealings |
41 | in 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 | |
52 | typedef struct _ChildInfoChildState ChildInfoChildState; |
53 | typedef struct _ChildInfoState ChildInfoState; |
54 | typedef struct _ListChildrenState ListChildrenState; |
55 | typedef struct _SendEventState SendEventState; |
56 | typedef struct _SetInputFocusState SetInputFocusState; |
57 | typedef struct _RoundtripState RoundtripState; |
58 | |
59 | typedef enum { |
60 | CHILD_INFO_GET_PROPERTY, |
61 | CHILD_INFO_GET_WA, |
62 | CHILD_INFO_GET_GEOMETRY |
63 | } ChildInfoReq; |
64 | |
65 | struct _ChildInfoChildState |
66 | { |
67 | gulong seq[3]; |
68 | }; |
69 | |
70 | struct _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 | |
85 | struct _ListChildrenState |
86 | { |
87 | Display *dpy; |
88 | gulong get_property_req; |
89 | gboolean have_error; |
90 | gboolean has_wm_state; |
91 | }; |
92 | |
93 | struct _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 | |
105 | struct _SetInputFocusState |
106 | { |
107 | Display *dpy; |
108 | _XAsyncHandler async; |
109 | gulong set_input_focus_req; |
110 | gulong get_input_focus_req; |
111 | }; |
112 | |
113 | struct _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 | |
123 | static gboolean |
124 | callback_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 | |
135 | static Boolint |
136 | send_event_handler (Display *dpy, |
137 | xReply *rep, |
138 | char *buf, |
139 | int len, |
140 | XPointer data) |
141 | { |
142 | SendEventState *state = (SendEventState *)data; |
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 *) |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
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 | |
184 | static void |
185 | client_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 | |
226 | void |
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 | |
289 | static Boolint |
290 | list_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 | |
326 | static gboolean |
327 | list_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 | |
399 | static void |
400 | handle_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 | |
409 | static void |
410 | handle_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 | |
422 | static void |
423 | handle_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 | |
436 | static void |
437 | next_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 | |
458 | static Boolint |
459 | get_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 | |
533 | gboolean |
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 | |
666 | static gboolean |
667 | roundtrip_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 | |
678 | static Boolint |
679 | roundtrip_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 | |
719 | void |
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 | } |