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