svn update: 48958 (latest:48959)
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_window.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include <string.h>
6
7 #include <Ecore.h>
8
9 #include "ecore_xcb_private.h"
10 #include "Ecore_X_Atoms.h"
11
12
13 static int             ignore_num = 0;
14 static Ecore_X_Window *ignore_list = NULL;
15
16 static Ecore_X_Window _ecore_x_window_at_xy_get(Ecore_X_Window  base,
17                                                 int16_t         base_x,
18                                                 int16_t         base_y,
19                                                 int16_t         x,
20                                                 int16_t         y,
21                                                 Ecore_X_Window *skip,
22                                                 int             skip_num);
23
24 #ifdef ECORE_XCB_RENDER
25 static Ecore_X_Window _ecore_x_window_argb_internal_new(Ecore_X_Window parent,
26                                                         int16_t        x,
27                                                         int16_t        y,
28                                                         uint16_t       w,
29                                                         uint16_t       h,
30                                                         uint8_t        override_redirect,
31                                                         uint8_t        save_under);
32 #endif /* ECORE_XCB_RENDER */
33
34
35 /**
36  * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions
37  *
38  * Functions that can be used to create an X window.
39  */
40
41 /**
42  * Creates a new window.
43  * @param   parent The parent window to use.  If @p parent is @c 0, the root
44  *                 window of the default display is used.
45  * @param   x      X position.
46  * @param   y      Y position.
47  * @param   w      Width.
48  * @param   h      Height.
49  * @return  The new window handle.
50  * @ingroup Ecore_X_Window_Create_Group
51  */
52 EAPI Ecore_X_Window
53 ecore_x_window_new(Ecore_X_Window parent,
54                    int            x,
55                    int            y,
56                    int            width,
57                    int            height)
58 {
59    uint32_t       value_list[9];
60    Ecore_X_Window window;
61    xcb_visualid_t vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT };
62    uint32_t       value_mask;
63
64    if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
65
66    value_mask =
67      XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL  | XCB_CW_BIT_GRAVITY       |
68      XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT |
69      XCB_CW_SAVE_UNDER  | XCB_CW_EVENT_MASK    | XCB_CW_DONT_PROPAGATE;
70
71    value_list[0]  = XCB_NONE;
72    value_list[1]  = 0;
73    value_list[2]  = XCB_GRAVITY_NORTH_WEST;
74    value_list[3]  = XCB_GRAVITY_NORTH_WEST;
75    value_list[4]  = XCB_BACKING_STORE_NOT_USEFUL;
76    value_list[5]  = 0;
77    value_list[6]  = 0;
78    value_list[7]  =
79      XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
80      XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
81      XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
82      XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
83      XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
84      XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
85      XCB_EVENT_MASK_COLOR_MAP_CHANGE;
86    value_list[8]  = XCB_EVENT_MASK_NO_EVENT;
87
88    window = xcb_generate_id(_ecore_xcb_conn);
89    xcb_create_window(_ecore_xcb_conn,
90                    XCB_WINDOW_CLASS_COPY_FROM_PARENT,
91                    window, parent, x, y, width, height, 0,
92                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
93                    vis,
94                    value_mask,
95                    value_list);
96
97    if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) ecore_x_window_defaults_set(window);
98    return window;
99 }
100
101 /**
102  * Creates a window with the override redirect attribute set to @c True.
103  * @param   parent The parent window to use.  If @p parent is @c 0, the root
104  *                 window of the default display is used.
105  * @param   x      X position.
106  * @param   y      Y position.
107  * @param   w      Width.
108  * @param   h      Height.
109  * @return  The new window handle.
110  * @ingroup Ecore_X_Window_Create_Group
111  */
112 EAPI Ecore_X_Window
113 ecore_x_window_override_new(Ecore_X_Window parent,
114                             int            x,
115                             int            y,
116                             int            width,
117                             int            height)
118 {
119    uint32_t         value_list[9];
120    Ecore_X_Window window;
121    xcb_visualid_t   vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT };
122    uint32_t         value_mask;
123
124    if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
125
126    value_mask =
127      XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL  | XCB_CW_BIT_GRAVITY       |
128      XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT |
129      XCB_CW_SAVE_UNDER  | XCB_CW_EVENT_MASK    | XCB_CW_DONT_PROPAGATE;
130
131    value_list[0]  = XCB_NONE;
132    value_list[1]  = 0;
133    value_list[2]  = XCB_GRAVITY_NORTH_WEST;
134    value_list[3]  = XCB_GRAVITY_NORTH_WEST;
135    value_list[4]  = XCB_BACKING_STORE_NOT_USEFUL;
136    value_list[5]  = 1;
137    value_list[6]  = 0;
138    value_list[7]  =
139      XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
140      XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
141      XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
142      XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
143      XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
144      XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
145      XCB_EVENT_MASK_COLOR_MAP_CHANGE;
146    value_list[8]  = XCB_EVENT_MASK_NO_EVENT;
147
148    window = xcb_generate_id(_ecore_xcb_conn);
149    xcb_create_window(_ecore_xcb_conn,
150                    XCB_WINDOW_CLASS_COPY_FROM_PARENT,
151                    window, parent, x, y, width, height, 0,
152                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
153                    vis,
154                    value_mask,
155                    value_list);
156    return window;
157 }
158
159 /**
160  * Creates a new input window.
161  * @param   parent The parent window to use.    If @p parent is @c 0, the root
162  *                 window of the default display is used.
163  * @param   x      X position.
164  * @param   y      Y position.
165  * @param   w      Width.
166  * @param   h      Height.
167  * @return  The new window.
168  * @ingroup Ecore_X_Window_Create_Group
169  */
170 EAPI Ecore_X_Window
171 ecore_x_window_input_new(Ecore_X_Window parent,
172                          int            x,
173                          int            y,
174                          int            width,
175                          int            height)
176 {
177    uint32_t         value_list[3];
178    Ecore_X_Window window;
179    xcb_visualid_t   vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT };
180    uint32_t         value_mask;
181
182    if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
183
184    value_mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE;
185
186    value_list[0]  = 1;
187    value_list[1]  =
188      XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
189      XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
190      XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
191      XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
192      XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
193      XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
194      XCB_EVENT_MASK_COLOR_MAP_CHANGE;
195    value_list[2]  = XCB_EVENT_MASK_NO_EVENT;
196
197    window = xcb_generate_id(_ecore_xcb_conn);
198    xcb_create_window(_ecore_xcb_conn,
199                    XCB_WINDOW_CLASS_COPY_FROM_PARENT,
200                    window, parent, x, y, width, height, 0,
201                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
202                    vis,
203                    value_mask,
204                    value_list);
205
206    if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root)
207      {
208      }
209
210    return window;
211 }
212
213 /**
214  * Creates a new window.
215  * @param   parent The parent window to use.  If @p parent is @c 0, the root
216  *                 window of the default display is used.
217  * @param   x      X position.
218  * @param   y      Y position.
219  * @param   width  Width.
220  * @param   height Height.
221  * @return         The new window handle.
222  * @ingroup Ecore_X_Window_Create_Group
223  */
224 EAPI Ecore_X_Window
225 ecore_x_window_manager_argb_new(Ecore_X_Window parent,
226                                 int            x,
227                                 int            y,
228                                 int            width,
229                                 int            height)
230 {
231    Ecore_X_Window window = 0;
232
233 #ifdef ECORE_XCB_RENDER
234    window = _ecore_x_window_argb_internal_new(parent,
235                                               x, y, width, height,
236                                               1, 0);
237 #endif /* ECORE_XCB_RENDER */
238
239    return window;
240 }
241
242 /**
243  * Creates a new window.
244  * @param   parent The parent window to use.  If @p parent is @c 0, the root
245  *                 window of the default display is used.
246  * @param   x      X position.
247  * @param   y      Y position.
248  * @param   width  Width.
249  * @param   height Height.
250  * @return         The new window handle.
251  * @ingroup Ecore_X_Window_Create_Group
252  */
253 EAPI Ecore_X_Window
254 ecore_x_window_argb_new(Ecore_X_Window parent,
255                         int            x,
256                         int            y,
257                         int            width,
258                         int            height)
259 {
260    Ecore_X_Window window = 0;
261
262 #ifdef ECORE_XCB_RENDER
263    window = _ecore_x_window_argb_internal_new(parent,
264                                               x, y, width, height,
265                                               0, 0);
266 #endif /* ECORE_XCB_RENDER */
267
268    return window;
269 }
270
271 /**
272  * Creates a window with the override redirect attribute set to @c True.
273  * @param   parent The parent window to use.  If @p parent is @c 0, the root
274  *                 window of the default display is used.
275  * @param   x      X position.
276  * @param   y      Y position.
277  * @param   width  Width.
278  * @param   height Height.
279  * @return         The new window handle.
280  * @ingroup Ecore_X_Window_Create_Group
281  */
282 EAPI Ecore_X_Window
283 ecore_x_window_override_argb_new(Ecore_X_Window parent,
284                                  int            x,
285                                  int            y,
286                                  int            width,
287                                  int            height)
288 {
289    Ecore_X_Window window = 0;
290
291 #ifdef ECORE_XCB_RENDER
292    window = _ecore_x_window_argb_internal_new(parent,
293                                               x, y, width, height,
294                                               1, 0);
295 #endif /* ECORE_XCB_RENDER */
296
297    return window;
298 }
299
300 /**
301  * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions
302  *
303  * Functions to destroy X windows.
304  */
305
306 /**
307  * Deletes the given window.
308  * @param   window The given window.
309  * @ingroup Ecore_X_Window_Destroy_Group
310  */
311 EAPI void
312 ecore_x_window_free(Ecore_X_Window window)
313 {
314    /* sorry sir, deleting the root window doesn't sound like
315     * a smart idea.
316     */
317    if (window)
318       xcb_destroy_window(_ecore_xcb_conn, window);
319 }
320
321 /**
322  * Sends a delete request to the given window.
323  * @param   window The given window.
324  * @ingroup Ecore_X_Window_Destroy_Group
325  */
326 EAPI void
327 ecore_x_window_delete_request_send(Ecore_X_Window window)
328 {
329    xcb_client_message_event_t ev;
330
331    /* sorry sir, deleting the root window doesn't sound like
332     * a smart idea.
333     */
334    if (window == 0)
335       return;
336
337    ev.response_type = XCB_CLIENT_MESSAGE;
338    ev.format = 32;
339    ev.sequence = 0;
340    ev.window = window;
341    ev.type = ECORE_X_ATOM_WM_PROTOCOLS;
342    ev.data.data32[0] = ECORE_X_ATOM_WM_DELETE_WINDOW;
343    ev.data.data32[1] = XCB_CURRENT_TIME;
344
345    xcb_send_event(_ecore_xcb_conn, 0, window,
346                   XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
347 }
348
349 /**
350  * @defgroup Ecore_X_Window_Configure_Group X Window Configure Functions
351  *
352  * Functions to configure X windows.
353  */
354
355
356 /**
357  * Configures the given window with the given mask.
358  * @param   window       The given window.
359  * @param   mask         The given mask.
360  * @param   x            The X coordinate of the window.
361  * @param   y            The Y coordinate of the window.
362  * @param   width        The width of the window.
363  * @param   height       The height of the window.
364  * @param   border_width The border width of the window.
365  * @param   sibling      The sibling window of the window.
366  * @param   stack_mode   The stack mode of the window.
367  * @ingroup Ecore_X_Window_Configure_Group
368  */
369 EAPI void
370 ecore_x_window_configure(Ecore_X_Window                window,
371                          Ecore_X_Window_Configure_Mask mask,
372                          int                           x,
373                          int                           y,
374                          int                           width,
375                          int                           height,
376                          int                           border_width,
377                          Ecore_X_Window                sibling,
378                          int                           stack_mode)
379 {
380    uint32_t *value_list;
381    uint32_t  value_mask;
382    int       length = 0;
383
384    if (!window)
385       return;
386
387    value_mask = mask;
388    for ( ; value_mask; value_mask >>= 1)
389      if (value_mask & 1)
390        length++;
391    value_list = (uint32_t *)malloc(sizeof(uint32_t) * length);
392    if (!value_list)
393       return;
394
395    value_mask = mask;
396    for ( ; value_mask; value_mask >>= 1, value_list++)
397       if (value_mask & 1)
398         {
399           switch (value_mask) {
400           case XCB_CONFIG_WINDOW_X:
401             *value_list = x;
402             break;
403           case XCB_CONFIG_WINDOW_Y:
404             *value_list = y;
405             break;
406           case XCB_CONFIG_WINDOW_WIDTH:
407             *value_list = width;
408             break;
409           case XCB_CONFIG_WINDOW_HEIGHT:
410             *value_list = height;
411             break;
412           case XCB_CONFIG_WINDOW_BORDER_WIDTH:
413             *value_list = border_width;
414             break;
415           case XCB_CONFIG_WINDOW_SIBLING:
416             *value_list = sibling;
417             break;
418           case XCB_CONFIG_WINDOW_STACK_MODE:
419             *value_list = stack_mode;
420             break;
421           }
422         }
423
424    xcb_configure_window(_ecore_xcb_conn, window, mask, value_list);
425    free(value_list);
426 }
427
428 /**
429  * Moves a window to the position @p x, @p y.
430  *
431  * The position is relative to the upper left hand corner of the
432  * parent window.
433  *
434  * @param   window The window to move.
435  * @param   x      X position.
436  * @param   y      Y position.
437  * @ingroup Ecore_X_Window_Configure_Group
438  */
439 EAPI void
440 ecore_x_window_move(Ecore_X_Window window,
441                     int            x,
442                     int            y)
443 {
444    uint32_t value_list[2];
445    uint32_t value_mask;
446
447    if (!window)
448       return;
449
450    value_mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
451
452    value_list[0] = x;
453    value_list[1] = y;
454
455    xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list);
456 }
457
458 /**
459  * Resizes a window.
460  * @param   window The window to resize.
461  * @param   width  New width of the window.
462  * @param   height New height of the window.
463  * @ingroup Ecore_X_Window_Configure_Group
464  */
465 EAPI void
466 ecore_x_window_resize(Ecore_X_Window window,
467                       int            width,
468                       int            height)
469 {
470    uint32_t value_list[2];
471    uint32_t value_mask;
472
473    if (!window)
474       return;
475
476    if (width < 1) width = 1;
477    if (height < 1) height = 1;
478
479    value_mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
480
481    value_list[0] = width;
482    value_list[1] = height;
483
484    xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list);
485 }
486
487 /**
488  * Moves and resizes a window.
489  * @param   window The window to move and resize.
490  * @param   x      New X position of the window.
491  * @param   y      New Y position of the window.
492  * @param   width  New width of the window.
493  * @param   height New height of the window.
494  * @ingroup Ecore_X_Window_Configure_Group
495  */
496 EAPI void
497 ecore_x_window_move_resize(Ecore_X_Window window,
498                            int            x,
499                            int            y,
500                            int            width,
501                            int            height)
502 {
503    uint32_t value_list[4];
504    uint32_t value_mask;
505
506    if (!window)
507       return;
508
509    if (width < 1) width = 1;
510    if (height < 1) height = 1;
511
512    value_mask =
513      XCB_CONFIG_WINDOW_X     | XCB_CONFIG_WINDOW_Y     |
514      XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
515
516    value_list[0] = x;
517    value_list[1] = y;
518    value_list[2] = width;
519    value_list[3] = height;
520
521    xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list);
522 }
523
524 /**
525  * Sets the width of the border of the given window.
526  * @param   window       The given window.
527  * @param   border_width The new border width.
528  * @ingroup Ecore_X_Window_Configure_Group
529  */
530 EAPI void
531 ecore_x_window_border_width_set(Ecore_X_Window window,
532                                 int            border_width)
533 {
534    uint32_t value_list;
535
536    /* doesn't make sense to call this on a root window */
537    if (!window)
538       return;
539
540    value_list = border_width;
541
542    xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_BORDER_WIDTH, &value_list);
543 }
544
545 /**
546  * Raises the given window.
547  * @param   window The window to raise.
548  * @ingroup Ecore_X_Window_Configure_Group
549  */
550 EAPI void
551 ecore_x_window_raise(Ecore_X_Window window)
552 {
553    uint32_t value_list;
554
555    if (!window)
556       return;
557
558    value_list = XCB_STACK_MODE_ABOVE;
559
560    xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_STACK_MODE, &value_list);
561 }
562
563 /**
564  * Lowers the given window.
565  * @param   window The window to lower.
566  * @ingroup Ecore_X_Window_Configure_Group
567  */
568 EAPI void
569 ecore_x_window_lower(Ecore_X_Window window)
570 {
571    uint32_t value_list;
572
573    if (!window)
574       return;
575
576    value_list = XCB_STACK_MODE_BELOW;
577
578    xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_STACK_MODE, &value_list);
579 }
580
581 /**
582  * @defgroup Ecore_X_Window_Change_Properties_Group X Window Change Property Functions
583  *
584  * Functions that change window properties.
585  */
586
587 /**
588  * Sets the default properties for the given window.
589  *
590  * The default properties set for the window are @c WM_CLIENT_MACHINE and
591  * @c _NET_WM_PID.
592  *
593  * @param   window The given window.
594  * @ingroup Ecore_X_Window_Change_Property_Group
595  */
596 EAPI void
597 ecore_x_window_defaults_set(Ecore_X_Window window)
598 {
599    char   buf[MAXHOSTNAMELEN];
600    pid_t  pid;
601    int    argc;
602    char **argv;
603
604    /*
605     * Set WM_CLIENT_MACHINE.
606     */
607    gethostname(buf, MAXHOSTNAMELEN);
608    buf[MAXHOSTNAMELEN - 1] = '\0';
609    /* The ecore function uses UTF8 which Xlib may not like (especially
610     * with older clients) */
611    /* ecore_xcb_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE,
612                                   (char *)buf); */
613    xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
614                        ECORE_X_ATOM_WM_CLIENT_MACHINE,
615                        ECORE_X_ATOM_STRING,
616                        8, strlen(buf), buf);
617
618    /*
619     * Set _NET_WM_PID
620     */
621    pid = getpid();
622    ecore_x_netwm_pid_set(window, pid);
623
624    ecore_x_netwm_window_type_set(window, ECORE_X_WINDOW_TYPE_NORMAL);
625
626    ecore_app_args_get(&argc, &argv);
627    ecore_x_icccm_command_set(window, argc, argv);
628 }
629
630 /**
631  * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions
632  *
633  * Functions to change the visibility of X windows.
634  */
635
636 /**
637  * Shows a window.
638  *
639  * Synonymous to "mapping" a window in X Window System terminology.
640  *
641  * @param   window The window to show.
642  * @ingroup Ecore_X_Window_Visibility_Group
643  */
644 EAPI void
645 ecore_x_window_show(Ecore_X_Window window)
646 {
647    xcb_map_window(_ecore_xcb_conn, window);
648 }
649
650 /**
651  * Hides a window.
652  *
653  * Synonymous to "unmapping" a window in X Window System terminology.
654  *
655  * @param   window The window to hide.
656  * @ingroup Ecore_X_Window_Visibility_Group
657  */
658 EAPI void
659 ecore_x_window_hide(Ecore_X_Window window)
660 {
661    xcb_unmap_notify_event_t ev;
662    Ecore_X_Window           root;
663
664    /* ICCCM: SEND unmap event... */
665    root = window;
666    /* FIXME: is it correct ? */
667    if (xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem == 1)
668      root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
669    else
670      {
671         xcb_get_geometry_cookie_t   cookie;
672         xcb_get_geometry_reply_t   *rep;
673         Ecore_X_Drawable            draw;
674
675         /* FIXME: can we avoid round trips, here ? */
676         draw = window;
677         cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, draw);
678         rep = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL);
679         if (!rep)
680            return;
681         root = rep->root;
682         free(rep);
683      }
684    ev.response_type = XCB_UNMAP_NOTIFY;
685    ev.pad0 = 0;
686    ev.sequence = 0;
687    ev.event = root;
688    ev.window = window;
689    ev.from_configure = 0;
690
691    xcb_send_event(_ecore_xcb_conn, 0, root,
692                   XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
693                   (const char *)&ev);
694    xcb_unmap_window(_ecore_xcb_conn, window);
695 }
696
697 /**
698  * @defgroup Ecore_X_Window_Input_Focus_Group X Window Input Focus Functions
699  *
700  * Functions that manage the focus of an X Window.
701  */
702
703 /**
704  * Sets the focus to the window @p window.
705  * @param   window The window to focus.
706  * @ingroup Ecore_X_Window_Input_Focus_Group
707  */
708 EAPI void
709 ecore_x_window_focus(Ecore_X_Window window)
710 {
711    Ecore_X_Time time = XCB_CURRENT_TIME;
712
713    if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
714
715    /* xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_NONE, win, time); */
716    xcb_set_input_focus(_ecore_xcb_conn,
717                        XCB_INPUT_FOCUS_POINTER_ROOT, window, time);
718 }
719
720 /**
721  * Sets the focus to the given window at a specific time.
722  * @param   window The window to focus.
723  * @param   time   When to set the focus to the window.
724  * @ingroup Ecore_X_Window_Input_Focus_Group
725  */
726 EAPI void
727 ecore_x_window_focus_at_time(Ecore_X_Window window,
728                              Ecore_X_Time   time)
729 {
730    if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
731
732    /* xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_NONE, win, time); */
733    xcb_set_input_focus(_ecore_xcb_conn,
734                        XCB_INPUT_FOCUS_POINTER_ROOT, window, time);
735 }
736
737 /**
738  * @defgroup Ecore_X_Window_Reparent_Group X Window Reparent Functions
739  *
740  * Functions that retrieve or changes the parent window of a window.
741  */
742
743 /**
744  * Moves a window to within another window at a given position.
745  * @param   window     The window to reparent.
746  * @param   new_parent The new parent window.
747  * @param   x          X position within new parent window.
748  * @param   y          Y position within new parent window.
749  * @ingroup Ecore_X_Window_Reparent_Group
750  */
751 EAPI void
752 ecore_x_window_reparent(Ecore_X_Window window,
753                         Ecore_X_Window new_parent,
754                         int            x,
755                         int            y)
756 {
757    if (new_parent == 0) new_parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
758
759    xcb_reparent_window(_ecore_xcb_conn, window, new_parent, x, y);
760 }
761
762
763 /**
764  * @defgroup Ecore_X_Window_Change_Attributes_Group X Window Change Attributes Functions
765  *
766  * Functions that change the attributes of a window.
767  */
768
769 /**
770  * Sets the background pixmap of the given window.
771  * @param   window The given window.
772  * @param   pixmap The pixmap to set to.
773  * @ingroup Ecore_X_Window_Change_Attributes_Group
774  */
775 EAPI void
776 ecore_x_window_pixmap_set(Ecore_X_Window window,
777                           Ecore_X_Pixmap pixmap)
778 {
779    uint32_t value_list;
780
781    value_list = pixmap;
782    xcb_change_window_attributes(_ecore_xcb_conn, window,
783                                 XCB_CW_BACK_PIXMAP, &value_list);
784 }
785
786 /**
787  * Sets the background color of the given window.
788  * @param   window The given window.
789  * @param   red    The red component of the color to set to.
790  * @param   green  The green component of the color to set to.
791  * @param   blue   The blue component of the color to set to.
792  * @ingroup Ecore_X_Window_Change_Attributes_Group
793  */
794 EAPI void
795 ecore_x_window_background_color_set(Ecore_X_Window window,
796                                     unsigned short red,
797                                     unsigned short green,
798                                     unsigned short blue)
799 {
800    xcb_alloc_color_cookie_t cookie;
801    xcb_alloc_color_reply_t *rep;
802    uint32_t                 value_list;
803
804    /* FIXME: should I provide a reply, and not the color components, here ? */
805    /*        (because of roundtrips) */
806    cookie = xcb_alloc_color_unchecked(_ecore_xcb_conn,
807                                       ((xcb_screen_t *)_ecore_xcb_screen)->default_colormap,
808                                       red, green, blue);
809    rep = xcb_alloc_color_reply(_ecore_xcb_conn, cookie, NULL);
810    if (!rep)
811      return;
812
813    value_list = rep->pixel;
814    xcb_change_window_attributes(_ecore_xcb_conn, window,
815                                 XCB_CW_BACK_PIXEL, &value_list);
816    free(rep);
817 }
818
819 /**
820  * Sets the bit gravity of the given window.
821  * @param   window  The given window.
822  * @param   gravity The gravity.
823  * @ingroup Ecore_X_Window_Change_Attributes_Group
824  */
825 EAPI void
826 ecore_x_window_pixel_gravity_set(Ecore_X_Window  window,
827                                  Ecore_X_Gravity gravity)
828 {
829    uint32_t value_list;
830
831    value_list = gravity;
832    xcb_change_window_attributes(_ecore_xcb_conn, window,
833                                 XCB_CW_BIT_GRAVITY, &value_list);
834 }
835
836 /**
837  * Sets the gravity of the given window.
838  * @param   window  The given window.
839  * @param   gravity The gravity.
840  * @ingroup Ecore_X_Window_Change_Attributes_Group
841  */
842 EAPI void
843 ecore_x_window_gravity_set(Ecore_X_Window  window,
844                            Ecore_X_Gravity gravity)
845 {
846    uint32_t value_list;
847
848    value_list = gravity;
849    xcb_change_window_attributes(_ecore_xcb_conn, window,
850                                 XCB_CW_WIN_GRAVITY, &value_list);
851 }
852
853 /**
854  * Sets the override attribute of the given window.
855  * @param   window            The given window.
856  * @param   override_redirect The override_redirect boolean.
857  * @ingroup Ecore_X_Window_Change_Attributes_Group
858  */
859 EAPI void
860 ecore_x_window_override_set(Ecore_X_Window window,
861                             int            override_redirect)
862 {
863    uint32_t value_list;
864
865    value_list = override_redirect;
866    xcb_change_window_attributes(_ecore_xcb_conn, window,
867                                 XCB_CW_OVERRIDE_REDIRECT, &value_list);
868 }
869
870 /**
871  * Shows the cursor of the given window.
872  * @param   window The given window.
873  * @param   show   If set to @c 0, hide the cursor. Show it otherwise.
874  * @ingroup Ecore_X_Window_Change_Attributes_Group
875  */
876 EAPI void
877 ecore_x_window_cursor_show(Ecore_X_Window window,
878                            int            show)
879 {
880    if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
881
882    if (!show)
883      {
884         Ecore_X_Cursor   cursor;
885         Ecore_X_Drawable draw;
886         Ecore_X_Pixmap   pixmap;
887         Ecore_X_Pixmap   mask;
888         Ecore_X_GC       gc;
889         xcb_point_t      point;
890         uint32_t         value_list;
891
892         draw = window;
893         pixmap = xcb_generate_id(_ecore_xcb_conn);
894         xcb_create_pixmap(_ecore_xcb_conn,
895                           1, pixmap, draw,
896                           1, 1);
897         mask = xcb_generate_id(_ecore_xcb_conn);
898         xcb_create_pixmap(_ecore_xcb_conn,
899                           1, mask, draw,
900                           1, 1);
901
902         gc = xcb_generate_id(_ecore_xcb_conn);
903         xcb_create_gc (_ecore_xcb_conn, gc, draw, 0, NULL);
904         value_list = 0;
905         xcb_change_gc(_ecore_xcb_conn, gc, XCB_GC_FOREGROUND, &value_list);
906
907         draw = mask;
908         point.x = 0;
909         point.y = 0;
910         xcb_poly_point(_ecore_xcb_conn, XCB_COORD_MODE_ORIGIN, draw,
911                        gc, 1, &point);
912
913         xcb_free_gc(_ecore_xcb_conn, gc);
914
915         cursor = xcb_generate_id(_ecore_xcb_conn);
916         xcb_create_cursor(_ecore_xcb_conn, cursor,
917                           pixmap, mask,
918                           0, 0, 0,
919                           0, 0, 0,
920                           0, 0);
921         value_list = cursor;
922         xcb_change_window_attributes(_ecore_xcb_conn, window,
923                                      XCB_CW_CURSOR, &value_list);
924
925         xcb_free_cursor(_ecore_xcb_conn, cursor);
926         xcb_free_pixmap(_ecore_xcb_conn, mask);
927         xcb_free_pixmap(_ecore_xcb_conn, pixmap);
928      }
929    else
930      {
931         uint32_t value_list;
932
933         value_list = 0;
934         xcb_change_window_attributes(_ecore_xcb_conn, window,
935                                      XCB_CW_CURSOR, &value_list);
936      }
937 }
938
939 /**
940  * Sets the cursor of the given window.
941  * @param   window The given window.
942  * @param   cursor The given cursor.
943  * @ingroup Ecore_X_Window_Change_Attributes_Group
944  */
945 EAPI void
946 ecore_x_window_cursor_set(Ecore_X_Window window,
947                           Ecore_X_Cursor cursor)
948 {
949    uint32_t value_list;
950
951    value_list = cursor;
952    xcb_change_window_attributes(_ecore_xcb_conn, window,
953                                 XCB_CW_CURSOR, &value_list);
954 }
955
956 /**
957  * Todo
958  * @param   window The given window.
959  * @ingroup Ecore_X_Window_Change_Attributes_Group
960  */
961 EAPI void
962 ecore_x_window_container_manage(Ecore_X_Window window)
963 {
964    uint32_t value_list;
965
966    value_list =
967      XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
968      XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
969    xcb_change_window_attributes(_ecore_xcb_conn, window,
970                                 XCB_CW_EVENT_MASK, &value_list);
971
972 }
973
974 /**
975  * Todo
976  * @param   window The given window.
977  * @ingroup Ecore_X_Window_Change_Attributes_Group
978  */
979 EAPI void
980 ecore_x_window_client_manage(Ecore_X_Window window)
981 {
982    uint32_t value_list;
983
984    value_list =
985      XCB_EVENT_MASK_VISIBILITY_CHANGE |
986 /*      XCB_EVENT_MASK_RESIZE_REDIRECT | */
987      XCB_EVENT_MASK_STRUCTURE_NOTIFY |
988      XCB_EVENT_MASK_FOCUS_CHANGE |
989      XCB_EVENT_MASK_PROPERTY_CHANGE |
990      XCB_EVENT_MASK_COLOR_MAP_CHANGE;
991    xcb_change_window_attributes(_ecore_xcb_conn, window,
992                                 XCB_CW_EVENT_MASK, &value_list);
993 #ifdef ECORE_XCB_SHAPE
994    xcb_shape_select_input(_ecore_xcb_conn, window, 1);
995 #endif /* ECORE_XCB_SHAPE */
996 }
997
998 /**
999  * Todo
1000  * @param   window The given window.
1001  * @ingroup Ecore_X_Window_Change_Attributes_Group
1002  */
1003 EAPI void
1004 ecore_x_window_sniff(Ecore_X_Window window)
1005 {
1006    uint32_t value_list;
1007
1008    value_list =
1009      XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
1010      XCB_EVENT_MASK_PROPERTY_CHANGE;
1011    xcb_change_window_attributes(_ecore_xcb_conn, window,
1012                                 XCB_CW_EVENT_MASK, &value_list);
1013 }
1014
1015 /**
1016  * Todo
1017  * @param   window The given window.
1018  * @ingroup Ecore_X_Window_Change_Attributes_Group
1019  */
1020 EAPI void
1021 ecore_x_window_client_sniff(Ecore_X_Window window)
1022 {
1023    uint32_t value_list;
1024
1025    value_list =
1026      XCB_EVENT_MASK_VISIBILITY_CHANGE |
1027      XCB_EVENT_MASK_STRUCTURE_NOTIFY |
1028      XCB_EVENT_MASK_FOCUS_CHANGE |
1029      XCB_EVENT_MASK_PROPERTY_CHANGE |
1030      XCB_EVENT_MASK_COLOR_MAP_CHANGE;
1031    xcb_change_window_attributes(_ecore_xcb_conn, window,
1032                                 XCB_CW_EVENT_MASK, &value_list);
1033 #ifdef ECORE_XCB_SHAPE
1034    xcb_shape_select_input(_ecore_xcb_conn, window, 1);
1035 #endif /* ECORE_XCB_SHAPE */
1036 }
1037
1038 /**
1039  * Clears an area of the given window.
1040  * @param   window  The given window.
1041  * @param   x            The X coordinate of the area.
1042  * @param   y            The Y coordinate of the area.
1043  * @param   width        The width of the area.
1044  * @param   height       The height of the area.
1045  * @ingroup Ecore_X_Window_Clear_Area_Group
1046  */
1047 EAPI void
1048 ecore_x_window_area_clear(Ecore_X_Window window,
1049                           int            x,
1050                           int            y,
1051                           int            width,
1052                           int            height)
1053 {
1054    xcb_clear_area(_ecore_xcb_conn, 0, window, x, y, width, height);
1055 }
1056
1057 /**
1058  * Exposes an area of the given window.
1059  * @param   window  The given window.
1060  * @param   x            The X coordinate of the area.
1061  * @param   y            The Y coordinate of the area.
1062  * @param   width        The width of the area.
1063  * @param   height       The height of the area.
1064  * @ingroup Ecore_X_Window_Clear_Area_Group
1065  */
1066 EAPI void
1067 ecore_x_window_area_expose(Ecore_X_Window window,
1068                            int            x,
1069                            int            y,
1070                            int            width,
1071                            int            height)
1072 {
1073    xcb_clear_area(_ecore_xcb_conn, 1, window, x, y, width, height);
1074 }
1075
1076
1077 /**
1078  * @defgroup Ecore_X_Window_Save_Set_Group X Window Change Save Set Functions
1079  *
1080  * Functions that either inserts or deletes the specified window from
1081  * the client's save-set.
1082  */
1083
1084 /**
1085  * Inserts the window in the client's save-set.
1086  * @param   window The window to insert in the client's save-set.
1087  * @ingroup Ecore_X_Window_Save_Set_Group
1088  */
1089 EAPI void
1090 ecore_x_window_save_set_add(Ecore_X_Window window)
1091 {
1092    xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_INSERT, window);
1093 }
1094
1095 /**
1096  * Deletes the window from the client's save-set.
1097  * @param   window The window to delete from the client's save-set.
1098  * @ingroup Ecore_X_Window_Save_Set_Group
1099  */
1100 EAPI void
1101 ecore_x_window_save_set_del(Ecore_X_Window window)
1102 {
1103    xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_DELETE, window);
1104 }
1105
1106 /******************************
1107  *
1108  * Request that have a reply
1109  *
1110  ******************************/
1111
1112
1113 /**
1114  * Sends the GetInputFocus request.
1115  * @ingroup Ecore_X_Window_Input_Focus_Group
1116  */
1117 EAPI void
1118 ecore_x_get_input_focus_prefetch(void)
1119 {
1120    xcb_get_input_focus_cookie_t cookie;
1121
1122    cookie = xcb_get_input_focus_unchecked(_ecore_xcb_conn);
1123    _ecore_xcb_cookie_cache(cookie.sequence);
1124 }
1125
1126 /**
1127  * Gets the reply of the GetInputFocus request sent by ecore_x_get_input_focus_prefetch().
1128  * @ingroup Ecore_X_Window_Input_Focus_Group
1129  */
1130 EAPI void
1131 ecore_x_get_input_focus_fetch(void)
1132 {
1133    xcb_get_input_focus_cookie_t cookie;
1134    xcb_get_input_focus_reply_t *reply;
1135
1136    cookie.sequence = _ecore_xcb_cookie_get();
1137    reply = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie, NULL);
1138    _ecore_xcb_reply_cache(reply);
1139 }
1140
1141 /**
1142  * Gets the window that has focus.
1143  * @return  The window that has focus.
1144  *
1145  * Returns the window that has the focus. If an error aoocured, @c 0
1146  * is returned, otherwise the function returns the window that has focus.
1147  *
1148  * To use this function, you must call before, and in order,
1149  * ecore_x_get_input_focus_prefetch(), which sends the GetInputFocus request,
1150  * then ecore_x_get_input_focus_fetch(), which gets the reply.
1151  * @ingroup Ecore_X_Window_Input_Focus_Group
1152  */
1153 EAPI Ecore_X_Window
1154 ecore_x_window_focus_get(void)
1155 {
1156    xcb_get_input_focus_reply_t *reply;
1157    Ecore_X_Window               window = 0;
1158
1159    reply = _ecore_xcb_reply_get();
1160    if (!reply) return window;
1161
1162    return reply->focus;
1163 }
1164
1165
1166 /**
1167  * @defgroup Ecore_X_Window_Get_Attributes_Group X Window Get Attributes Functions
1168  *
1169  * Functions that get the attributes of a window.
1170  */
1171
1172
1173 /**
1174  * Sends the GetWindowAttributes request.
1175  * @ingroup Ecore_X_Window_Get_Attributes_Group
1176  */
1177 EAPI void
1178 ecore_x_get_window_attributes_prefetch(Ecore_X_Window window)
1179 {
1180    xcb_get_window_attributes_cookie_t cookie;
1181
1182    cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
1183    _ecore_xcb_cookie_cache(cookie.sequence);
1184 }
1185
1186 /**
1187  * Gets the reply of the GetWindowAttributes request sent by ecore_x_get_window_attributes_prefetch().
1188  * @ingroup Ecore_X_Window_Get_Attributes_Group
1189  */
1190 EAPI void
1191 ecore_x_get_window_attributes_fetch(void)
1192 {
1193    xcb_get_window_attributes_cookie_t cookie;
1194    xcb_get_window_attributes_reply_t *reply;
1195
1196    cookie.sequence = _ecore_xcb_cookie_get();
1197    reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL);
1198    _ecore_xcb_reply_cache(reply);
1199 }
1200
1201 /**
1202  * Retrieves the attributes of a window.
1203  * @param windows Unused.
1204  * @param att_ret Pointer to an Ecore_X_Window_Attributes
1205  *                  structure in which the attributes of a window
1206  *                  are to be stored.
1207  *
1208  * Retrieves the attributes of a window. If
1209  * @p att_ret is @c NULL, the function does nothing. If an error
1210  * occurred, @p att_ret is set to 0. Otherwise, the @p att_ret structure
1211  * is filled with the attributes os the requested window.
1212  *
1213  * To use this function, you must call before, and in order,
1214  * ecore_x_get_window_attributes_prefetch(), which sends the GetWindowAttributes request,
1215  * then ecore_x_get_window_attributes_fetch(), which gets the reply.
1216  * @ingroup Ecore_X_Window_Get_Attributes_Group
1217  */
1218 EAPI int
1219 ecore_x_window_attributes_get(Ecore_X_Window             window __UNUSED__,
1220                               Ecore_X_Window_Attributes *att_ret)
1221 {
1222    xcb_get_window_attributes_reply_t *reply;
1223
1224    if (!att_ret) return 0;
1225
1226    reply = _ecore_xcb_reply_get();
1227    if (!reply) return 0;
1228
1229    memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes));
1230
1231    if (reply->map_state != XCB_MAP_STATE_UNMAPPED) att_ret->visible = 1;
1232    if (reply->map_state == XCB_MAP_STATE_VIEWABLE) att_ret->viewable = 1;
1233    if (reply->override_redirect) att_ret->override = 1;
1234    if (reply->_class == XCB_WINDOW_CLASS_INPUT_ONLY) att_ret->input_only = 1;
1235    if (reply->save_under) att_ret->save_under = 1;
1236
1237    att_ret->event_mask.mine         = reply->your_event_mask;
1238    att_ret->event_mask.all          = reply->all_event_masks;
1239    att_ret->event_mask.no_propagate = reply->do_not_propagate_mask;
1240    att_ret->window_gravity          = reply->win_gravity;
1241    att_ret->pixel_gravity           = reply->bit_gravity;
1242    att_ret->colormap                = reply->colormap;
1243    att_ret->visual                  = reply->visual;
1244
1245    return 1;
1246 }
1247
1248 /**
1249  * Finds out whether the given window is currently visible.
1250  * @param  window Unused.
1251  * @return        1 if the window is visible, otherwise 0.
1252  *
1253  * Finds out whether the given window is currently visible.
1254  * If an error occurred, or if the window is not visible, 0 is
1255  * returned. Otherwise 1 is returned.
1256  *
1257  * To use this function, you must call before, and in order,
1258  * ecore_x_get_window_attributes_prefetch(), which sends the GetWindowAttributes request,
1259  * then ecore_x_get_window_attributes_fetch(), which gets the reply.
1260  * @ingroup Ecore_X_Window_Get_Attributes_Group
1261  */
1262 EAPI int
1263 ecore_x_window_visible_get(Ecore_X_Window window __UNUSED__)
1264 {
1265    xcb_get_window_attributes_reply_t *reply;
1266
1267    reply = _ecore_xcb_reply_get();
1268    if (!reply) return 0;
1269
1270    return (reply->map_state == XCB_MAP_STATE_VIEWABLE) ? 1 : 0;
1271 }
1272
1273
1274 /**
1275  * Sends the QueryPointer request.
1276  * @ingroup Ecore_X_Window_Parent_Group
1277  */
1278 EAPI void
1279 ecore_x_pointer_xy_get_prefetch(Ecore_X_Window window)
1280 {
1281    xcb_query_pointer_cookie_t cookie;
1282
1283    cookie = xcb_query_pointer_unchecked(_ecore_xcb_conn, window);
1284    _ecore_xcb_cookie_cache(cookie.sequence);
1285 }
1286
1287 /**
1288  * Gets the reply of the QueryPointer request sent by ecore_x_query_pointer_prefetch().
1289  * @ingroup Ecore_X_Window_Parent_Group
1290  */
1291 EAPI void
1292 ecore_x_pointer_xy_get_fetch(void)
1293 {
1294    xcb_query_pointer_cookie_t cookie;
1295    xcb_query_pointer_reply_t *reply;
1296
1297    cookie.sequence = _ecore_xcb_cookie_get();
1298    reply = xcb_query_pointer_reply(_ecore_xcb_conn, cookie, NULL);
1299    _ecore_xcb_reply_cache(reply);
1300 }
1301
1302 /**
1303  * Retrieves the coordinates of the pointer.
1304  * @param window Unused.
1305  * @param x      The X coordinate of the pointer.
1306  * @param y      The Y coordinate of the pointer.
1307  *
1308  * Retrieves the coordinates of the pointer.
1309  * If the window used in
1310  * ecore_x_query_pointer_prefetch() is not on the same screen than
1311  * the root window or if an error occured, @p x and @p y  are set
1312  * to 0. Otherwise, they are respectively set to the X and Y
1313  * coordinates of the pointer.
1314  *
1315  * To use this function, you must call before, and in order,
1316  * ecore_x_query_pointer_prefetch(), which sends the QueryPointer request,
1317  * then ecore_x_query_pointer_fetch(), which gets the reply.
1318  * @ingroup Ecore_X_Window_Parent_Group
1319  */
1320 EAPI void
1321 ecore_x_pointer_xy_get(Ecore_X_Window window __UNUSED__,
1322                        int           *x,
1323                        int           *y)
1324 {
1325    xcb_query_pointer_reply_t *reply;
1326
1327    reply = _ecore_xcb_reply_get();
1328    if (!reply)
1329      {
1330        if (x) *x = 0;
1331        if (y) *y = 0;
1332
1333        return;
1334      }
1335
1336    if (x) *x = reply->win_x;
1337    if (y) *y = reply->win_y;
1338 }
1339
1340
1341 /**
1342  * Sends the QueryTree request.
1343  * @ingroup Ecore_X_Window_Parent_Group
1344  */
1345 EAPI void
1346 ecore_x_query_tree_prefetch(Ecore_X_Window window)
1347 {
1348    xcb_query_tree_cookie_t cookie;
1349
1350    cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, window);
1351    _ecore_xcb_cookie_cache(cookie.sequence);
1352 }
1353
1354 /**
1355  * Gets the reply of the QueryTree request sent by ecore_x_query_tree_prefetch().
1356  * @ingroup Ecore_X_Window_Parent_Group
1357  */
1358 EAPI void
1359 ecore_x_query_tree_fetch(void)
1360 {
1361    xcb_query_tree_cookie_t cookie;
1362    xcb_query_tree_reply_t *reply;
1363
1364    cookie.sequence = _ecore_xcb_cookie_get();
1365    reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL);
1366    _ecore_xcb_reply_cache(reply);
1367 }
1368
1369 /**
1370  * Retrieves the parent window of the given window.
1371  * @param   window Unused.
1372  * @return         The parent window of @p window.
1373  *
1374  * Retrieves the parent window of the given window. If
1375  * an error occured, @c 0 is returned.
1376  *
1377  * To use this function, you must call before, and in order,
1378  * ecore_x_query_tree_prefetch(), which sends the QueryTree request,
1379  * then ecore_x_query_tree_fetch(), which gets the reply.
1380  * @ingroup Ecore_X_Window_Parent_Group
1381  */
1382 EAPI Ecore_X_Window
1383 ecore_x_window_parent_get(Ecore_X_Window window __UNUSED__)
1384 {
1385    xcb_query_tree_reply_t *reply;
1386
1387    reply = _ecore_xcb_reply_get();
1388    if (!reply) return 0;
1389
1390    return reply->parent;
1391 }
1392
1393
1394 /**
1395  * Retrieves the children windows of the given window.
1396  * @param   window Unused.
1397  * @param   num    children windows count.
1398  * @return         The children windows.
1399  *
1400  * Retrieves the children windows of the given window. If
1401  * an error occured, @c 0 is returned.
1402  *
1403  * To use this function, you must call before, and in order,
1404  * ecore_x_query_tree_prefetch(), which sends the QueryTree request,
1405  * then ecore_x_query_tree_fetch(), which gets the reply.
1406  * @ingroup Ecore_X_Window_Parent_Group
1407  */
1408 EAPI Ecore_X_Window *
1409 ecore_x_window_children_get(Ecore_X_Window window __UNUSED__,
1410                             int           *num)
1411 {
1412    xcb_query_tree_reply_t *reply;
1413    Ecore_X_Window         *windows = NULL;
1414
1415    if (num) *num = 0;
1416    reply = _ecore_xcb_reply_get();
1417    if (!reply) return NULL;
1418
1419    windows = malloc(sizeof(Ecore_X_Window) * reply->children_len);
1420    if (!windows)
1421      return NULL;
1422
1423    if (num) *num = reply->children_len;
1424    memcpy(windows,
1425           xcb_query_tree_children(reply),
1426           sizeof(Ecore_X_Window) * reply->children_len);
1427
1428    return windows;
1429 }
1430
1431 /* FIXME: I've tried to remove the round trips. 3 cookies are */
1432 /*        created at the beginning of the function. Because of */
1433 /*        the recursivity of the algo, I can't find better trick */
1434 static Ecore_X_Window
1435 _ecore_x_window_at_xy_get(Ecore_X_Window  base,
1436                           int16_t         base_x,
1437                           int16_t         base_y,
1438                           int16_t         x,
1439                           int16_t         y,
1440                           Ecore_X_Window *skip,
1441                           int             skip_num)
1442 {
1443    xcb_window_iterator_t              iter_children;
1444    xcb_get_window_attributes_cookie_t cookie_get_window_attributes;
1445    xcb_get_geometry_cookie_t          cookie_get_geometry;
1446    xcb_query_tree_cookie_t            cookie_query_tree;
1447    xcb_get_window_attributes_reply_t *reply_get_window_attributes;
1448    xcb_get_geometry_reply_t          *reply_get_geometry;
1449    xcb_query_tree_reply_t            *reply_query_tree;
1450    Ecore_X_Window                     window = 0;
1451    Ecore_X_Window                     child = 0;
1452    int16_t                            win_x;
1453    int16_t                            win_y;
1454    uint16_t                           win_width;
1455    uint16_t                           win_height;
1456
1457    cookie_get_window_attributes = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, base);
1458    cookie_get_geometry = xcb_get_geometry_unchecked(_ecore_xcb_conn, base);
1459    cookie_query_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, base);
1460
1461    reply_get_window_attributes = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_get_window_attributes, NULL);
1462    if (!reply_get_window_attributes)
1463      {
1464        reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL);
1465        if (reply_get_geometry) free(reply_get_geometry);
1466        reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
1467        if (reply_query_tree) free(reply_query_tree);
1468        return window;
1469      }
1470
1471    if (reply_get_window_attributes->map_state != XCB_MAP_STATE_VIEWABLE)
1472      {
1473        free(reply_get_window_attributes);
1474        reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL);
1475        if (reply_get_geometry) free(reply_get_geometry);
1476        reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
1477        if (reply_query_tree) free(reply_query_tree);
1478        return window;
1479      }
1480
1481    free(reply_get_window_attributes);
1482
1483    reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL);
1484    if (!reply_get_geometry)
1485      {
1486        reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
1487        if (reply_query_tree) free(reply_query_tree);
1488        return window;
1489      }
1490
1491    win_x = reply_get_geometry->x;
1492    win_y = reply_get_geometry->y;
1493    win_width = reply_get_geometry->width;
1494    win_height = reply_get_geometry->height;
1495
1496    free(reply_get_geometry);
1497
1498    win_x += base_x;
1499    win_y += base_y;
1500
1501    if (!((x >= win_x) &&
1502          (y >= win_y) &&
1503          (x < (int16_t)(win_x + win_width)) &&
1504          (y < (int16_t)(win_y + win_height))))
1505      {
1506        reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
1507        if (reply_query_tree) free(reply_query_tree);
1508        return window;
1509      }
1510
1511    reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
1512    if (!reply_query_tree)
1513      {
1514         if (skip)
1515           {
1516              int i;
1517
1518              for (i = 0; i < skip_num; i++)
1519                if (base == skip[i])
1520                  return window;
1521           }
1522         return base;
1523      }
1524
1525    iter_children = xcb_query_tree_children_iterator(reply_query_tree);
1526    for (; iter_children.rem; xcb_window_next(&iter_children))
1527      {
1528         if (skip)
1529           {
1530              int j;
1531
1532              for (j = 0; j < skip_num; j++)
1533                if (*iter_children.data == skip[j])
1534                  continue;
1535           }
1536         child = _ecore_x_window_at_xy_get(*iter_children.data, win_x, win_y, x, y, skip, skip_num);
1537         if (child)
1538           {
1539              free(reply_query_tree);
1540
1541              return child;
1542           }
1543      }
1544
1545    if (skip)
1546      {
1547         int i;
1548
1549         for (i = 0; i < skip_num; i++)
1550           if (base == skip[i])
1551             {
1552                /* We return 0. child has an xid equal to 0 */
1553                free(reply_query_tree);
1554                return child;
1555             }
1556      }
1557
1558    free(reply_query_tree);
1559
1560    return base;
1561 }
1562
1563 /**
1564  * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions
1565  *
1566  * Functions that change or retrieve the geometry of X windows.
1567  */
1568
1569 /**
1570  * Retrieves the top, visible window at the given location.
1571  * @param   x The given X position.
1572  * @param   y The given Y position.
1573  * @return    The window at that position.
1574  * @ingroup Ecore_X_Window_Geometry_Group
1575  */
1576 EAPI Ecore_X_Window
1577 ecore_x_window_at_xy_get(int x,
1578                            int y)
1579 {
1580    Ecore_X_Window window;
1581    Ecore_X_Window root;
1582
1583    /* FIXME: Proper function to determine current root/virtual root
1584     * window missing here */
1585    root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
1586
1587    ecore_x_grab();
1588    window = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0);
1589    ecore_x_ungrab();
1590
1591    return window ? window : root;
1592 }
1593
1594 /**
1595  * Retrieves the top, visible window at the given location,
1596  * but skips the windows in the list.
1597  * @param   x The given X position.
1598  * @param   y The given Y position.
1599  * @return    The window at that position.
1600  * @ingroup Ecore_X_Window_Geometry_Group
1601  */
1602 EAPI Ecore_X_Window
1603 ecore_x_window_at_xy_with_skip_get(int             x,
1604                                      int             y,
1605                                      Ecore_X_Window *skip,
1606                                      int             skip_num)
1607 {
1608    Ecore_X_Window window;
1609    Ecore_X_Window root;
1610
1611    /* FIXME: Proper function to determine current root/virtual root
1612     * window missing here */
1613    root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
1614
1615    ecore_x_grab();
1616    window = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num);
1617    ecore_x_ungrab();
1618
1619    return window ? window : root;
1620 }
1621
1622 /**
1623  * Retrieves the top, visible window at the given location,
1624  * but begins at the @p begin window instead of the root one.
1625  * @param   begin The window from which we begin.
1626  * @param   x     The given X position.
1627  * @param   y     The given Y position.
1628  * @return        The window at that position.
1629  * @ingroup Ecore_X_Window_Geometry_Group
1630  */
1631 EAPI Ecore_X_Window
1632 ecore_x_window_at_xy_begin_get(Ecore_X_Window begin,
1633                                int            x,
1634                                int            y)
1635 {
1636    Ecore_X_Window window;
1637
1638    ecore_x_grab();
1639    window = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0);
1640    ecore_x_ungrab();
1641
1642    return window ? window : begin;
1643 }
1644
1645
1646
1647 /* FIXME: Should I provide the replies (or the cookies), instead of
1648           creating them in the function ? */
1649 #ifdef ECORE_XCB_RENDER
1650 static Ecore_X_Window
1651 _ecore_x_window_argb_internal_new(Ecore_X_Window parent,
1652                                   int16_t        x,
1653                                   int16_t        y,
1654                                   uint16_t       w,
1655                                   uint16_t       h,
1656                                   uint8_t        override_redirect,
1657                                   uint8_t        save_under)
1658 {
1659    uint32_t                               value_list[10];
1660    xcb_depth_iterator_t                   iter_depth;
1661    xcb_visualtype_iterator_t              iter_visualtype;
1662    xcb_render_query_pict_formats_cookie_t cookie_pict_format;
1663    xcb_render_query_pict_formats_reply_t *rep_pict_format;
1664    Ecore_X_Screen                        *screen = NULL;
1665    Ecore_X_Window                         win = { 0 };
1666    xcb_visualid_t                         vis = { 0 };
1667    Ecore_X_Colormap                       colormap;
1668    uint32_t                               value_mask;
1669
1670    cookie_pict_format = xcb_render_query_pict_formats_unchecked(_ecore_xcb_conn);
1671
1672    if (parent == 0)
1673      {
1674         parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
1675         screen = ((xcb_screen_t *)_ecore_xcb_screen);
1676      }
1677    else
1678      {
1679         xcb_screen_iterator_t     iter_screen;
1680         xcb_get_geometry_reply_t *rep;
1681         Ecore_X_Drawable        draw;
1682         Ecore_X_Window          root;
1683
1684         draw = parent;
1685         rep = xcb_get_geometry_reply(_ecore_xcb_conn,
1686                                      xcb_get_geometry_unchecked(_ecore_xcb_conn,
1687                                                                 draw),
1688                                      NULL);
1689         if (!rep)
1690           return win;
1691
1692         root = rep->root;
1693
1694         free(rep);
1695
1696         for (; iter_screen.rem; xcb_screen_next(&iter_screen))
1697           {
1698              if (iter_screen.data->root == root)
1699                {
1700                  screen = iter_screen.data;
1701                }
1702           }
1703      }
1704    if (!screen)
1705      return win;
1706
1707    /* we get the X visual types */
1708    iter_depth = xcb_screen_allowed_depths_iterator(screen);
1709    for (; iter_depth.rem; xcb_depth_next(&iter_depth)) {
1710         if (iter_depth.data->depth == 32) {
1711              iter_visualtype = xcb_depth_visuals_iterator(iter_depth.data);
1712              break;
1713         }
1714    }
1715
1716    /* we get the X render visual id */
1717    rep_pict_format = xcb_render_query_pict_formats_reply(_ecore_xcb_conn,
1718                                                          cookie_pict_format,
1719                                                          NULL);
1720    if (!rep_pict_format)
1721      return win;
1722
1723    for (; iter_visualtype.rem; xcb_visualtype_next(&iter_visualtype)) {
1724       if (iter_visualtype.data->_class == XCB_VISUAL_CLASS_TRUE_COLOR) {
1725          xcb_render_pictforminfo_iterator_t iter_forminfo;
1726          xcb_render_pictscreen_iterator_t   iter_pictscreen;
1727          xcb_render_pictformat_t            pict_format = { 0 };
1728
1729          iter_forminfo = xcb_render_query_pict_formats_formats_iterator(rep_pict_format);
1730          for (; iter_forminfo.rem; xcb_render_pictforminfo_next(&iter_forminfo)) {
1731             if (iter_forminfo.data->type == XCB_RENDER_PICT_TYPE_DIRECT &&
1732                 iter_forminfo.data->direct.alpha_mask && iter_forminfo.data->depth == 32) {
1733                pict_format = iter_forminfo.data->id;
1734                break;
1735             }
1736          }
1737          if (pict_format == 0) {
1738             free(rep_pict_format);
1739             return win;
1740          }
1741          iter_pictscreen = xcb_render_query_pict_formats_screens_iterator(rep_pict_format);
1742          for (; iter_pictscreen.rem; xcb_render_pictscreen_next(&iter_pictscreen)) {
1743             xcb_render_pictdepth_iterator_t iter_depth;
1744
1745             iter_depth = xcb_render_pictscreen_depths_iterator(iter_pictscreen.data);
1746             for (; iter_depth.rem; xcb_render_pictdepth_next(&iter_depth)) {
1747                xcb_render_pictvisual_iterator_t iter_visual;
1748
1749                iter_visual = xcb_render_pictdepth_visuals_iterator(iter_depth.data);
1750                for (; iter_visual.rem; xcb_render_pictvisual_next(&iter_visual)) {
1751                   if ((iter_visual.data->visual == iter_visualtype.data->visual_id) &&
1752                       (pict_format == iter_visual.data->format)) {
1753                     vis = iter_visual.data->visual;
1754                     break;
1755                   }
1756                }
1757             }
1758          }
1759       }
1760    }
1761
1762    free(rep_pict_format);
1763
1764    if (vis == 0)
1765      return win;
1766
1767    colormap = xcb_generate_id(_ecore_xcb_conn);
1768    xcb_create_colormap(_ecore_xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap, parent, vis);
1769
1770    value_mask =
1771      XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL  | XCB_CW_BIT_GRAVITY       |
1772      XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT |
1773      XCB_CW_SAVE_UNDER  | XCB_CW_EVENT_MASK    | XCB_CW_DONT_PROPAGATE    |
1774      XCB_CW_COLORMAP;
1775
1776    value_list[0]  = XCB_NONE;
1777    value_list[1]  = 0;
1778    value_list[2]  = XCB_GRAVITY_NORTH_WEST;
1779    value_list[3]  = XCB_GRAVITY_NORTH_WEST;
1780    value_list[4]  = XCB_BACKING_STORE_NOT_USEFUL;
1781    value_list[5]  = override_redirect;
1782    value_list[6]  = save_under;
1783    value_list[7]  =
1784      XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
1785      XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
1786      XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
1787      XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
1788      XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
1789      XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
1790      XCB_EVENT_MASK_COLOR_MAP_CHANGE;
1791    value_list[8]  = XCB_EVENT_MASK_NO_EVENT;
1792    value_list[9]  = colormap;
1793
1794    win = xcb_generate_id(_ecore_xcb_conn);
1795    xcb_create_window(_ecore_xcb_conn,
1796                      32, /* depth */
1797                      win, parent,
1798                      x, y, w, h, 0,
1799                      XCB_WINDOW_CLASS_INPUT_OUTPUT,
1800                      vis,
1801                      value_mask,
1802                      value_list);
1803
1804    xcb_free_colormap(_ecore_xcb_conn, colormap);
1805
1806    if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root)
1807      ecore_x_window_defaults_set(win);
1808
1809    return win;
1810 }
1811 #endif /* ECORE_XCB_RENDER */
1812
1813
1814
1815 /* FIXME: round trip */
1816 EAPI int
1817 ecore_x_window_argb_get(Ecore_X_Window win)
1818 {
1819    uint8_t                                ret = 0;
1820 #ifdef ECORE_XCB_RENDER
1821    xcb_render_pictforminfo_iterator_t     iter_forminfo;
1822    xcb_render_pictscreen_iterator_t       iter_pictscreen;
1823    xcb_render_pictformat_t                pict_format = { 0 };
1824    xcb_render_query_pict_formats_reply_t *rep_pictformat;
1825    xcb_get_window_attributes_reply_t     *rep;
1826    xcb_visualid_t                         visual;
1827
1828    rep = xcb_get_window_attributes_reply(_ecore_xcb_conn,
1829                                          xcb_get_window_attributes_unchecked(_ecore_xcb_conn,
1830                                                                              win),
1831                                          NULL);
1832    if (!rep)
1833      return ret;
1834
1835    visual = rep->visual;
1836
1837    free(rep);
1838
1839    rep_pictformat = xcb_render_query_pict_formats_reply(_ecore_xcb_conn,
1840                                                         xcb_render_query_pict_formats_unchecked(_ecore_xcb_conn),
1841                                                         NULL);
1842    if (!rep_pictformat)
1843      return ret;
1844
1845    iter_forminfo = xcb_render_query_pict_formats_formats_iterator(rep_pictformat);
1846    for (; iter_forminfo.rem; xcb_render_pictforminfo_next(&iter_forminfo))
1847      {
1848         if ((iter_forminfo.data->type == XCB_RENDER_PICT_TYPE_DIRECT) &&
1849             (iter_forminfo.data->direct.alpha_mask))
1850           {
1851              pict_format = iter_forminfo.data->id;
1852              break;
1853           }
1854      }
1855    if (pict_format == 0)
1856      {
1857         free(rep_pictformat);
1858
1859         return ret;
1860      }
1861
1862    iter_pictscreen = xcb_render_query_pict_formats_screens_iterator(rep_pictformat);
1863    for (; iter_pictscreen.rem; xcb_render_pictscreen_next(&iter_pictscreen))
1864      {
1865         xcb_render_pictdepth_iterator_t iter_depth;
1866
1867         iter_depth = xcb_render_pictscreen_depths_iterator(iter_pictscreen.data);
1868         for (; iter_depth.rem; xcb_render_pictdepth_next(&iter_depth))
1869           {
1870              xcb_render_pictvisual_iterator_t iter_visual;
1871
1872              iter_visual = xcb_render_pictdepth_visuals_iterator(iter_depth.data);
1873              for (; iter_visual.rem; xcb_render_pictvisual_next(&iter_visual))
1874                {
1875                   if ((iter_visual.data->visual == visual) &&
1876                       (pict_format == iter_visual.data->format))
1877                     {
1878                        ret = 1;
1879                        break;
1880                     }
1881                }
1882           }
1883      }
1884
1885    free(rep_pictformat);
1886 #endif /* ECORE_XCB_RENDER */
1887
1888    return ret;
1889 }
1890
1891
1892
1893
1894 /**
1895  * Set if a window should be ignored.
1896  * @param   window The given window.
1897  * @param   ignore if to ignore
1898  */
1899 EAPI void
1900 ecore_x_window_ignore_set(Ecore_X_Window window,
1901                           int            ignore)
1902 {
1903    int i, j;
1904
1905    if (ignore)
1906      {
1907         if (ignore_list)
1908           {
1909              for (i = 0; i < ignore_num; i++)
1910                {
1911                   if (window == ignore_list[i])
1912                     return;
1913                }
1914              ignore_list = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window));
1915              if (!ignore_list) return;
1916              ignore_list[ignore_num++] = window;
1917           }
1918         else
1919           {
1920              ignore_num = 0;
1921              ignore_list = malloc(sizeof(Ecore_X_Window));
1922              ignore_list[ignore_num++] = window;
1923           }
1924      }
1925    else
1926      {
1927         if (!ignore_list) return;
1928         for (i = 0, j = 0; i < ignore_num; i++)
1929           {
1930              if (window != ignore_list[i])
1931                ignore_list[i] = ignore_list[j++];
1932              else
1933                ignore_num--;
1934           }
1935         ignore_list = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window));
1936      }
1937 }
1938
1939 /**
1940  * Get the ignore list
1941  * @param   num number of windows in the list
1942  * @return  list of windows to ignore
1943  */
1944 EAPI Ecore_X_Window *
1945 ecore_x_window_ignore_list(int *num)
1946 {
1947    if (num) *num = ignore_num;
1948    return ignore_list;
1949 }
1950
1951 /**
1952  * Retrieves the size of the given window.
1953  * @param   win The given window.
1954  * @param   w   Pointer to an integer into which the width is to be stored.
1955  * @param   h   Pointer to an integer into which the height is to be stored.
1956  *
1957  * To use this function, you must call before, and in order,
1958  * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request,
1959  * then ecore_x_drawable_geometry_get_fetch(), which gets the reply.
1960  * @ingroup Ecore_X_Window_Geometry_Group
1961  */
1962 EAPI void
1963 ecore_x_window_size_get(Ecore_X_Window window,
1964                         int           *width,
1965                         int           *height)
1966 {
1967    if (window == 0)
1968       window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
1969
1970    ecore_x_drawable_geometry_get(window, NULL, NULL, width, height);
1971 }
1972
1973 /**
1974  * Retrieves the geometry of the given window.
1975  * @param   win The given window.
1976  * @param   x   Pointer to an integer in which the X position is to be stored.
1977  * @param   y   Pointer to an integer in which the Y position is to be stored.
1978  * @param   w   Pointer to an integer in which the width is to be stored.
1979  * @param   h   Pointer to an integer in which the height is to be stored.
1980  *
1981  * To use this function, you must call before, and in order,
1982  * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request,
1983  * then ecore_x_drawable_geometry_get_fetch(), which gets the reply.
1984  * @ingroup Ecore_X_Window_Geometry_Group
1985  */
1986 EAPI void
1987 ecore_x_window_geometry_get(Ecore_X_Window window,
1988                             int           *x,
1989                             int           *y,
1990                             int           *width,
1991                             int           *height)
1992 {
1993    if (!window)
1994       window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
1995
1996    ecore_x_drawable_geometry_get(window, x, y, width, height);
1997 }
1998
1999 /**
2000  * Retrieves the width of the border of the given window.
2001  * @param   win The given window.
2002  * @return  Width of the border of @p win.
2003  * @ingroup Ecore_X_Window_Geometry_Group
2004  */
2005 EAPI int
2006 ecore_x_window_border_width_get(Ecore_X_Window win)
2007 {
2008    /* doesn't make sense to call this on a root window */
2009    if (!win)
2010       return 0;
2011
2012    return ecore_x_drawable_border_width_get(win);
2013 }
2014
2015 /**
2016  * Retrieves the depth of the given window.
2017  * @param  win The given window.
2018  * @return Depth of the window.
2019  */
2020 EAPI int
2021 ecore_x_window_depth_get(Ecore_X_Window win)
2022 {
2023    return ecore_x_drawable_depth_get(win);
2024 }