13026b16915a05a8b4d2bf34622bee3809bb8510
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_netwm.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 /*
6  * _NET_WM... aka Extended Window Manager Hint (EWMH) functions.
7  */
8
9 #include "Ecore_Data.h"
10 #include "ecore_xcb_private.h"
11 #include "Ecore_X_Atoms.h"
12
13
14 /**
15  * @defgroup Ecore_X_NetWM_Group Extended Window Manager Hint (EWMH) functions
16  *
17  * Functions related to the Extended Window Manager Hint (EWMH).
18  */
19
20
21 typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info;
22
23 struct _Ecore_X_Startup_Info
24 {
25    Ecore_X_Window win;
26
27    int   init;
28
29    int   buffer_size;
30    char *buffer;
31
32    int   length;
33
34    /* These are the sequence info fields */
35    char *id;
36    char *name;
37    int   screen;
38    char *bin;
39    char *icon;
40    int   desktop;
41    int   timestamp;
42    char *description;
43    char *wmclass;
44    int   silent;
45 };
46
47 #if 0
48 static void  _ecore_x_window_prop_string_utf8_get_prefetch(Ecore_X_Window window, Ecore_X_Atom atom);
49 static void  _ecore_x_window_prop_string_utf8_get_fetch(void);
50 #endif
51 static void  _ecore_x_window_prop_string_utf8_set(Ecore_X_Window window, Ecore_X_Atom atom, const char *str);
52 static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window window, Ecore_X_Atom atom);
53 #if 0 /* Unused */
54 static int   _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info);
55 static int   _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, char *data);
56 #endif
57 static void  _ecore_x_netwm_startup_info_free(void *data);
58
59 /*
60  * Local variables
61  */
62
63 static Ecore_Hash *startup_info = NULL;
64
65 /**
66  * Initialize the NetWM module
67  */
68 EAPI void
69 ecore_x_netwm_init(void)
70 {
71    startup_info = ecore_hash_new(ecore_direct_hash, ecore_direct_compare);
72    if (startup_info)
73      {
74         ecore_hash_free_value_cb_set(startup_info, _ecore_x_netwm_startup_info_free);
75      }
76 }
77
78 /**
79  * Shutdown the NetWM module
80  */
81 EAPI void
82 ecore_x_netwm_shutdown(void)
83 {
84    if (startup_info)
85      ecore_hash_destroy(startup_info);
86    startup_info = NULL;
87 }
88
89 /**
90  * Set the _NET_SUPPORTING_WM_CHECK property.
91  * @param root    The root window.
92  * @param check   The child window.
93  * @param wm_name The name of the Window Manager.
94  *
95  * Set the _NET_SUPPORTING_WM_CHECK property on the @p root window to be
96  * the ID of the child window @p check created by the Window Manager.
97  * @p check also have the _NET_WM_NAME property set to the name
98  * @p wm_name of the Window Manager.
99  *
100  * The Window MUST call that function to indicate that a compliant
101  * window manager is active.
102  * @ingroup Ecore_X_NetWM_Group
103  */
104 EAPI void
105 ecore_x_netwm_wm_identify(Ecore_X_Window root,
106                           Ecore_X_Window check,
107                           const char    *wm_name)
108 {
109    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1);
110    ecore_x_window_prop_window_set(check, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1);
111    _ecore_x_window_prop_string_utf8_set(check, ECORE_X_ATOM_NET_WM_NAME, wm_name);
112    /* This one isn't mandatory */
113    _ecore_x_window_prop_string_utf8_set(root, ECORE_X_ATOM_NET_WM_NAME, wm_name);
114 }
115
116 /**
117  * Set the _NET_SUPPORTED property.
118  * @param root      The root window.
119  * @param supported The supported hints.
120  * @param num       The number of hints.
121  *
122  * Set the _NET_SUPPORTED property on the @p root window. The hints
123  * that the Window Manager supports are stored in @p supported.
124  *
125  * The Window Manager MUST set this property to indicate which hints
126  * it supports.
127  * @ingroup Ecore_X_NetWM_Group
128  */
129 EAPI void
130 ecore_x_netwm_supported_set(Ecore_X_Window root,
131                             Ecore_X_Atom  *supported,
132                             int            num)
133 {
134    ecore_x_window_prop_atom_set(root, ECORE_X_ATOM_NET_SUPPORTED, supported, num);
135 }
136
137 /**
138  * Sends the GetProperty request.
139  * @param root The root window
140  * @ingroup Ecore_X_NetWM_Group
141  */
142 EAPI void
143 ecore_x_netwm_supported_get_prefetch(Ecore_X_Window root)
144 {
145    xcb_get_property_cookie_t cookie;
146
147    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, root,
148                                        ECORE_X_ATOM_NET_SUPPORTED, ECORE_X_ATOM_ATOM,
149                                        0, 0x7fffffff);
150    _ecore_xcb_cookie_cache(cookie.sequence);
151 }
152
153 /**
154  * Gets the reply of the GetProperty request sent by ecore_x_netwm_supported_get_prefetch().
155  * @ingroup Ecore_X_NetWM_Group
156  */
157 EAPI void
158 ecore_x_netwm_supported_get_fetch(void)
159 {
160    xcb_get_property_cookie_t cookie;
161    xcb_get_property_reply_t *reply;
162
163    cookie.sequence = _ecore_xcb_cookie_get();
164    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
165    _ecore_xcb_reply_cache(reply);
166 }
167
168 /**
169  * Get the hints supported by the Window Manager.
170  * @param root      The root window.
171  * @param supported The supported hints.
172  * @param num       The number of atoms.
173  * @return          1 on success, 0 otherwise.
174  *
175  * Get the hints supported by the Window Manager. @p root is the root
176  * window. The hints are stored in @p supported. The number of hints
177  * is stored in @p num.
178  *
179  * To use this function, you must call before, and in order,
180  * ecore_x_netwm_supported_get_prefetch(), which sends the GetProperty request,
181  * then ecore_x_netwm_supported_get_fetch(), which gets the reply.
182  * @ingroup Ecore_X_NetWM_Group
183  */
184 EAPI int
185 ecore_x_netwm_supported_get(Ecore_X_Window root,
186                             Ecore_X_Atom **supported,
187                             int           *num)
188 {
189    int num_ret;
190
191    if (num) *num = 0UL;
192    if (supported) *supported = NULL;
193
194    num_ret = ecore_x_window_prop_xid_list_get(root,
195                                               ECORE_X_ATOM_NET_SUPPORTED,
196                                               ECORE_X_ATOM_ATOM,
197                                               supported);
198    if (num_ret <= 0)
199       return 0;
200
201    if (num) *num = (uint32_t)num_ret;
202    return 1;
203 }
204
205 /**
206  * Set the _NET_NUMBER_OF_DESKTOPS property.
207  * @param root The root window.
208  * @param n_desks The number of desktops.
209  *
210  * Set the number of desktops @p n_desks of the Window Manager by
211  * sending the _NET_NUMBER_OF_DESKTOPS to the @p root window.
212  *
213  * The Window Manager SHOULD set and update this property to indicate
214  * the number of virtual desktops. A Pager can request a change in the
215  * number of desktops by using that function.
216  * @ingroup Ecore_X_NetWM_Group
217  */
218 EAPI void
219 ecore_x_netwm_desk_count_set(Ecore_X_Window root,
220                              unsigned int   n_desks)
221 {
222    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS,
223                                   &n_desks, 1);
224 }
225
226 /**
227  * Set the _NET_VIRTUAL_ROOTS property.
228  * @param root    The root window.
229  * @param vroots  The virtual root windows.
230  * @param n_desks The number of desks.
231  *
232  * Set the number of virtual desktops by sending the
233  * _NET_VIRTUAL_ROOTS property to the @p root window. @p vroots is an
234  * array of window and @p n_desks is the number of windows.
235  *
236  * A Window Manager that implements virtual desktops by reparent
237  * client windows to a child of the root window MUST use that
238  * function.
239  * @ingroup Ecore_X_NetWM_Group
240  */
241 EAPI void
242 ecore_x_netwm_desk_roots_set(Ecore_X_Window  root,
243                              Ecore_X_Window *vroots,
244                              unsigned int    n_desks)
245 {
246    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_VIRTUAL_ROOTS, vroots, n_desks);
247 }
248
249 /**
250  * Set the _NET_DESKTOP_NAMES property.
251  * @param root    The root window.
252  * @param names   The names of the virtual desktops.
253  * @param n_desks The number of virtual desktops.
254  *
255  * Set the name of each virtual desktop by sending the
256  * _NET_DESKTOP_NAMES to the @p root window. @p names are the names of
257  * the virtual desktops and @p n_desks is the number of virtual
258  * desktops.
259  *
260  * A Pager MAY use that function. @p n_desks may be different from the
261  * one passed to ecore_x_netwm_desk_count_set().  If it less or equal,
262  * then the desktops with high numbers are unnamed. If it is larger,
263  * then the excess names are considered to be reserved in case the
264  * number of desktops is increased.
265  * @ingroup Ecore_X_NetWM_Group
266  */
267 EAPI void
268 ecore_x_netwm_desk_names_set(Ecore_X_Window root,
269                              const char   **names,
270                              unsigned int   n_desks)
271 {
272    char        ss[32];
273    char       *buf;
274    const char *s;
275    uint32_t    i;
276    uint32_t    len;
277    uint32_t    l;
278
279    buf = NULL;
280    len = 0;
281
282    for (i = 0; i < n_desks; i++)
283      {
284         s = (names) ? names[i] : NULL;
285         if (!s)
286           {
287              /* Default to "Desk-<number>" */
288              sprintf(ss, "Desk-%d", i);
289              s = ss;
290           }
291
292         l = strlen(s) + 1;
293         buf = realloc(buf, len + l);
294         memcpy(buf + len, s, l);
295         len += l;
296      }
297
298    xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, root,
299                        ECORE_X_ATOM_NET_DESKTOP_NAMES,
300                        ECORE_X_ATOM_UTF8_STRING,
301                        8, len, (const void *)buf);
302    free(buf);
303 }
304
305 /**
306  * Set the _NET_DESKTOP_GEOMETRY property.
307  * @param root   The root window.
308  * @param width  The width of the desktop.
309  * @param height The height of the desktop.
310  *
311  * Set the common @p width and @p height of all desktops by sending
312  * the _NET_DESKTOP_GEOMETRY to the @p root window.
313  *
314  * This size is equal to the screen size if the Window Manager doesn't
315  * support large desktops, otherwise it's equal to the virtual size of
316  * the desktop. The Window Manager SHOULD set this property. A Pager
317  * can request a change in the desktop geometry by using this
318  * function.
319  * @ingroup Ecore_X_NetWM_Group
320  */
321 EAPI void
322 ecore_x_netwm_desk_size_set(Ecore_X_Window root,
323                             unsigned int   width,
324                             unsigned int   height)
325 {
326    uint32_t size[2];
327
328    size[0] = width;
329    size[1] = height;
330    ecore_x_window_prop_card32_set(root,
331                                   ECORE_X_ATOM_NET_DESKTOP_GEOMETRY,
332                                   size, 2);
333 }
334
335 /**
336  * Set the _NET_DESKTOP_VIEWPORT property.
337  * @param root    The root window.
338  * @param origins An array of paris of coordiantes.
339  * @param n_desks The number of virtual desktops.
340  *
341  * Set the top left corner of each desktop's viewport by sending the
342  * _NET_DESKTOP_VIEWPORT property to the @p root window. @p origins
343  * contains each pair of X coordinate and Y coordinate of the top left
344  * corner of each desktop's viewport.
345  *
346  * If the Window Manager does not support large desktops, the
347  * coordinates MUST be (0,0). A Pager can request to change the
348  * viewport for the current desktop by using this function.
349  * @ingroup Ecore_X_NetWM_Group
350  */
351 EAPI void
352 ecore_x_netwm_desk_viewports_set(Ecore_X_Window root,
353                                  unsigned int  *origins,
354                                  unsigned int   n_desks)
355 {
356    ecore_x_window_prop_card32_set(root,
357                                   ECORE_X_ATOM_NET_DESKTOP_VIEWPORT,
358                                   origins, 2 * n_desks);
359 }
360
361 /**
362  * Set the _NET_DESKTOP_LAYOUT property.
363  * @param root The root window.
364  * @param orientation
365  * @param columns
366  * @param rows
367  * @param starting_corner
368  *
369  * Set the layout of virtual desktops relative to each other by
370  * sending the _NET_DESKTOP_LAYOUT to the @p root window.
371  * @p orientation defines the orientation of the virtual desktop. 0
372  * means horizontal layout, 1 means vertical layout. @p columns is
373  * the number of desktops in the X direction and @p rows is the number
374  * in the Y direction. @p starting_corner is the corner containing the
375  * first desktop. The values for @p starting_corner are 0 (top-left),
376  * 1 (top-right), 2 (bottom-right) and 3 (bottom-left).
377  *
378  * When the orientation is horizontal the desktops are laid out in
379  * rows, with the first desktop in the specified starting corner. So a
380  * layout with four columns and three rows starting in
381  * the top-left corner looks like this:
382  *
383  * +--+--+--+--+
384  * | 0| 1| 2| 3|
385  * +--+--+--+--+
386  * | 4| 5| 6| 7|
387  * +--+--+--+--+
388  * | 8| 9|10|11|
389  * +--+--+--+--+
390  *
391  * With @p starting_corner being bottom-right, it looks like this:
392  *
393  * +--+--+--+--+
394  * |11|10| 9| 8|
395  * +--+--+--+--+
396  * | 7| 6| 5| 4|
397  * +--+--+--+--+
398  * | 3| 2| 1| 0|
399  * +--+--+--+--+
400  *
401  * When the orientation is vertical the layout with four columns and
402  * three rows starting in the top-left corner looks like:
403  *
404  * +--+--+--+--+
405  * | 0| 3| 6| 9|
406  * +--+--+--+--+
407  * | 1| 4| 7|10|
408  * +--+--+--+--+
409  * | 2| 5| 8|11|
410  * +--+--+--+--+
411  *
412  * With @p starting_corner  being top-right, it looks like:
413  *
414  * +--+--+--+--+
415  * | 9| 6| 3| 0|
416  * +--+--+--+--+
417  * |10| 7| 4| 1|
418  * +--+--+--+--+
419  * |11| 8| 5| 2|
420  * +--+--+--+--+
421  *
422  * This function MUST be used by a Pager and NOT by the Window
423  * Manager. When using this function, the Pager must own a manager
424  * selection.
425  * @ingroup Ecore_X_NetWM_Group
426  */
427 EAPI void
428 ecore_x_netwm_desk_layout_set(Ecore_X_Window root,
429                               int            orientation,
430                               int            columns,
431                               int            rows,
432                               int            starting_corner)
433 {
434    uint32_t layout[4];
435
436    layout[0] = orientation;
437    layout[1] = columns;
438    layout[2] = rows;
439    layout[3] = starting_corner;
440    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT, layout, 4);
441 }
442
443 /**
444  * Set the _NET_WORKAREA property.
445  * @param root    The root window.
446  * @param areas   An array of areas.
447  * @param n_desks The number of desks.
448  *
449  * Set the work area for each desktop by sending the _NET_WORKAREA
450  * property to the @p root window. An area contains the geometry (X
451  * and Y coordinates, width and height). These geometries are
452  * specified relative to the viewport on each desktop and specify an
453  * area that is completely contained within the viewport. @p areas
454  * stores these geometries. @p n_desks is the number of geometry to
455  * set.
456  *
457  * This function MUST be set by the Window Manager. It is used by
458  * desktop applications to place desktop icons appropriately.
459  * @ingroup Ecore_X_NetWM_Group
460  */
461 EAPI void
462 ecore_x_netwm_desk_workareas_set(Ecore_X_Window root,
463                                  unsigned int  *areas,
464                                  unsigned int   n_desks)
465 {
466    ecore_x_window_prop_card32_set(root,
467                                   ECORE_X_ATOM_NET_WORKAREA,
468                                   areas, 4 * n_desks);
469 }
470
471 /**
472  * Set the _NET_CURRENT_DESKTOP property.
473  * @param root The root window.
474  * @param desk The index of the current desktop.
475  *
476  * Set the current desktop by sending the _NET_CURRENT_DESKTOP to the
477  * @p root window. @p deskmust be an integer number between 0 and the
478  * number of desks (set by ecore_x_netwm_desk_count_set()) -1.
479  *
480  * This function MUST be called by the Window Manager. If a Pagerwants
481  * to switch to naother desktop, it MUST call that function.
482  * @ingroup Ecore_X_NetWM_Group
483  */
484 EAPI void
485 ecore_x_netwm_desk_current_set(Ecore_X_Window root,
486                                unsigned int   desk)
487 {
488    ecore_x_window_prop_card32_set(root,
489                                   ECORE_X_ATOM_NET_CURRENT_DESKTOP,
490                                   &desk, 1);
491 }
492
493 /**
494  * Set the _NET_SHOWING_DESKTOP property.
495  * @param root The root window
496  * @param on   0 to hide the desktop, non 0 to show it.
497  *
498  * Set or unset the desktop in a "showing mode" by sending the
499  * _NET_SHOWING_DESKTOP property to the @p root window. If @p on is 0,
500  * the windows are hidden and the desktop background is displayed and
501  * focused.
502  *
503  * If a Pager wants to enter or leave the mode, it MUST use this
504  * function.
505  * @ingroup Ecore_X_NetWM_Group
506  */
507 EAPI void
508 ecore_x_netwm_showing_desktop_set(Ecore_X_Window root,
509                                   int            on)
510 {
511    uint32_t val;
512
513    val = (on) ? 1 : 0;
514    ecore_x_window_prop_card32_set(root,
515                                   ECORE_X_ATOM_NET_SHOWING_DESKTOP,
516                                   &val, 1);
517 }
518
519 /*
520  * Client status
521  */
522
523 /**
524  * Set the _NET_CLIENT_LIST property.
525  * @param root The root window.
526  * @param p_clients An array of windows.
527  * @param n_clients The number of windows.
528  *
529  * Map all the X windows managed by the window manager from the oldest
530  * to the newest by sending the _NET_CLIENT_LIST property to the
531  * @p root window. The X windows are stored in @p p_clients and their
532  * number in @p n_clients.
533  *
534  * This function SHOULD be called by the Window Manager.
535  * @ingroup Ecore_X_NetWM_Group
536  */
537 EAPI void
538 ecore_x_netwm_client_list_set(Ecore_X_Window  root,
539                               Ecore_X_Window *p_clients,
540                               unsigned int    n_clients)
541 {
542    ecore_x_window_prop_window_set(root,
543                                   ECORE_X_ATOM_NET_CLIENT_LIST,
544                                   p_clients, n_clients);
545 }
546
547 /**
548  * Set the _NET_CLIENT_LIST_STACKING property.
549  * @param root The root window.
550  * @param p_clients An array of windows.
551  * @param n_clients The number of windows.
552  *
553  * Stack all the X windows managed by the window manager from bottom
554  * to top order by sending the _NET_CLIENT_LIST_STACKING property to the
555  * @p root window. The X windows are stored in @p p_clients and their
556  * number in @p n_clients.
557  *
558  * This function SHOULD be called by the Window Manager.
559  * @ingroup Ecore_X_NetWM_Group
560  */
561 EAPI void
562 ecore_x_netwm_client_list_stacking_set(Ecore_X_Window  root,
563                                        Ecore_X_Window *p_clients,
564                                        unsigned int    n_clients)
565 {
566    ecore_x_window_prop_window_set(root,
567                                   ECORE_X_ATOM_NET_CLIENT_LIST_STACKING,
568                                   p_clients, n_clients);
569 }
570
571 /**
572  * Set the _NET_ACTIVE_WINDOW property.
573  * @param root   The root window.
574  * @param window The widow to activate.
575  *
576  * Activate @p window by sending the _NET_ACTIVE_WINDOW property to
577  * the @p root window.
578  *
579  * If a Client wants to activate another window, it MUST call this
580  * function.
581  * @ingroup Ecore_X_NetWM_Group
582  */
583 EAPI void
584 ecore_x_netwm_client_active_set(Ecore_X_Window root,
585                                 Ecore_X_Window window)
586 {
587    ecore_x_window_prop_window_set(root,
588                                   ECORE_X_ATOM_NET_ACTIVE_WINDOW,
589                                   &window, 1);
590 }
591
592 /**
593  * Set the _NET_WM_NAME property.
594  * @param window The widow to activate.
595  * @param name   The title name of the window.
596  *
597  * Set the title name of @p window to @p name by sending the
598  * _NET_WM_NAME property to @p window.
599  *
600  * The Client SHOULD set the title of @p window in UTF-8 encoding. If
601  * set, the Window Manager should use this in preference to WM_NAME.
602  * @ingroup Ecore_X_NetWM_Group
603  */
604 EAPI void
605 ecore_x_netwm_name_set(Ecore_X_Window window,
606                        const char    *name)
607 {
608    _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_NAME, name);
609 }
610
611 /**
612  * Sends the GetProperty request.
613  * @param window The window.
614  * @ingroup Ecore_X_NetWM_Group
615  */
616 EAPI void
617 ecore_x_netwm_name_get_prefetch(Ecore_X_Window window)
618 {
619    xcb_get_property_cookie_t cookie;
620
621    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
622                                        ECORE_X_ATOM_NET_WM_NAME, ECORE_X_ATOM_UTF8_STRING,
623                                        0, 0x7fffffff);
624    _ecore_xcb_cookie_cache(cookie.sequence);
625 }
626
627 /**
628  * Gets the reply of the GetProperty request sent by ecore_x_netwm_name_get_prefetch().
629  * @ingroup Ecore_X_NetWM_Group
630  */
631 EAPI void
632 ecore_x_netwm_name_get_fetch(void)
633 {
634    xcb_get_property_cookie_t cookie;
635    xcb_get_property_reply_t *reply;
636
637    cookie.sequence = _ecore_xcb_cookie_get();
638    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
639    _ecore_xcb_reply_cache(reply);
640 }
641
642 /**
643  * Get the title of a window.
644  * @param window The window.
645  * @param name   The title name.
646  * @return       Returns always 1.
647  *
648  * Retrieve the title name of @p window and store it in @p name. The
649  * function returns always 1.
650  *
651  * To use this function, you must call before, and in order,
652  * ecore_x_netwm_name_get_prefetch(), which sends the GetProperty request,
653  * then ecore_x_netwm_name_get_fetch(), which gets the reply.
654  * @ingroup Ecore_X_NetWM_Group
655  */
656 EAPI int
657 ecore_x_netwm_name_get(Ecore_X_Window window,
658                        char         **name)
659 {
660    if (name)
661      *name = _ecore_x_window_prop_string_utf8_get(window, ECORE_X_ATOM_NET_WM_NAME);
662    return 1;
663 }
664
665 /**
666  * Set the _NET_STARTUP_ID property.
667  * @param window The window.
668  * @param id     The ID name.
669  *
670  * Set the ID @p id used for the startup sequence by sending the
671  * property _NET_STARTUP_ID to @p window. The ID name should be
672  * encoded in UTF-8.
673  *
674  * If a new value for the property is set, the Window Manager
675  * should update the window's status accordingly (update its virtual
676  * desktop, etc.).
677  * @ingroup Ecore_X_NetWM_Group
678  */
679 EAPI void
680 ecore_x_netwm_startup_id_set(Ecore_X_Window window,
681                              const char    *id)
682 {
683    _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_STARTUP_ID, id);
684 }
685
686 /**
687  * Sends the GetProperty request.
688  * @param window The window.
689  * @ingroup Ecore_X_NetWM_Group
690  */
691 EAPI void
692 ecore_x_netwm_startup_id_get_prefetch(Ecore_X_Window window)
693 {
694    xcb_get_property_cookie_t cookie;
695
696    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
697                                        ECORE_X_ATOM_NET_STARTUP_ID, ECORE_X_ATOM_UTF8_STRING,
698                                        0, 0x7fffffff);
699    _ecore_xcb_cookie_cache(cookie.sequence);
700 }
701
702 /**
703  * Gets the reply of the GetProperty request sent by ecore_x_netwm_startup_id_get_prefetch().
704  * @ingroup Ecore_X_NetWM_Group
705  */
706 EAPI void
707 ecore_x_netwm_startup_id_get_fetch(void)
708 {
709    xcb_get_property_cookie_t cookie;
710    xcb_get_property_reply_t *reply;
711
712    cookie.sequence = _ecore_xcb_cookie_get();
713    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
714    _ecore_xcb_reply_cache(reply);
715 }
716
717 /**
718  * Get the startup ID name of a window.
719  * @param window The window
720  * @param id     The ID name
721  * @return       Return always 1.
722  *
723  * To use this function, you must call before, and in order,
724  * ecore_x_netwm_startup_id_get_prefetch(), which sends the GetProperty request,
725  * then ecore_x_netwm_startup_id_get_fetch(), which gets the reply.
726  * @ingroup Ecore_X_NetWM_Group
727  */
728 EAPI int
729 ecore_x_netwm_startup_id_get(Ecore_X_Window window,
730                              char         **id)
731 {
732    if (id)
733      *id = _ecore_x_window_prop_string_utf8_get(window, ECORE_X_ATOM_NET_STARTUP_ID);
734    return 1;
735 }
736
737 /**
738  * Set the _NET_WM_VISIBLE_NAME property.
739  * @param window The widow to activate.
740  * @param name   The title name of the window.
741  *
742  * Set the title name of @p window to @p name by sending the
743  * _NET_WM_VISIBLE_NAME property to @p window, when the Window Manager
744  * displays a window name other than by calling
745  * ecore_x_netwm_name_set().
746  *
747  * The Client SHOULD set the title of @p window in UTF-8
748  * encoding. This function is used for displaying title windows like
749  * [xterm1], [xterm2], ... thereby allowing Pagers to display the same
750  * title as the Window Manager.
751  * @ingroup Ecore_X_NetWM_Group
752  */
753 EAPI void
754 ecore_x_netwm_visible_name_set(Ecore_X_Window window,
755                                const char    *name)
756 {
757    _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_VISIBLE_NAME,
758                                         name);
759 }
760
761 /**
762  * Sends the GetProperty request.
763  * @param window The window.
764  * @ingroup Ecore_X_NetWM_Group
765  */
766 EAPI void
767 ecore_x_netwm_visible_name_get_prefetch(Ecore_X_Window window)
768 {
769    xcb_get_property_cookie_t cookie;
770
771    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
772                                        ECORE_X_ATOM_NET_WM_VISIBLE_NAME, ECORE_X_ATOM_UTF8_STRING,
773                                        0, 0x7fffffff);
774    _ecore_xcb_cookie_cache(cookie.sequence);
775 }
776
777 /**
778  * Gets the reply of the GetProperty request sent by ecore_x_netwm_visible_name_get_prefetch().
779  * @ingroup Ecore_X_NetWM_Group
780  */
781 EAPI void
782 ecore_x_netwm_visible_name_get_fetch(void)
783 {
784    xcb_get_property_cookie_t cookie;
785    xcb_get_property_reply_t *reply;
786
787    cookie.sequence = _ecore_xcb_cookie_get();
788    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
789    _ecore_xcb_reply_cache(reply);
790 }
791
792 /**
793  * Get the visible title of a window.
794  * @param window The window.
795  * @param name   The title name.
796  * @return       Returns always 1.
797  *
798  * Retrieve the visible title name of @p window and store it in @p name. The
799  * function returns always 1.
800  * @param window The window
801  *
802  * To use this function, you must call before, and in order,
803  * ecore_x_netwm_visible_name_get_prefetch(), which sends the GetProperty request,
804  * then ecore_x_netwm_visible_name_get_fetch(), which gets the reply.
805  * @ingroup Ecore_X_NetWM_Group
806  */
807 EAPI int
808 ecore_x_netwm_visible_name_get(Ecore_X_Window window,
809                                char         **name)
810 {
811    if (name)
812      *name = _ecore_x_window_prop_string_utf8_get(window,
813                                                   ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
814    return 1;
815 }
816
817 /**
818  * Set the _NET_WM_ICON_NAME property.
819  * @param window The widow to activate.
820  * @param name   The icon name of the window.
821  *
822  * Set the icon name of @p window to @p name by sending the
823  * _NET_WM_ICON_NAME property to @p window.
824  *
825  * The Client SHOULD set the title of @p window in UTF-8 encoding. If
826  * set, the Window Manager should use this in preference to WM_ICON_NAME.
827  * @ingroup Ecore_X_NetWM_Group
828  */
829 EAPI void
830 ecore_x_netwm_icon_name_set(Ecore_X_Window window,
831                             const char    *name)
832 {
833    _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_ICON_NAME,
834                                         name);
835 }
836
837 /**
838  * Sends the GetProperty request.
839  * @param window The window.
840  * @ingroup Ecore_X_NetWM_Group
841  */
842 EAPI void
843 ecore_x_netwm_icon_name_get_prefetch(Ecore_X_Window window)
844 {
845    xcb_get_property_cookie_t cookie;
846
847    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
848                                        ECORE_X_ATOM_NET_WM_ICON_NAME, ECORE_X_ATOM_UTF8_STRING,
849                                        0, 0x7fffffff);
850    _ecore_xcb_cookie_cache(cookie.sequence);
851 }
852
853 /**
854  * Gets the reply of the GetProperty request sent by ecore_x_netwm_icon_name_get_prefetch().
855  * @ingroup Ecore_X_NetWM_Group
856  */
857 EAPI void
858 ecore_x_netwm_icon_name_get_fetch(void)
859 {
860    xcb_get_property_cookie_t cookie;
861    xcb_get_property_reply_t *reply;
862
863    cookie.sequence = _ecore_xcb_cookie_get();
864    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
865    _ecore_xcb_reply_cache(reply);
866 }
867
868 /**
869  * Get the icon name of a window.
870  * @param window The window.
871  * @param name   The icon name.
872  * @return       Returns always 1.
873  *
874  * Retrieve the icon name of @p window and store it in @p name. The
875  * function returns always 1.
876  *
877  * To use this function, you must call before, and in order,
878  * ecore_x_netwm_icon_name_get_prefetch(), which sends the GetProperty request,
879  * then ecore_x_netwm_icon_name_get_fetch(), which gets the reply.
880  * @ingroup Ecore_X_NetWM_Group
881  */
882 EAPI int
883 ecore_x_netwm_icon_name_get(Ecore_X_Window window,
884                             char         **name)
885 {
886    if (name)
887      *name = _ecore_x_window_prop_string_utf8_get(window,
888                                                   ECORE_X_ATOM_NET_WM_ICON_NAME);
889    return 1;
890 }
891
892 /**
893  * Set the _NET_WM_VISIBLE_ICON_NAME property.
894  * @param window The widow to activate.
895  * @param name   The title name of the window.
896  *
897  * Set the icon name of @p window to @p name by sending the
898  * _NET_WM_VISIBLE_ICON_NAME property to @p window, when the Window Manager
899  * displays a icon name other than by calling
900  * ecore_x_netwm_icon_name_set().
901  *
902  * The Client SHOULD set the icon name in UTF-8
903  * encoding. The Window Manager MUST use this function is it display
904  * an icon name other than with ecore_x_netwm_icon_name_set().
905  * @ingroup Ecore_X_NetWM_Group
906  */
907 EAPI void
908 ecore_x_netwm_visible_icon_name_set(Ecore_X_Window window,
909                                     const char    *name)
910 {
911    _ecore_x_window_prop_string_utf8_set(window,
912                                         ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME,
913                                         name);
914 }
915
916 /**
917  * Sends the GetProperty request.
918  * @param window The window.
919  * @ingroup Ecore_X_NetWM_Group
920  */
921 EAPI void
922 ecore_x_netwm_visible_icon_name_get_prefetch(Ecore_X_Window window)
923 {
924    xcb_get_property_cookie_t cookie;
925
926    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
927                                        ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME, ECORE_X_ATOM_UTF8_STRING,
928                                        0, 0x7fffffff);
929    _ecore_xcb_cookie_cache(cookie.sequence);
930 }
931
932 /**
933  * Gets the reply of the GetProperty request sent by ecore_x_netwm_visible_icon_name_get_prefetch().
934  * @ingroup Ecore_X_NetWM_Group
935  */
936 EAPI void
937 ecore_x_netwm_visible_icon_name_get_fetch(void)
938 {
939    xcb_get_property_cookie_t cookie;
940    xcb_get_property_reply_t *reply;
941
942    cookie.sequence = _ecore_xcb_cookie_get();
943    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
944    _ecore_xcb_reply_cache(reply);
945 }
946
947 /**
948  * Get the visible icon name of a window.
949  * @param window The window.
950  * @param name   The icon name.
951  * @return       Returns always 1.
952  *
953  * Retrieve the visible icon name of @p window and store it in
954  * @p name. The function returns always 1.
955  *
956  * To use this function, you must call before, and in order,
957  * ecore_x_netwm_visible_icon_name_get_prefetch(), which sends the GetProperty request,
958  * then ecore_x_netwm_visible_icon_name_get_fetch(), which gets the reply.
959  * @ingroup Ecore_X_NetWM_Group
960  */
961 EAPI int
962 ecore_x_netwm_visible_icon_name_get(Ecore_X_Window window,
963                                     char         **name)
964 {
965    if (name)
966      *name = _ecore_x_window_prop_string_utf8_get(window,
967                                                   ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
968    return 1;
969 }
970
971 /**
972  * Set the _NET_WM_DESKTOP property.
973  * @param window The window.
974  * @param desk   The desktop index.
975  *
976  * Set on which desktop the @p window is in by sending the
977  * _NET_WM_DESKTOP property to @p window. @p desk is the index of
978  * the desktop, starting from 0. To indicate that the window should
979  * appear on all desktops, @p desk must be equal to 0xFFFFFFFF.
980  *
981  * A Client MAY choose not to set this property, in which case the
982  * Window Manager SHOULD place it as it wishes.
983  *
984  * The Window Manager should honor _NET_WM_DESKTOP whenever a
985  * withdrawn window requests to be mapped.
986  *
987  * A Client can request a change of desktop for a non-withdrawn window
988  * by sending a _NET_WM_DESKTOP client message to the root window.
989  * @ingroup Ecore_X_NetWM_Group
990  */
991 EAPI void
992 ecore_x_netwm_desktop_set(Ecore_X_Window window,
993                           unsigned int   desk)
994 {
995    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1);
996 }
997
998 /**
999  * Sends the GetProperty request.
1000  * @param window The window.
1001  * @ingroup Ecore_X_NetWM_Group
1002  */
1003 EAPI void
1004 ecore_x_netwm_desktop_get_prefetch(Ecore_X_Window window)
1005 {
1006    xcb_get_property_cookie_t cookie;
1007
1008    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1009                                        ECORE_X_ATOM_NET_WM_DESKTOP, ECORE_X_ATOM_CARDINAL,
1010                                        0, 0x7fffffff);
1011    _ecore_xcb_cookie_cache(cookie.sequence);
1012 }
1013
1014 /**
1015  * Gets the reply of the GetProperty request sent by ecore_x_netwm_desktop_get_prefetch().
1016  * @ingroup Ecore_X_NetWM_Group
1017  */
1018 EAPI void
1019 ecore_x_netwm_desktop_get_fetch(void)
1020 {
1021    xcb_get_property_cookie_t cookie;
1022    xcb_get_property_reply_t *reply;
1023
1024    cookie.sequence = _ecore_xcb_cookie_get();
1025    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1026    _ecore_xcb_reply_cache(reply);
1027 }
1028
1029 /**
1030  * Get the visible icon name of a window.
1031  * @param window The window.
1032  * @param desk   The desktop index.
1033  * @return       1 on success, 0 otherwise.
1034  *
1035  * Retrieve the desktop index in which @p window is displayed and
1036  * store it in @p desk. If @p desk value is 0xFFFFFFFF, the window
1037  * appears on all desktops. The function returns 1 on success, 0
1038  * otherwise.
1039  *
1040  * To use this function, you must call before, and in order,
1041  * ecore_x_netwm_desktop_get_prefetch(), which sends the GetProperty request,
1042  * then ecore_x_netwm_desktop_get_fetch(), which gets the reply.
1043  * @ingroup Ecore_X_NetWM_Group
1044  */
1045 EAPI int
1046 ecore_x_netwm_desktop_get(Ecore_X_Window window,
1047                           unsigned int *desk)
1048 {
1049    int      ret;
1050    uint32_t tmp;
1051
1052    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_DESKTOP,
1053                                         &tmp, 1);
1054
1055    if (desk) *desk = tmp;
1056    return (ret == 1) ? 1 : 0;
1057 }
1058
1059 /**
1060  * Set the _NET_WM_STRUT property.
1061  * @param window The window
1062  * @param left   The number of pixels at the left of the screen.
1063  * @param right  The number of pixels at the right of the screen.
1064  * @param top    The number of pixels at the top of the screen.
1065  * @param bottom The number of pixels at the bottom of the screen.
1066  *
1067  * Set space at the edje of the screen by sending the _NET_WM_STRUT
1068  * property to @p window if @p window is to reserve that space.
1069  * @p left, @p right, @p top and @p bottom are respectively the number
1070  * of pixels at the left, right, top and bottom of the screen.
1071  *
1072  * This property is deprecated and ecore_x_netwm_strut_partial_set()
1073  * should be used instead. However, Clients MAY set this property in
1074  * addition to _NET_WM_STRUT_PARTIAL to ensure backward compatibility
1075  * with Window Managers supporting older versions of the
1076  * Specification.
1077  * @ingroup Ecore_X_NetWM_Group
1078  */
1079 EAPI void
1080 ecore_x_netwm_strut_set(Ecore_X_Window window,
1081                         int            left,
1082                         int            right,
1083                         int            top,
1084                         int            bottom)
1085 {
1086    uint32_t strut[4];
1087
1088    strut[0] = left;
1089    strut[1] = right;
1090    strut[2] = top;
1091    strut[3] = bottom;
1092    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
1093 }
1094
1095 /**
1096  * Sends the GetProperty request.
1097  * @param window The window.
1098  * @ingroup Ecore_X_NetWM_Group
1099  */
1100 EAPI void
1101 ecore_x_netwm_strut_get_prefetch(Ecore_X_Window window)
1102 {
1103    xcb_get_property_cookie_t cookie;
1104
1105    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1106                                        ECORE_X_ATOM_NET_WM_STRUT, ECORE_X_ATOM_CARDINAL,
1107                                        0, 0x7fffffff);
1108    _ecore_xcb_cookie_cache(cookie.sequence);
1109 }
1110
1111 /**
1112  * Gets the reply of the GetProperty request sent by ecore_x_strut_get_prefetch().
1113  * @ingroup Ecore_X_NetWM_Group
1114  */
1115 EAPI void
1116 ecore_x_netwm_strut_get_fetch(void)
1117 {
1118    xcb_get_property_cookie_t cookie;
1119    xcb_get_property_reply_t *reply;
1120
1121    cookie.sequence = _ecore_xcb_cookie_get();
1122    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1123    _ecore_xcb_reply_cache(reply);
1124 }
1125
1126 /*
1127  * _NET_WM_STRUT is deprecated
1128  */
1129
1130 /**
1131  * Get the space at the edje of the screen.
1132  * @param window The window
1133  * @param left   The number of pixels at the left of the screen.
1134  * @param right  The number of pixels at the right of the screen.
1135  * @param top    The number of pixels at the top of the screen.
1136  * @param bottom The number of pixels at the bottom of the screen.
1137  * @return       1 on success, 0 otherwise.
1138  *
1139  * Retrieve the space at the edje of the screen if @p window is to
1140  * reserve such space. The number of pixels at the left, right, top
1141  * and bottom of the screen are respectively stored in @p left,
1142  * @p right, @p top and @p bottom. This function returns 1 on success,
1143  * 0 otherwise.
1144  *
1145  * This property is deprecated. See ecore_x_netwm_strut_set() for more
1146  * informations.
1147  *
1148  * To use this function, you must call before, and in order,
1149  * ecore_x_netwm_strut_get_prefetch(), which sends the GetProperty request,
1150  * then ecore_x_netwm_strut_get_fetch(), which gets the reply.
1151  * @ingroup Ecore_X_NetWM_Group
1152  */
1153 EAPI int
1154 ecore_x_netwm_strut_get(Ecore_X_Window window,
1155                         int           *left,
1156                         int           *right,
1157                         int           *top,
1158                         int           *bottom)
1159 {
1160    uint32_t strut[4];
1161    int      ret = 0;
1162
1163    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
1164    if (ret != 4)
1165      return 0;
1166
1167    if (left)   *left   = strut[0];
1168    if (right)  *right  = strut[1];
1169    if (top)    *top    = strut[2];
1170    if (bottom) *bottom = strut[3];
1171
1172    return 1;
1173 }
1174
1175 /**
1176  * Set the _NET_WM_STRUT_PARTIAL property.
1177  * @param window         The window
1178  * @param left           The number of pixels at the left of the screen.
1179  * @param right          The number of pixels at the right of the screen.
1180  * @param top            The number of pixels at the top of the screen.
1181  * @param bottom         The number of pixels at the bottom of the screen.
1182  * @param left_start_y   The number of pixels.
1183  * @param left_end_y     The number of pixels.
1184  * @param right_start_y  The number of pixels.
1185  * @param right_end_y    The number of pixels.
1186  * @param top_start_x    The number of pixels.
1187  * @param top_end_x      The number of pixels.
1188  * @param bottom_start_x The number of pixels.
1189  * @param bottom_end_x   The number of pixels.
1190  *
1191  * Set space at the edje of the screen by sending the
1192  * _NET_WM_STRUT_PARTIAL property to @p window if @p window is to
1193  * reserve that space. @p left, @p right, @p top and @p bottom are
1194  * respectively the number of pixels at the left, right, top and
1195  * bottom of the screen.
1196  *
1197  * TODO: more description for that function.
1198  * @ingroup Ecore_X_NetWM_Group
1199  */
1200 EAPI void
1201 ecore_x_netwm_strut_partial_set(Ecore_X_Window window,
1202                                 int            left,
1203                                 int            right,
1204                                 int            top,
1205                                 int            bottom,
1206                                 int            left_start_y,
1207                                 int            left_end_y,
1208                                 int            right_start_y,
1209                                 int            right_end_y,
1210                                 int            top_start_x,
1211                                 int            top_end_x,
1212                                 int            bottom_start_x,
1213                                 int            bottom_end_x)
1214 {
1215    unsigned int strut[12];
1216
1217    strut[0] = left;
1218    strut[1] = right;
1219    strut[2] = top;
1220    strut[3] = bottom;
1221    strut[4] = left_start_y;
1222    strut[5] = left_end_y;
1223    strut[6] = right_start_y;
1224    strut[7] = right_end_y;
1225    strut[8] = top_start_x;
1226    strut[9] = top_end_x;
1227    strut[10] = bottom_start_x;
1228    strut[11] = bottom_end_x;
1229    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12);
1230 }
1231
1232 /**
1233  * Sends the GetProperty request.
1234  * @param window The window.
1235  * @ingroup Ecore_X_NetWM_Group
1236  */
1237 EAPI void
1238 ecore_x_netwm_strut_partial_get_prefetch(Ecore_X_Window window)
1239 {
1240    xcb_get_property_cookie_t cookie;
1241
1242    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1243                                        ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, ECORE_X_ATOM_CARDINAL,
1244                                        0, 0x7fffffff);
1245    _ecore_xcb_cookie_cache(cookie.sequence);
1246 }
1247
1248 /**
1249  * Gets the reply of the GetProperty request sent by ecore_x_strut_partial_get_prefetch().
1250  * @ingroup Ecore_X_NetWM_Group
1251  */
1252 EAPI void
1253 ecore_x_netwm_strut_partial_get_fetch(void)
1254 {
1255    xcb_get_property_cookie_t cookie;
1256    xcb_get_property_reply_t *reply;
1257
1258    cookie.sequence = _ecore_xcb_cookie_get();
1259    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1260    _ecore_xcb_reply_cache(reply);
1261 }
1262
1263 /**
1264  * Get the space at the edje of the screen of a window.
1265  * @param window         The window
1266  * @param left           The number of pixels at the left of the screen.
1267  * @param right          The number of pixels at the right of the screen.
1268  * @param top            The number of pixels at the top of the screen.
1269  * @param bottom         The number of pixels at the bottom of the screen.
1270  * @param left_start_y   The number of pixels.
1271  * @param left_end_y     The number of pixels.
1272  * @param right_start_y  The number of pixels.
1273  * @param right_end_y    The number of pixels.
1274  * @param top_start_x    The number of pixels.
1275  * @param top_end_x      The number of pixels.
1276  * @param bottom_start_x The number of pixels.
1277  * @param bottom_end_x   The number of pixels.
1278  *
1279  * Retrieve the space at the edje of the screen if @p window is to
1280  * reserve such space. The number of pixels at the left, right, top
1281  * and bottom of the screen are respectively stored in @p left,
1282  * @p right, @p top and @p bottom. This function returns 1 on success,
1283  * 0 otherwise.
1284  *
1285  * TODO: more description for that function.
1286  *
1287  * To use this function, you must call before, and in order,
1288  * ecore_x_netwm_strut_partial_get_prefetch(), which sends the GetProperty request,
1289  * then ecore_x_netwm_strut_partial_get_fetch(), which gets the reply.
1290  * @ingroup Ecore_X_NetWM_Group
1291  */
1292 EAPI int
1293 ecore_x_netwm_strut_partial_get(Ecore_X_Window window,
1294                                 int           *left,
1295                                 int           *right,
1296                                 int           *top,
1297                                 int           *bottom,
1298                                 int           *left_start_y,
1299                                 int           *left_end_y,
1300                                 int           *right_start_y,
1301                                 int           *right_end_y,
1302                                 int           *top_start_x,
1303                                 int           *top_end_x,
1304                                 int           *bottom_start_x,
1305                                 int           *bottom_end_x)
1306 {
1307    uint32_t strut[12];
1308    int      ret = 0;
1309
1310    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12);
1311    if (ret != 12)
1312      return 0;
1313
1314    if (left)           *left           = strut[0];
1315    if (right)          *right          = strut[1];
1316    if (top)            *top            = strut[2];
1317    if (bottom)         *bottom         = strut[3];
1318    if (left_start_y)   *left_start_y   = strut[4];
1319    if (left_end_y)     *left_end_y     = strut[5];
1320    if (right_start_y)  *right_start_y  = strut[6];
1321    if (right_end_y)    *right_end_y    = strut[7];
1322    if (top_start_x)    *top_start_x    = strut[8];
1323    if (top_end_x)      *top_end_x      = strut[9];
1324    if (bottom_start_x) *bottom_start_x = strut[10];
1325    if (bottom_end_x)   *bottom_end_x   = strut[11];
1326    return 1;
1327 }
1328
1329 /**
1330  * Sends the GetProperty request.
1331  * @param window The window.
1332  * @ingroup Ecore_X_NetWM_Group
1333  */
1334 EAPI void
1335 ecore_x_netwm_icons_get_prefetch(Ecore_X_Window window)
1336 {
1337    xcb_get_property_cookie_t cookie;
1338
1339    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1340                                        ECORE_X_ATOM_NET_WM_ICON, ECORE_X_ATOM_CARDINAL,
1341                                        0, 0x7fffffff);
1342    _ecore_xcb_cookie_cache(cookie.sequence);
1343 }
1344
1345 /**
1346  * Gets the reply of the GetProperty request sent by ecore_x_icons_get_prefetch().
1347  * @ingroup Ecore_X_NetWM_Group
1348  */
1349 EAPI void
1350 ecore_x_netwm_icons_get_fetch(void)
1351 {
1352    xcb_get_property_cookie_t cookie;
1353    xcb_get_property_reply_t *reply;
1354
1355    cookie.sequence = _ecore_xcb_cookie_get();
1356    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1357    _ecore_xcb_reply_cache(reply);
1358 }
1359
1360 /**
1361  * Retrieve hte possible icons of a window.
1362  * @param window The window
1363  * @param icon   An array of icons.
1364  * @param num    The number of icons.
1365  * @return       1 on success, 0 otherwise.
1366  *
1367  * Retrieve an array of possible icons of @p window. The icons are
1368  * stored in @p icon and their number in @p num.
1369  *
1370  * To use this function, you must call before, and in order,
1371  * ecore_x_netwm_icons_get_prefetch(), which sends the GetProperty request,
1372  * then ecore_x_netwm_icons_get_fetch(), which gets the reply.
1373  * @ingroup Ecore_X_NetWM_Group
1374  */
1375 EAPI int
1376 ecore_x_netwm_icons_get(Ecore_X_Window window,
1377                         Ecore_X_Icon **icon,
1378                         int           *num)
1379 {
1380    uint32_t *data;
1381    uint32_t *p;
1382    uint32_t *src;
1383    uint32_t  icons;
1384    uint32_t  len;
1385    uint32_t  i;
1386    int       num_ret;
1387
1388    if (num) *num = 0UL;
1389    if (icon) *icon = NULL;
1390
1391    num_ret = ecore_x_window_prop_card32_list_get(window,
1392                                                  ECORE_X_ATOM_NET_WM_ICON,
1393                                                  &data);
1394    if ((num_ret <= 0) || !data)
1395      return 0;
1396
1397    if (num_ret < 2)
1398      {
1399         free(data);
1400         return 0;
1401      }
1402
1403    /* Check how many icons there are */
1404    icons = 0;
1405    p = data;
1406    while (p)
1407      {
1408         len = p[0] * p[1];
1409         p += (len + 2);
1410         if ((p - data) > num_ret)
1411           {
1412              free(data);
1413              return 0;
1414           }
1415         icons++;
1416
1417         if ((p - data) == num_ret)
1418           p = NULL;
1419      }
1420    if (num) *num = icons;
1421
1422    /* If the user doesn't want the icons, return */
1423    if (!icon)
1424      {
1425         free(data);
1426         return 1;
1427      }
1428
1429    /* Allocate memory */
1430    *icon = malloc(icons * sizeof(Ecore_X_Icon));
1431    if (!(*icon))
1432      {
1433         free(data);
1434         return 0;
1435      }
1436
1437    /* Fetch the icons */
1438    p = data;
1439    for (i = 0; i < icons; i++)
1440      {
1441         uint32_t *ps, *pd, *pe;
1442
1443         len = p[0] * p[1];
1444         ((*icon)[i]).width = p[0];
1445         ((*icon)[i]).height = p[1];
1446         src = &(p[2]);
1447         ((*icon)[i]).data = malloc(len * sizeof(uint32_t));
1448         if (!((*icon)[i]).data)
1449           {
1450              while (i)
1451                free(((*icon)[--i]).data);
1452              free(*icon);
1453              free(data);
1454              return 0;
1455           }
1456
1457         pd = ((*icon)[i]).data;
1458         ps = src;
1459         pe = ps + len;
1460         for (; ps < pe; ps++)
1461           {
1462              uint32_t r, g, b, a;
1463
1464              a = (*ps >> 24) & 0xff;
1465              r = (((*ps >> 16) & 0xff) * a) / 255;
1466              g = (((*ps >>  8) & 0xff) * a) / 255;
1467              b = (((*ps      ) & 0xff) * a) / 255;
1468              *pd = (a << 24) | (r << 16) | (g << 8) | (b);
1469              pd++;
1470           }
1471         p += (len + 2);
1472      }
1473
1474    free(data);
1475
1476    return 1;
1477 }
1478
1479 /**
1480  * Set the _NET_WM_ICON_GEOMETRY property.
1481  * @param window The window.
1482  * @param x      The X coordinate of the icon.
1483  * @param y      The Y coordinate of the icon.
1484  * @param width  The width of the icon.
1485  * @param height The height of the icon.
1486  *
1487  * Set the geometry of the icon of @p window by sending the
1488  * _NET_WM_ICON_GEOMETRY property to @p window. @p x, @p y, @p width
1489  * and @p height specify respectively the X coordinate, the Y
1490  * coordinate, the width and the height of the icon.
1491  *
1492  * Stand alone tools like a taskbar or an iconbox MAY use this
1493  * function. This functions makes possible for a Window Manager to
1494  * display a nice animation like morphing the window into its icon.
1495  * @ingroup Ecore_X_NetWM_Group
1496  */
1497 EAPI void
1498 ecore_x_netwm_icon_geometry_set(Ecore_X_Window window,
1499                                 int            x,
1500                                 int            y,
1501                                 int            width,
1502                                 int            height)
1503 {
1504    uint32_t geometry[4];
1505
1506    geometry[0] = (uint32_t)x;
1507    geometry[1] = (uint32_t)y;
1508    geometry[2] = (uint32_t)width;
1509    geometry[3] = (uint32_t)height;
1510    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4);
1511 }
1512
1513 /**
1514  * Sends the GetProperty request.
1515  * @param window The window.
1516  * @ingroup Ecore_X_NetWM_Group
1517  */
1518 EAPI void
1519 ecore_x_netwm_icon_geometry_get_prefetch(Ecore_X_Window window)
1520 {
1521    xcb_get_property_cookie_t cookie;
1522
1523    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1524                                        ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, ECORE_X_ATOM_CARDINAL,
1525                                        0, 0x7fffffff);
1526    _ecore_xcb_cookie_cache(cookie.sequence);
1527 }
1528
1529 /**
1530  * Gets the reply of the GetProperty request sent by ecore_x_icon_geometry_get_prefetch().
1531  * @ingroup Ecore_X_NetWM_Group
1532  */
1533 EAPI void
1534 ecore_x_netwm_icon_geometry_get_fetch(void)
1535 {
1536    xcb_get_property_cookie_t cookie;
1537    xcb_get_property_reply_t *reply;
1538
1539    cookie.sequence = _ecore_xcb_cookie_get();
1540    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1541    _ecore_xcb_reply_cache(reply);
1542 }
1543
1544 /**
1545  * Get the geometry of an icon.
1546  * @param window The window
1547  * @param x      x
1548  * @param x      The X coordinate of the icon.
1549  * @param y      The Y coordinate of the icon.
1550  * @param width  The width of the icon.
1551  * @param height The height of the icon.
1552  * @return       1 on success, 0 othrwise.
1553  *
1554  * Retrieve the geometry of the icon of @p window. The geometry is
1555  * stored in @p x, @p y, @p width and @p height. The function returns
1556  * 1 on success, 0 otherwise.
1557  *
1558  * To use this function, you must call before, and in order,
1559  * ecore_x_netwm_icon_geometry_get_prefetch(), which sends the GetProperty request,
1560  * then ecore_x_netwm_icon_geometry_get_fetch(), which gets the reply.
1561  * @ingroup Ecore_X_NetWM_Group
1562  */
1563 EAPI int
1564 ecore_x_netwm_icon_geometry_get(Ecore_X_Window window,
1565                                 int           *x,
1566                                 int           *y,
1567                                 int           *width,
1568                                 int           *height)
1569 {
1570    uint32_t geometry[4];
1571    int      ret;
1572
1573    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4);
1574    if (ret != 4)
1575      return 0;
1576
1577    if (x)      *x      = geometry[0];
1578    if (y)      *y      = geometry[1];
1579    if (width)  *width  = geometry[2];
1580    if (height) *height = geometry[3];
1581
1582    return 1;
1583 }
1584
1585 /**
1586  * Set the _NET_WM_PID property.
1587  * @param window The window.
1588  * @param pid    The process ID.
1589  *
1590  * Set the process ID of the client owning @p window by sending the
1591  * _NET_WM_PID property to @p window.
1592  *
1593  * This function MAY be used by the Window Manager to kill windows
1594  * which do not respond to the _NET_WM_PING protocol.
1595  *
1596  * If _NET_WM_PID is set, the ICCCM-specified property
1597  * WM_CLIENT_MACHINE MUST also be set.
1598  * @ingroup Ecore_X_NetWM_Group
1599  */
1600 EAPI void
1601 ecore_x_netwm_pid_set(Ecore_X_Window window,
1602                       int            pid)
1603 {
1604    unsigned int tmp;
1605
1606    tmp = pid;
1607    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_PID,
1608                                   &tmp, 1);
1609 }
1610
1611 /**
1612  * Sends the GetProperty request.
1613  * @param window The window.
1614  * @ingroup Ecore_X_NetWM_Group
1615  */
1616 EAPI void
1617 ecore_x_netwm_pid_get_prefetch(Ecore_X_Window window)
1618 {
1619    xcb_get_property_cookie_t cookie;
1620
1621    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1622                                        ECORE_X_ATOM_NET_WM_PID, ECORE_X_ATOM_CARDINAL,
1623                                        0, 0x7fffffff);
1624    _ecore_xcb_cookie_cache(cookie.sequence);
1625 }
1626
1627 /**
1628  * Gets the reply of the GetProperty request sent by ecore_x_pid_get_prefetch().
1629  * @ingroup Ecore_X_NetWM_Group
1630  */
1631 EAPI void
1632 ecore_x_netwm_pid_get_fetch(void)
1633 {
1634    xcb_get_property_cookie_t cookie;
1635    xcb_get_property_reply_t *reply;
1636
1637    cookie.sequence = _ecore_xcb_cookie_get();
1638    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1639    _ecore_xcb_reply_cache(reply);
1640 }
1641
1642 /**
1643  * Get the process ID of a client window.
1644  * @param window The window.
1645  * @param pid    The process ID.
1646  * @return       1 on success, 0 otherwise.
1647  *
1648  * Retrieve the process ID of @p window and store it in @p pid. This
1649  * function returns 1 on success, 0 otherwise.
1650  *
1651  * To use this function, you must call before, and in order,
1652  * ecore_x_netwm_pid_get_prefetch(), which sends the GetProperty request,
1653  * then ecore_x_netwm_pid_get_fetch(), which gets the reply.
1654  * @ingroup Ecore_X_NetWM_Group
1655  */
1656 EAPI int
1657 ecore_x_netwm_pid_get(Ecore_X_Window window,
1658                       int           *pid)
1659 {
1660    int ret;
1661    uint32_t tmp;
1662
1663    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_PID,
1664                                         &tmp, 1);
1665    if (pid) *pid = tmp;
1666
1667    return (ret == 1) ? 1 : 0;
1668 }
1669
1670 /**
1671  * Set the _NET_WM_HANDLED_ICONS property.
1672  * @param window The window.
1673  *
1674  * Indicate to the Window Manager that it does not need to provide
1675  * icons for the iconified @p window by sending the
1676  * _NET_WM_HANDLED_ICONS property to @p window.
1677  *
1678  * This function can be used by a Pager on one of its own toplevel
1679  * windows (for example if the Client is a taskbar and provides
1680  * buttons for iconified windows).
1681  * @ingroup Ecore_X_NetWM_Group
1682  */
1683 EAPI void
1684 ecore_x_netwm_handled_icons_set(Ecore_X_Window window)
1685 {
1686    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
1687                                   NULL, 0);
1688 }
1689
1690 /**
1691  * Sends the GetProperty request.
1692  * @param window The window.
1693  * @ingroup Ecore_X_NetWM_Group
1694  */
1695 EAPI void
1696 ecore_x_netwm_handled_icons_get_prefetch(Ecore_X_Window window)
1697 {
1698    xcb_get_property_cookie_t cookie;
1699
1700    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1701                                        ECORE_X_ATOM_NET_WM_HANDLED_ICONS, ECORE_X_ATOM_CARDINAL,
1702                                        0, 0x7fffffff);
1703    _ecore_xcb_cookie_cache(cookie.sequence);
1704 }
1705
1706 /**
1707  * Gets the reply of the GetProperty request sent by ecore_x_handled_icons_get_prefetch().
1708  * @ingroup Ecore_X_NetWM_Group
1709  */
1710 EAPI void
1711 ecore_x_netwm_handled_icons_get_fetch(void)
1712 {
1713    xcb_get_property_cookie_t cookie;
1714    xcb_get_property_reply_t *reply;
1715
1716    cookie.sequence = _ecore_xcb_cookie_get();
1717    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1718    _ecore_xcb_reply_cache(reply);
1719 }
1720
1721 /**
1722  * Return wheter the Client handles icons or not.
1723  * @param window The window.
1724  * @return       1 if icons are handled, 0 otherwise.
1725  *
1726  * Return whether the client handles icons or not if @p window is
1727  * iconified.
1728  *
1729  * To use this function, you must call before, and in order,
1730  * ecore_x_netwm_handled_icons_get_prefetch(), which sends the GetProperty request,
1731  * then ecore_x_netwm_handled_icons_get_fetch(), which gets the reply.
1732  * @ingroup Ecore_X_NetWM_Group
1733  */
1734 EAPI int
1735 ecore_x_netwm_handled_icons_get(Ecore_X_Window window)
1736 {
1737    int ret = 0;
1738    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
1739                                         NULL, 0);
1740    return (ret == 0) ? 1 : 0;
1741 }
1742
1743 /**
1744  * Set the _NET_WM_USER_TIME property.
1745  * @param window The window.
1746  * @param time   The last user activity time in the window.
1747  *
1748  * Set the XServer time at which last user activity in @p window took
1749  * place by sending the _NET_WM_USER_TIME property to @p window. @p
1750  * time contains that XServer time in seconds.
1751  *
1752  * This function allows a Window Manager to alter the focus, stacking,
1753  * and/or placement behavior of windows when they are mapped depending
1754  * on whether the new window was created by a user action or is a
1755  * "pop-up" window activated by a timer or some other event.
1756  * @ingroup Ecore_X_NetWM_Group
1757  */
1758 EAPI void
1759 ecore_x_netwm_user_time_set(Ecore_X_Window window,
1760                             unsigned int   time)
1761 {
1762    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_USER_TIME,
1763                                   &time, 1);
1764 }
1765
1766 /**
1767  * Sends the GetProperty request.
1768  * @param window The window.
1769  * @ingroup Ecore_X_NetWM_Group
1770  */
1771 EAPI void
1772 ecore_x_netwm_user_time_get_prefetch(Ecore_X_Window window)
1773 {
1774    xcb_get_property_cookie_t cookie;
1775
1776    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1777                                        ECORE_X_ATOM_NET_WM_USER_TIME, ECORE_X_ATOM_CARDINAL,
1778                                        0, 0x7fffffff);
1779    _ecore_xcb_cookie_cache(cookie.sequence);
1780 }
1781
1782 /**
1783  * Gets the reply of the GetProperty request sent by ecore_x_netwm_user_time_get_prefetch().
1784  * @ingroup Ecore_X_NetWM_Group
1785  */
1786 EAPI void
1787 ecore_x_netwm_user_time_get_fetch(void)
1788 {
1789    xcb_get_property_cookie_t cookie;
1790    xcb_get_property_reply_t *reply;
1791
1792    cookie.sequence = _ecore_xcb_cookie_get();
1793    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1794    _ecore_xcb_reply_cache(reply);
1795 }
1796
1797 /**
1798  * Get the last user activity time in the window.
1799  * @param window The window.
1800  * @param time   The returned time.
1801  * @return       1 on success, 0 otherwise.
1802  *
1803  * Return the XServer time at which last user activity in @p window
1804  * took place. The time is stored in @p time.
1805  *
1806  * To use this function, you must call before, and in order,
1807  * ecore_x_netwm_user_time_get_prefetch(), which sends the GetProperty request,
1808  * then ecore_x_netwm_user_time_get_fetch(), which gets the reply.
1809  * @ingroup Ecore_X_NetWM_Group
1810  */
1811 EAPI int
1812 ecore_x_netwm_user_time_get(Ecore_X_Window window,
1813                             unsigned int  *time)
1814 {
1815    int ret;
1816    uint32_t tmp;
1817
1818    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_USER_TIME,
1819                                         &tmp, 1);
1820    if (time) *time = tmp;
1821    return (ret == 1) ? 1 : 0;
1822 }
1823
1824 Ecore_X_Window_State
1825 _ecore_x_netwm_state_get(Ecore_X_Atom a)
1826 {
1827    if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL)
1828      return ECORE_X_WINDOW_STATE_MODAL;
1829    else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY)
1830      return ECORE_X_WINDOW_STATE_STICKY;
1831    else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT)
1832      return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
1833    else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ)
1834      return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
1835    else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED)
1836      return ECORE_X_WINDOW_STATE_SHADED;
1837    else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR)
1838      return ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
1839    else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER)
1840      return ECORE_X_WINDOW_STATE_SKIP_PAGER;
1841    else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN)
1842      return ECORE_X_WINDOW_STATE_HIDDEN;
1843    else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN)
1844      return ECORE_X_WINDOW_STATE_FULLSCREEN;
1845    else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE)
1846      return ECORE_X_WINDOW_STATE_ABOVE;
1847    else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW)
1848      return ECORE_X_WINDOW_STATE_BELOW;
1849    else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION)
1850      return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION;
1851    else
1852      return ECORE_X_WINDOW_STATE_UNKNOWN;
1853 }
1854
1855 static Ecore_X_Atom
1856 _ecore_x_netwm_state_atom_get(Ecore_X_Window_State s)
1857 {
1858    switch(s)
1859      {
1860       case ECORE_X_WINDOW_STATE_MODAL:
1861          return ECORE_X_ATOM_NET_WM_STATE_MODAL;
1862       case ECORE_X_WINDOW_STATE_STICKY:
1863          return ECORE_X_ATOM_NET_WM_STATE_STICKY;
1864       case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
1865          return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
1866       case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
1867          return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
1868       case ECORE_X_WINDOW_STATE_SHADED:
1869          return ECORE_X_ATOM_NET_WM_STATE_SHADED;
1870       case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
1871          return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
1872       case ECORE_X_WINDOW_STATE_SKIP_PAGER:
1873          return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
1874       case ECORE_X_WINDOW_STATE_HIDDEN:
1875          return ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
1876       case ECORE_X_WINDOW_STATE_FULLSCREEN:
1877          return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
1878       case ECORE_X_WINDOW_STATE_ABOVE:
1879          return ECORE_X_ATOM_NET_WM_STATE_ABOVE;
1880       case ECORE_X_WINDOW_STATE_BELOW:
1881          return ECORE_X_ATOM_NET_WM_STATE_BELOW;
1882       case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
1883          return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION;
1884       default:
1885          return 0;
1886      }
1887 }
1888
1889 /**
1890  * Set the _NET_WM_STATE property.
1891  * @param window The window.
1892  * @param state  An array of window hints.
1893  * @param num    The number of hints.
1894  *
1895  * Set a list of hints describing @p window state by sending the
1896  * _NET_WM_STATE property to @p window. The hints are stored in the
1897  * array @p state. @p num must contain the number of hints.
1898  *
1899  * The Window Manager SHOULD honor _NET_WM_STATE whenever a withdrawn
1900  * window requests to be mapped. A Client wishing to change the state
1901  * of a window MUST send a _NET_WM_STATE client message to the root
1902  * window. The Window Manager MUST keep this property updated to
1903  * reflect the current state of the window.
1904  * @ingroup Ecore_X_NetWM_Group
1905  */
1906 EAPI void
1907 ecore_x_netwm_window_state_set(Ecore_X_Window        window,
1908                                Ecore_X_Window_State *state,
1909                                unsigned int          num)
1910 {
1911    Ecore_X_Atom  *set;
1912    uint32_t       i;
1913
1914    if (!num)
1915      {
1916         ecore_x_window_prop_property_del(window, ECORE_X_ATOM_NET_WM_STATE);
1917         return;
1918      }
1919
1920    set = malloc(num * sizeof(Ecore_X_Atom));
1921    if (!set) return;
1922
1923    for (i = 0; i < num; i++)
1924      set[i] = _ecore_x_netwm_state_atom_get(state[i]);
1925
1926    ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_STATE, set, num);
1927
1928    free(set);
1929 }
1930
1931 /**
1932  * Sends the GetProperty request.
1933  * @param window The window.
1934  * @ingroup Ecore_X_NetWM_Group
1935  */
1936 EAPI void
1937 ecore_x_netwm_window_state_get_prefetch(Ecore_X_Window window)
1938 {
1939    xcb_get_property_cookie_t cookie;
1940
1941    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
1942                                        ECORE_X_ATOM_NET_WM_STATE, ECORE_X_ATOM_ATOM,
1943                                        0, 0x7fffffff);;
1944    _ecore_xcb_cookie_cache(cookie.sequence);
1945 }
1946
1947 /**
1948  * Gets the reply of the GetProperty request sent by ecore_x_window_state_get_prefetch().
1949  * @ingroup Ecore_X_NetWM_Group
1950  */
1951 EAPI void
1952 ecore_x_netwm_window_state_get_fetch(void)
1953 {
1954    xcb_get_property_cookie_t cookie;
1955    xcb_get_property_reply_t *reply;
1956
1957    cookie.sequence = _ecore_xcb_cookie_get();
1958    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
1959    _ecore_xcb_reply_cache(reply);
1960 }
1961
1962 /**
1963  * Get the hints describing the window state.
1964  * @param window The window.
1965  * @param state  The returned hins.
1966  * @param num    The number of hints.
1967  * @return       1 on success, 0 otherwise.
1968  *
1969  * Retrieve the hints describing @p window state. The state is
1970  * returned in @p state. The nummber of hints is stored in @p
1971  * num. This function returns 1 on success, 0 otherwise.
1972  *
1973  * To use this function, you must call before, and in order,
1974  * ecore_x_netwm_window_state_get_prefetch(), which sends the GetProperty request,
1975  * then ecore_x_netwm_window_state_get_fetch(), which gets the reply.
1976  * @ingroup Ecore_X_NetWM_Group
1977  */
1978 EAPI int
1979 ecore_x_netwm_window_state_get(Ecore_X_Window         window,
1980                                Ecore_X_Window_State **state,
1981                                unsigned int          *num)
1982 {
1983    Ecore_X_Atom *atoms;
1984    int           num_ret;
1985    int           i;
1986
1987    if (num) *num = 0;
1988    if (state) *state = NULL;
1989
1990    num_ret = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_STATE,
1991                                                &atoms);
1992    if (num_ret <= 0)
1993       return 0;
1994
1995    if (state)
1996      {
1997         *state = malloc(num_ret * sizeof(Ecore_X_Window_State));
1998         if (*state)
1999           for (i = 0; i < num_ret; ++i)
2000             (*state)[i] = _ecore_x_netwm_state_get(atoms[i]);
2001
2002         if (num) *num = num_ret;
2003      }
2004
2005    free(atoms);
2006
2007    return 1;
2008 }
2009
2010 static Ecore_X_Window_Type
2011 _ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom)
2012 {
2013    if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP)
2014      return ECORE_X_WINDOW_TYPE_DESKTOP;
2015    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK)
2016      return ECORE_X_WINDOW_TYPE_DOCK;
2017    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR)
2018      return ECORE_X_WINDOW_TYPE_TOOLBAR;
2019    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU)
2020      return ECORE_X_WINDOW_TYPE_MENU;
2021    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY)
2022      return ECORE_X_WINDOW_TYPE_UTILITY;
2023    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH)
2024      return ECORE_X_WINDOW_TYPE_SPLASH;
2025    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG)
2026      return ECORE_X_WINDOW_TYPE_DIALOG;
2027    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL)
2028      return ECORE_X_WINDOW_TYPE_NORMAL;
2029    else
2030      return ECORE_X_WINDOW_TYPE_UNKNOWN;
2031 }
2032
2033 static Ecore_X_Atom
2034 _ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type)
2035 {
2036    switch (type)
2037      {
2038       case ECORE_X_WINDOW_TYPE_DESKTOP:
2039          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
2040       case ECORE_X_WINDOW_TYPE_DOCK:
2041          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
2042       case ECORE_X_WINDOW_TYPE_TOOLBAR:
2043          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
2044       case ECORE_X_WINDOW_TYPE_MENU:
2045          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
2046       case ECORE_X_WINDOW_TYPE_UTILITY:
2047          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
2048       case ECORE_X_WINDOW_TYPE_SPLASH:
2049          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
2050       case ECORE_X_WINDOW_TYPE_DIALOG:
2051          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
2052       case ECORE_X_WINDOW_TYPE_NORMAL:
2053          return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
2054       default:
2055          return 0;
2056      }
2057 }
2058
2059 /*
2060  * FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR
2061  * , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG
2062  */
2063
2064 /**
2065  * Set the _NET_WM_WINDOW_TYPE property.
2066  * @param window The window.
2067  * @param type   The functional type of the window.
2068  *
2069  * Set the functional @p type of @p window by sending _NET_WM_WINDOW_TYPE
2070  * property to @p window.
2071  *
2072  * This property SHOULD be set by the Client before mapping. This
2073  * property SHOULD be used by the window manager in determining the
2074  * decoration, stacking position and other behavior of the window. The
2075  * Client SHOULD specify window types in order of preference (the first
2076  * being most preferable).
2077  *
2078  * This hint is intended to replace the MOTIF hints.
2079  * @ingroup Ecore_X_NetWM_Group
2080  */
2081 EAPI void
2082 ecore_x_netwm_window_type_set(Ecore_X_Window      window,
2083                               Ecore_X_Window_Type type)
2084 {
2085    Ecore_X_Atom atom;
2086
2087    atom = _ecore_x_netwm_window_type_atom_get(type);
2088    ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
2089                                 &atom, 1);
2090 }
2091
2092 /**
2093  * Sends the GetProperty request.
2094  * @param window The window.
2095  * @ingroup Ecore_X_NetWM_Group
2096  */
2097 EAPI void
2098 ecore_x_netwm_window_type_get_prefetch(Ecore_X_Window window)
2099 {
2100    xcb_get_property_cookie_t cookie;
2101
2102    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
2103                                        ECORE_X_ATOM_NET_WM_WINDOW_TYPE, ECORE_X_ATOM_ATOM,
2104                                        0, 0x7fffffff);
2105    _ecore_xcb_cookie_cache(cookie.sequence);
2106 }
2107
2108 /**
2109  * Gets the reply of the GetProperty request sent by ecore_x_window_type_get_prefetch().
2110  * @ingroup Ecore_X_NetWM_Group
2111  */
2112 EAPI void
2113 ecore_x_netwm_window_type_get_fetch(void)
2114 {
2115    xcb_get_property_cookie_t cookie;
2116    xcb_get_property_reply_t *reply;
2117
2118    cookie.sequence = _ecore_xcb_cookie_get();
2119    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
2120    _ecore_xcb_reply_cache(reply);
2121 }
2122
2123 /* FIXME: Maybe return 0 on some conditions? */
2124
2125 /**
2126  * Get the functional type of a window.
2127  * @param window The window.
2128  * @param type   The function type of the window.
2129  * @return       1 on success, 0 otherwise.
2130  *
2131  * Retrieve the functional type of @p window. The type is stored in
2132  * @p type. This function returns 1 on success, 0 otherwise.
2133  *
2134  * To use this function, you must call before, and in order,
2135  * ecore_x_netwm_window_type_get_prefetch(), which sends the GetProperty request,
2136  * then ecore_x_netwm_window_type_get_fetch(), which gets the reply.
2137  * @ingroup Ecore_X_NetWM_Group
2138  */
2139 EAPI int
2140 ecore_x_netwm_window_type_get(Ecore_X_Window       window,
2141                               Ecore_X_Window_Type *type)
2142 {
2143    Ecore_X_Atom *atoms;
2144    int           num;
2145    int           i;
2146
2147    if (type) *type = ECORE_X_WINDOW_TYPE_NORMAL;
2148
2149    num = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
2150                                            &atoms);
2151    if (num < 0)
2152      {
2153         /* IMO this is not the place to mix netwm and icccm /kwo */
2154         /* Check if WM_TRANSIENT_FOR is set */
2155
2156         /* Disable it for xcb */
2157
2158 /*      if ((type) && (ecore_x_icccm_transient_for_get(window))) */
2159 /*        *type = ECORE_X_WINDOW_TYPE_DIALOG; */
2160 /*      return 1; */
2161      }
2162
2163    if (type)
2164      {
2165         for (i = 0; i < num; ++i)
2166           {
2167              *type = _ecore_x_netwm_window_type_type_get(atoms[i]);
2168              if (*type != ECORE_X_WINDOW_TYPE_UNKNOWN)
2169                break;
2170           }
2171      }
2172
2173    free(atoms);
2174
2175    return 1;
2176 }
2177
2178 static Ecore_X_Atom
2179 _ecore_x_netwm_action_atom_get(Ecore_X_Action action)
2180 {
2181    switch (action)
2182      {
2183       case ECORE_X_ACTION_MOVE:
2184          return ECORE_X_ATOM_NET_WM_ACTION_MOVE;
2185       case ECORE_X_ACTION_RESIZE:
2186          return ECORE_X_ATOM_NET_WM_ACTION_RESIZE;
2187       case ECORE_X_ACTION_MINIMIZE:
2188          return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE;
2189       case ECORE_X_ACTION_SHADE:
2190          return ECORE_X_ATOM_NET_WM_ACTION_SHADE;
2191       case ECORE_X_ACTION_STICK:
2192          return ECORE_X_ATOM_NET_WM_ACTION_STICK;
2193       case ECORE_X_ACTION_MAXIMIZE_HORZ:
2194          return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ;
2195       case ECORE_X_ACTION_MAXIMIZE_VERT:
2196          return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT;
2197       case ECORE_X_ACTION_FULLSCREEN:
2198          return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN;
2199       case ECORE_X_ACTION_CHANGE_DESKTOP:
2200          return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP;
2201       case ECORE_X_ACTION_CLOSE:
2202          return ECORE_X_ATOM_NET_WM_ACTION_CLOSE;
2203       default:
2204          return 0;
2205      }
2206 }
2207
2208 /**
2209  * Sends the GetProperty request.
2210  * @param window The window.
2211  * @ingroup Ecore_X_NetWM_Group
2212  */
2213 EAPI void
2214 ecore_x_netwm_allowed_action_get_prefetch(Ecore_X_Window window)
2215 {
2216    xcb_get_property_cookie_t cookie;
2217
2218    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
2219                                        ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, ECORE_X_ATOM_ATOM,
2220                                        0, 0x7fffffff);
2221    _ecore_xcb_cookie_cache(cookie.sequence);
2222 }
2223
2224 /**
2225  * Gets the reply of the GetProperty request sent by ecore_x_allowed_action_get_prefetch().
2226  * @ingroup Ecore_X_NetWM_Group
2227  */
2228 EAPI void
2229 ecore_x_netwm_allowed_action_get_fetch(void)
2230 {
2231    xcb_get_property_cookie_t cookie;
2232    xcb_get_property_reply_t *reply;
2233
2234    cookie.sequence = _ecore_xcb_cookie_get();
2235    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
2236    _ecore_xcb_reply_cache(reply);
2237 }
2238
2239 /* FIXME: Get complete list */
2240
2241 /**
2242  * Check whether an action is supported by a window.
2243  * @param window The window
2244  * @param action The action
2245  * @return       1 if set, 0 otherwise.
2246  *
2247  * Return whether the user operation @p action is supported by the
2248  * Window Manager for @p window.
2249  *
2250  * To use this function, you must call before, and in order,
2251  * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request,
2252  * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply.
2253  * @ingroup Ecore_X_NetWM_Group
2254  */
2255 EAPI int
2256 ecore_x_netwm_allowed_action_isset(Ecore_X_Window window,
2257                                    Ecore_X_Action action)
2258 {
2259    Ecore_X_Atom *atoms;
2260    Ecore_X_Atom  atom;
2261    int           num;
2262    int           ret = 0;
2263    int           i;
2264
2265    num = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
2266                                            &atoms);
2267    if (num <= 0)
2268      return ret;
2269
2270    atom = _ecore_x_netwm_action_atom_get(action);
2271
2272    for (i = 0; i < num; ++i)
2273      {
2274         if (atom == atoms[i])
2275           {
2276              ret = 1;
2277              break;
2278           }
2279      }
2280
2281    free(atoms);
2282
2283    return ret;
2284 }
2285
2286 /* FIXME: Set complete list */
2287 /**
2288  * Set the _NET_WM_ALLOWED_ACTIONS property.
2289  * @param window The window.
2290  * @param action An array of allowed actions.
2291  * @param num    The number of actions.
2292  *
2293  * Set the user operations that the Window Manager supports for
2294  * @p window by sending the _NET_WM_ALLOWED_ACTIONS property to
2295  * @p window. @p action stores @p num actions.
2296  *
2297  * To use this function, you must call before, and in order,
2298  * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request,
2299  * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply.
2300  * @ingroup Ecore_X_NetWM_Group
2301  */
2302 EAPI void
2303 ecore_x_netwm_allowed_action_set(Ecore_X_Window  window,
2304                                  Ecore_X_Action *action,
2305                                  unsigned int    num)
2306 {
2307    Ecore_X_Atom  *set;
2308    unsigned int   i;
2309
2310    if (!num)
2311      {
2312         ecore_x_window_prop_property_del(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS);
2313         return;
2314      }
2315
2316    set = malloc(num * sizeof(Ecore_X_Atom));
2317    if (!set) return;
2318
2319    for (i = 0; i < num; i++)
2320      set[i] = _ecore_x_netwm_action_atom_get(action[i]);
2321
2322    ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, set, num);
2323
2324    free(set);
2325 }
2326
2327 /**
2328  * Get the allowed actions supported by a window.
2329  * @param window The window.
2330  * @param action The returned array of the actions.
2331  * @param num    The number of actions.
2332  * @return       1 on success, 0 otherwise.
2333  *
2334  * Retrieve the user operations that the Window Manager supports for
2335  * @p window and store them in @p action. The number of actions is
2336  * stored in @p num. This function returns 1 on success, 0 otherwise.
2337  *
2338  * To use this function, you must call before, and in order,
2339  * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request,
2340  * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply.
2341  * @ingroup Ecore_X_NetWM_Group
2342  */
2343 EAPI int
2344 ecore_x_netwm_allowed_action_get(Ecore_X_Window   window,
2345                                  Ecore_X_Action **action,
2346                                  unsigned int    *num)
2347 {
2348    Ecore_X_Atom *atoms;
2349    int           num_ret;
2350    int           i;
2351
2352    if (num) *num = 0;
2353    if (action) *action = NULL;
2354
2355    num_ret = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
2356                                                &atoms);
2357    if (num_ret <= 0)
2358       return 0;
2359
2360    if (action)
2361      {
2362         *action = malloc(num_ret * sizeof(Ecore_X_Action));
2363         if (*action)
2364           for (i = 0; i < num_ret; ++i)
2365             (*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]);
2366
2367         if (num) *num = num_ret;
2368      }
2369
2370    free(atoms);
2371
2372    return 1;
2373 }
2374
2375 /**
2376  * Set the _NET_WM_WINDOW_OPACITY property.
2377  * @param window  The window.
2378  * @param opacity The opacity value.
2379  *
2380  * Set the desired opacity of @p window by sending the
2381  * _NET_WM_WINDOW_OPACITY property to @p window. @p opacity is 0 for a
2382  * transparent window and 0xffffffff for an opaque window. @p opacity
2383  * must be multiplied with the original alpha value of @p window
2384  * (which is 1 for visuals not including an alpha component) so that
2385  * @p window content is modulated by the opacity value.
2386  *
2387  * Window Managers acting as compositing managers MAY take this into
2388  * account when displaying a window. Window Managers MUST forward the
2389  * value of this property to any enclosing frame window.  This
2390  * property MAY change while the window is mapped and the Window
2391  * Manager MUST respect changes while the window is mapped.
2392  * @ingroup Ecore_X_NetWM_Group
2393  */
2394 EAPI void
2395 ecore_x_netwm_opacity_set(Ecore_X_Window window,
2396                           unsigned int   opacity)
2397 {
2398    uint32_t op = opacity;
2399    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
2400                                   &op, 1);
2401 }
2402
2403 /**
2404  * Sends the GetProperty request.
2405  * @param window The window.
2406  * @ingroup Ecore_X_NetWM_Group
2407  */
2408 EAPI void
2409 ecore_x_netwm_opacity_get_prefetch(Ecore_X_Window window)
2410 {
2411    xcb_get_property_cookie_t cookie;
2412
2413    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
2414                                        ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, ECORE_X_ATOM_CARDINAL,
2415                                        0, 0x7fffffff);
2416    _ecore_xcb_cookie_cache(cookie.sequence);
2417 }
2418
2419 /**
2420  * Gets the reply of the GetProperty request sent by ecore_x_netwm_opacity_get_prefetch().
2421  * @ingroup Ecore_X_NetWM_Group
2422  */
2423 EAPI void
2424 ecore_x_netwm_opacity_get_fetch(void)
2425 {
2426    xcb_get_property_cookie_t cookie;
2427    xcb_get_property_reply_t *reply;
2428
2429    cookie.sequence = _ecore_xcb_cookie_get();
2430    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
2431    _ecore_xcb_reply_cache(reply);
2432 }
2433
2434 /**
2435  * Get the opacity value of a window.
2436  * @param window  The window.
2437  * @param opacity The returned opacity.
2438  * @return        1 on success, 0 otherwise.
2439  *
2440  * Retriee the opacity value of @p window and store it in
2441  * @p opacity. This function returns 1 on sucess, 0 otherwise.
2442  *
2443  * To use this function, you must call before, and in order,
2444  * ecore_x_netwm_opacity_get_prefetch(), which sends the GetProperty request,
2445  * then ecore_x_netwm_opacity_get_fetch(), which gets the reply.
2446  * @ingroup Ecore_X_NetWM_Group
2447  */
2448 EAPI int
2449 ecore_x_netwm_opacity_get(Ecore_X_Window window,
2450                           unsigned int  *opacity)
2451 {
2452    int ret;
2453    unsigned int tmp;
2454
2455    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
2456                                         &tmp, 1);
2457    if (opacity) *opacity = tmp;
2458    return ret == 1 ? 1 : 0;
2459 }
2460
2461 /**
2462  * Set the _NET_FRAME_EXTENTS property.
2463  * @param window The window.
2464  * @param fl     The number of pixels of the left border of the window.
2465  * @param fr     The number of pixels of the right border of the window.
2466  * @param ft     The number of pixels of the top border of the window.
2467  * @param fb     The number of pixels of the bottom border of the window.
2468  *
2469  * Set the border witdh of @p window by sending the _NET_FRAME_EXTENTS
2470  * property to @p window. @p fl, @p fr, @p ft and @p fb are respectively
2471  * the number of pixels of the left, right, top and bottom border of
2472  * @p window.
2473  *
2474  * The Window Manager MUST set _NET_FRAME_EXTENTS to the extents of
2475  * the window's frame.
2476  * @ingroup Ecore_X_NetWM_Group
2477  */
2478 EAPI void
2479 ecore_x_netwm_frame_size_set(Ecore_X_Window window,
2480                              int            fl,
2481                              int            fr,
2482                              int            ft,
2483                              int            fb)
2484 {
2485    uint32_t frames[4];
2486
2487    frames[0] = fl;
2488    frames[1] = fr;
2489    frames[2] = ft;
2490    frames[3] = fb;
2491    ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4);
2492 }
2493
2494 /**
2495  * Sends the GetProperty request.
2496  * @param window The window.
2497  * @ingroup Ecore_X_NetWM_Group
2498  */
2499 EAPI void
2500 ecore_x_netwm_frame_size_get_prefetch(Ecore_X_Window window)
2501 {
2502    xcb_get_property_cookie_t cookie;
2503
2504    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
2505                                        ECORE_X_ATOM_NET_FRAME_EXTENTS, ECORE_X_ATOM_CARDINAL,
2506                                        0, 0x7fffffff);
2507    _ecore_xcb_cookie_cache(cookie.sequence);
2508 }
2509
2510 /**
2511  * Gets the reply of the GetProperty request sent by ecore_x_netwm_frame_size_get_prefetch().
2512  * @ingroup Ecore_X_NetWM_Group
2513  */
2514 EAPI void
2515 ecore_x_netwm_frame_size_get_fetch(void)
2516 {
2517    xcb_get_property_cookie_t cookie;
2518    xcb_get_property_reply_t *reply;
2519
2520    cookie.sequence = _ecore_xcb_cookie_get();
2521    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
2522    _ecore_xcb_reply_cache(reply);
2523 }
2524
2525 /**
2526  * Get the frame extent of a window.
2527  * @param window  The window.
2528  * @param fl      The number of pixels of the left border of the window.
2529  * @param fr      The number of pixels of the right border of the window.
2530  * @param ft      The number of pixels of the top border of the window.
2531  * @param fb      The number of pixels of the bottom border of the window.
2532  * @return        1 on success, 0 otherwise.
2533  *
2534  * Retrieve the frame extents of @p window. The number of pixels of
2535  * the left, right, top and bottom border of @p window are
2536  * respectively stored in @p fl, @p fr, @p ft anfd @p fb. TYhis
2537  * function retuirns 1 on success, 0 otherwise.
2538  *
2539  * To use this function, you must call before, and in order,
2540  * ecore_x_netwm_frame_size_get_prefetch(), which sends the GetProperty request,
2541  * then ecore_x_netwm_frame_size_get_fetch(), which gets the reply.
2542  * @ingroup Ecore_X_NetWM_Group
2543  */
2544 EAPI int
2545 ecore_x_netwm_frame_size_get(Ecore_X_Window window,
2546                              int           *fl,
2547                              int           *fr,
2548                              int           *ft,
2549                              int           *fb)
2550 {
2551    uint32_t frames[4];
2552    int      ret = 0;
2553
2554    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4);
2555    if (ret != 4)
2556      return 0;
2557
2558    if (fl) *fl = frames[0];
2559    if (fr) *fr = frames[1];
2560    if (ft) *ft = frames[2];
2561    if (fb) *fb = frames[3];
2562    return 1;
2563 }
2564
2565 /**
2566  * Sends the GetProperty request.
2567  * @param window The window.
2568  * @ingroup Ecore_X_NetWM_Group
2569  */
2570 EAPI void
2571 ecore_x_netwm_sync_counter_get_prefetch(Ecore_X_Window window)
2572 {
2573    xcb_get_property_cookie_t cookie;
2574
2575    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
2576                                        ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER, ECORE_X_ATOM_CARDINAL,
2577                                        0, 0x7fffffff);
2578    _ecore_xcb_cookie_cache(cookie.sequence);
2579 }
2580
2581 /**
2582  * Gets the reply of the GetProperty request sent by ecore_x_netwm_sync_counter_get_prefetch().
2583  * @ingroup Ecore_X_NetWM_Group
2584  */
2585 EAPI void
2586 ecore_x_netwm_sync_counter_get_fetch(void)
2587 {
2588    xcb_get_property_cookie_t cookie;
2589    xcb_get_property_reply_t *reply;
2590
2591    cookie.sequence = _ecore_xcb_cookie_get();
2592    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
2593    _ecore_xcb_reply_cache(reply);
2594 }
2595
2596 /**
2597  * Get the X ID of a X Sync counter.
2598  * @param window  The window.
2599  * @param counter The X ID of the Sync counter.
2600  * @return        1 on success, 0 otherwise.
2601  *
2602  * Retrieve the X ID of the X Sync counter of @p window and store it
2603  * in @p counter. This function returns 1 on success, 0 otherwise.
2604  *
2605  * To use this function, you must call before, and in order,
2606  * ecore_x_netwm_frame_size_get_prefetch(), which sends the GetProperty request,
2607  * then ecore_x_netwm_frame_size_get_fetch(), which gets the reply.
2608  * @ingroup Ecore_X_NetWM_Group
2609  */
2610 EAPI int
2611 ecore_x_netwm_sync_counter_get(Ecore_X_Window        window,
2612                                Ecore_X_Sync_Counter *counter)
2613 {
2614    int          ret;
2615    unsigned int tmp;
2616
2617    ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER,
2618                                         &tmp, 1);
2619
2620    if (counter) *counter = tmp;
2621    return (ret == 1) ? 1 : 0;
2622 }
2623
2624 /**
2625  * Send a _NET_WM_PING property event.
2626  * @param window The window.
2627  *
2628  * Send a ClientMessage event from @p window with the _NET_WM_PING
2629  * property set.
2630  * @ingroup Ecore_X_NetWM_Group
2631  */
2632 EAPI void
2633 ecore_x_netwm_ping_send(Ecore_X_Window window)
2634 {
2635    xcb_client_message_event_t ev;
2636
2637    if (!window) return;
2638
2639    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
2640    ev.format = 32;
2641    ev.sequence = 0;
2642    ev.window = window;
2643    ev.type = ECORE_X_ATOM_WM_PROTOCOLS;
2644    ev.data.data32[0] = ECORE_X_ATOM_NET_WM_PING;
2645    ev.data.data32[1] = XCB_CURRENT_TIME;
2646    ev.data.data32[2] = window;
2647    ev.data.data32[3] = 0;
2648    ev.data.data32[4] = 0;
2649    ev.data.data32[5] = 0;
2650
2651    xcb_send_event(_ecore_xcb_conn, 0, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
2652 }
2653
2654 /**
2655  * Send a _NET_WM_SYNC_REQUEST property event.
2656  * @param window The window.
2657  * @param serial The update request number.
2658  *
2659  * Send a ClientMessage event from @p window with the _NET_WM_SYNC_REQUEST
2660  * property set.
2661  * @ingroup Ecore_X_NetWM_Group
2662  */
2663 EAPI void
2664 ecore_x_netwm_sync_request_send(Ecore_X_Window window,
2665                                 unsigned int   serial)
2666 {
2667    xcb_client_message_event_t ev;
2668
2669    if (!window) return;
2670
2671    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
2672    ev.format = 32;
2673    ev.window = window;
2674    ev.type = ECORE_X_ATOM_WM_PROTOCOLS;
2675    ev.data.data32[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
2676    ev.data.data32[1] = XCB_CURRENT_TIME;
2677    ev.data.data32[2] = serial;
2678    /* FIXME: imho, the following test is useless as serial is non negative */
2679    /* should we remove it ? */
2680    ev.data.data32[3] = (serial < 0) ? ~0L : 0L;
2681    ev.data.data32[4] = 0;
2682
2683    xcb_send_event(_ecore_xcb_conn, 0, window, 0, (const char *)&ev);
2684 }
2685
2686 /**
2687  * Send a _NET_WM_STATE property event.
2688  * @param window The window.
2689  * @param root   The root window.
2690  * @param s1     The first state to alter.
2691  * @param s2     The second state to alter.
2692  * @param set    0 to unset the property, set it otherwise.
2693  *
2694  * Send a ClientMessage event from @p window to the @p root window
2695  * with the _NET_WM_STATE property set. This change the state of a
2696  * mapped window. @p s1 is the first state to alter. @p s2 is the
2697  * second state to alter. If @p set value is 0, the property is
2698  * removed (or unset), otherwise, the property is set.
2699  * @ingroup Ecore_X_NetWM_Group
2700  */
2701 EAPI void
2702 ecore_x_netwm_state_request_send(Ecore_X_Window       window,
2703                                  Ecore_X_Window       root,
2704                                  Ecore_X_Window_State s1,
2705                                  Ecore_X_Window_State s2,
2706                                  int                  set)
2707 {
2708    xcb_client_message_event_t ev;
2709
2710    if (!window) return;
2711    if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
2712
2713    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
2714    ev.format = 32;
2715    ev.window = window;
2716    ev.type = ECORE_X_ATOM_NET_WM_STATE;
2717    ev.data.data32[0] = !!set;
2718    ev.data.data32[1] = _ecore_x_netwm_state_atom_get(s1);
2719    ev.data.data32[2] = _ecore_x_netwm_state_atom_get(s2);
2720    /* 1 == normal client, if someone wants to use this
2721     * function in a pager, this should be 2 */
2722    ev.data.data32[3] = 1;
2723    ev.data.data32[4] = 0;
2724
2725    xcb_send_event(_ecore_xcb_conn, 0, root,
2726                   XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
2727                   (const char *)&ev);
2728 }
2729
2730 /**
2731  * Send a _NET_WM_DESKTOP property event.
2732  * @param window  The window.
2733  * @param root    The root window.
2734  * @param desktop The new desktop index.
2735  *
2736  * Send a ClientMessage event from @p window to the @p root window
2737  * with the _NET_WM_DESKTOP property set. This change the state of a
2738  * non-withdrawn window. @p desktop is the new desktop index to set.
2739  * @ingroup Ecore_X_NetWM_Group
2740  */
2741 EAPI void
2742 ecore_x_netwm_desktop_request_send(Ecore_X_Window window,
2743                                    Ecore_X_Window root,
2744                                    unsigned int   desktop)
2745 {
2746    xcb_client_message_event_t ev;
2747
2748    if (!window) return;
2749    if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
2750
2751    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
2752    ev.format = 32;
2753    ev.window = window;
2754    ev.type = ECORE_X_ATOM_NET_WM_DESKTOP;
2755    ev.data.data32[0] = desktop;
2756
2757    xcb_send_event(_ecore_xcb_conn, 0, root,
2758                   XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
2759                   (const char *)&ev);
2760 }
2761
2762 int
2763 _ecore_x_netwm_startup_info_begin(Ecore_X_Window window,
2764                                   char          *data)
2765 {
2766 #if 0
2767    Ecore_X_Startup_Info *info;
2768
2769    if (!startup_info) return 0;
2770    info = ecore_hash_get(startup_info, (void *)window);
2771    if (info)
2772      {
2773         printf("Already got info for win: 0x%x\n", window);
2774         _ecore_x_netwm_startup_info_free(info);
2775      }
2776    info = calloc(1, sizeof(Ecore_X_Startup_Info));
2777    if (!info) return 0;
2778    info->win = win;
2779    info->length = 0;
2780    info->buffer_size = 161;
2781    info->buffer = calloc(info->buffer_size, sizeof(char));
2782    if (!info->buffer)
2783      {
2784         _ecore_x_netwm_startup_info_free(info);
2785         return 0;
2786      }
2787    memcpy(info->buffer, data, 20);
2788    info->length += 20;
2789    info->buffer[info->length] = 0;
2790    ecore_hash_set(startup_info, (void *)info->win, info);
2791    if (strlen(info->buffer) != 20)
2792      {
2793         /* We have a '\0' in there, the message is done */
2794         _ecore_x_netwm_startup_info_process(info);
2795      }
2796 #else
2797    window = XCB_NONE;
2798    data = NULL;
2799 #endif
2800
2801    return 1;
2802 }
2803
2804 int
2805 _ecore_x_netwm_startup_info(Ecore_X_Window window,
2806                             char          *data)
2807 {
2808 #if 0
2809    Ecore_X_Startup_Info *info;
2810    char *p;
2811
2812    if (!startup_info) return 0;
2813    info = ecore_hash_get(startup_info, (void *)window);
2814    if (!info) return 0;
2815    if ((info->length + 20) > info->buffer_size)
2816      {
2817         info->buffer_size += 160;
2818         info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char));
2819         if (!info->buffer)
2820           {
2821              ecore_hash_remove(startup_info, (void *)info->win);
2822              _ecore_x_netwm_startup_info_free(info);
2823              return 0;
2824           }
2825      }
2826    memcpy(info->buffer + info->length, data, 20);
2827    p = info->buffer + info->length;
2828    info->length += 20;
2829    info->buffer[info->length] = 0;
2830    if (strlen(p) != 20)
2831      {
2832         /* We have a '\0' in there, the message is done */
2833         _ecore_x_netwm_startup_info_process(info);
2834      }
2835 #else
2836    window = XCB_NONE;
2837    data = NULL;
2838 #endif
2839
2840    return 1;
2841 }
2842
2843 /*
2844  * Set UTF-8 string property
2845  */
2846 static void
2847 _ecore_x_window_prop_string_utf8_set(Ecore_X_Window window,
2848                                      Ecore_X_Atom   atom,
2849                                      const char    *str)
2850 {
2851    xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
2852                        atom, ECORE_X_ATOM_UTF8_STRING,
2853                        8, strlen(str), str);
2854 }
2855
2856 #if 0
2857 static void
2858 _ecore_x_window_prop_string_utf8_get_prefetch(Ecore_X_Window window,
2859                                               Ecore_X_Atom atom)
2860 {
2861    xcb_get_property_cookie_t cookie;
2862
2863    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
2864                                        atom, ECORE_X_ATOM_UTF8_STRING,
2865                                        0, 0x7fffffff);
2866    _ecore_xcb_cookie_cache(cookie.sequence);
2867 }
2868
2869 static void
2870 _ecore_x_window_prop_string_utf8_get_fetch(void)
2871 {
2872    xcb_get_property_cookie_t cookie;
2873    xcb_get_property_reply_t *reply;
2874
2875    cookie.sequence = _ecore_xcb_cookie_get();
2876    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
2877    _ecore_xcb_reply_cache(reply);
2878 }
2879 #endif
2880
2881 /*
2882  * Get UTF-8 string property
2883  */
2884 static char *
2885 _ecore_x_window_prop_string_utf8_get(Ecore_X_Window window __UNUSED__,
2886                                      Ecore_X_Atom   atom __UNUSED__)
2887 {
2888    xcb_get_property_reply_t *reply;
2889    char                     *str;
2890    int                       length;
2891
2892    reply = _ecore_xcb_reply_get();
2893    if (!reply) return NULL;
2894
2895    if ((reply->format != 8) ||
2896        (reply->value_len <= 0))
2897       return NULL;
2898
2899    length = reply->value_len;
2900    str = (char *)malloc (sizeof (char) * (length + 1));
2901    if (!str)
2902      {
2903         return NULL;
2904      }
2905    memcpy(str, xcb_get_property_value(reply), length);
2906    str[length] = '\0';
2907
2908    return str;
2909 }
2910
2911 #if 0 /* Unused */
2912 /*
2913  * Process startup info
2914  */
2915 static int
2916 _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info)
2917 {
2918    Ecore_X_Event_Startup_Sequence *e;
2919    int                             event;
2920    char                           *p;
2921
2922    p = strchr(info->buffer, ':');
2923    if (!p)
2924      {
2925         ecore_hash_remove(startup_info, (void *)info->win);
2926         _ecore_x_netwm_startup_info_free(info);
2927         return 0;
2928      }
2929    *p = 0;
2930    if (!strcmp(info->buffer, "new"))
2931      {
2932         if (info->init)
2933           event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
2934         else
2935           event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW;
2936         info->init = 1;
2937      }
2938    else if (!strcmp(info->buffer, "change"))
2939      {
2940         event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
2941      }
2942    else if (!strcmp(info->buffer, "remove"))
2943      event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE;
2944    else
2945      {
2946         ecore_hash_remove(startup_info, (void *)info->win);
2947         _ecore_x_netwm_startup_info_free(info);
2948         return 0;
2949      }
2950
2951    p++;
2952
2953    if (!_ecore_x_netwm_startup_info_parse(info, p))
2954      {
2955         ecore_hash_remove(startup_info, (void *)info->win);
2956         _ecore_x_netwm_startup_info_free(info);
2957         return 0;
2958      }
2959
2960    if (info->init)
2961      {
2962         e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence));
2963         if (!e)
2964           {
2965              ecore_hash_remove(startup_info, (void *)info->win);
2966              _ecore_x_netwm_startup_info_free(info);
2967              return 0;
2968           }
2969         e->win = info->win;
2970         ecore_event_add(event, e, NULL, NULL);
2971      }
2972
2973    if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE)
2974      {
2975         ecore_hash_remove(startup_info, (void *)info->win);
2976         _ecore_x_netwm_startup_info_free(info);
2977      }
2978    else
2979      {
2980         /* Discard buffer */
2981         info->length = 0;
2982         info->buffer[0] = 0;
2983      }
2984    return 1;
2985 }
2986
2987 /*
2988  * Parse startup info
2989  */
2990 static int
2991 _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
2992                                   char                 *data)
2993 {
2994
2995    while (*data)
2996      {
2997         int in_quot_sing, in_quot_dbl, escaped;
2998         char *p, *pp;
2999         char *key;
3000         char value[1024];
3001
3002         /* Skip space */
3003         while (*data == ' ') data++;
3004         /* Get key */
3005         key = data;
3006         data = strchr(key, '=');
3007         if (!data) return 0;
3008         *data = 0;
3009         data++;
3010
3011         /* Get value */
3012         p = data;
3013         pp = value;
3014         in_quot_dbl = 0;
3015         in_quot_sing = 0;
3016         escaped = 0;
3017         while (*p)
3018           {
3019              if ((pp - value) >= 1024) return 0;
3020              if (escaped)
3021                {
3022                   *pp = *p;
3023                   pp++;
3024                   escaped = 0;
3025                }
3026              else if (in_quot_sing)
3027                {
3028                   if (*p == '\\')
3029                     escaped = 1;
3030                   else if (*p == '\'')
3031                     in_quot_sing = 0;
3032                   else
3033                     {
3034                        *pp = *p;
3035                        pp++;
3036                     }
3037                }
3038              else if (in_quot_dbl)
3039                {
3040                   if (*p == '\\')
3041                     escaped = 1;
3042                   else if (*p == '\"')
3043                     in_quot_dbl = 0;
3044                   else
3045                     {
3046                        *pp = *p;
3047                        pp++;
3048                     }
3049                }
3050              else
3051                {
3052                   if (*p == '\\')
3053                     escaped = 1;
3054                   else if (*p == '\'')
3055                     in_quot_sing = 1;
3056                   else if (*p == '\"')
3057                     in_quot_dbl = 1;
3058                   else if (*p == ' ')
3059                     {
3060                        break;
3061                     }
3062                   else
3063                     {
3064                        *pp = *p;
3065                        pp++;
3066                     }
3067                }
3068              p++;
3069           }
3070         if ((in_quot_dbl) || (in_quot_sing)) return 0;
3071         data = p;
3072         *pp = 0;
3073
3074         /* Parse info */
3075         if (!strcmp(key, "ID"))
3076           {
3077              if ((info->id) && (strcmp(info->id, value))) return 0;
3078              info->id = strdup(value);
3079              p = strstr(value, "_TIME");
3080              if (p)
3081                {
3082                   info->timestamp = atoi(p + 5);
3083                }
3084           }
3085         else if (!strcmp(key, "NAME"))
3086           {
3087              if (info->name) free(info->name);
3088              info->name = strdup(value);
3089           }
3090         else if (!strcmp(key, "SCREEN"))
3091           {
3092              info->screen = atoi(value);
3093           }
3094         else if (!strcmp(key, "BIN"))
3095           {
3096              if (info->bin) free(info->bin);
3097              info->bin = strdup(value);
3098           }
3099         else if (!strcmp(key, "ICON"))
3100           {
3101              if (info->icon) free(info->icon);
3102              info->icon = strdup(value);
3103           }
3104         else if (!strcmp(key, "DESKTOP"))
3105           {
3106              info->desktop = atoi(value);
3107           }
3108         else if (!strcmp(key, "TIMESTAMP"))
3109           {
3110              if (!info->timestamp)
3111                info->timestamp = atoi(value);
3112           }
3113         else if (!strcmp(key, "DESCRIPTION"))
3114           {
3115              if (info->description) free(info->description);
3116              info->description = strdup(value);
3117           }
3118         else if (!strcmp(key, "WMCLASS"))
3119           {
3120              if (info->wmclass) free(info->wmclass);
3121              info->wmclass = strdup(value);
3122           }
3123         else if (!strcmp(key, "SILENT"))
3124           {
3125              info->silent = atoi(value);
3126           }
3127         else
3128           {
3129              printf("Ecore X Sequence, Unknown: %s=%s\n", key, value);
3130           }
3131      }
3132    if (!info->id) return 0;
3133    return 1;
3134 }
3135 #endif
3136
3137 /*
3138  * Free startup info struct
3139  */
3140 static void
3141 _ecore_x_netwm_startup_info_free(void *data)
3142 {
3143    Ecore_X_Startup_Info *info;
3144
3145    info = data;
3146    if (!info) return;
3147    if (info->buffer) free(info->buffer);
3148    if (info->id) free(info->id);
3149    if (info->name) free(info->name);
3150    if (info->bin) free(info->bin);
3151    if (info->icon) free(info->icon);
3152    if (info->description) free(info->description);
3153    if (info->wmclass) free(info->wmclass);
3154    free(info);
3155 }
3156
3157 /*
3158  * Is screen composited?
3159  */
3160
3161 /* FIXME: one round trip can be removed. Can we keep it ? */
3162
3163 /**
3164  * Check whether a screen is composited or not.
3165  * @param screen The screen index.
3166  *
3167  * Return 1 if @p screen is composited, 0 otherwise.
3168  * @ingroup Ecore_X_NetWM_Group
3169  */
3170 EAPI int
3171 ecore_x_screen_is_composited(int screen)
3172 {
3173    char                             buf[32];
3174    xcb_intern_atom_cookie_t         cookie_atom;
3175    xcb_get_selection_owner_cookie_t cookie_owner;
3176    xcb_intern_atom_reply_t         *reply_atom;
3177    xcb_get_selection_owner_reply_t *reply_owner;
3178    Ecore_X_Window                   window;
3179    Ecore_X_Atom                     atom;
3180
3181    snprintf(buf, sizeof(buf), "_NET_WM_CM_S%d", screen);
3182    cookie_atom = xcb_intern_atom_unchecked(_ecore_xcb_conn, 1,
3183                                            strlen(buf), buf);
3184    reply_atom = xcb_intern_atom_reply(_ecore_xcb_conn, cookie_atom, NULL);
3185    if (!reply_atom) return 0;
3186    atom = reply_atom->atom;
3187    free(reply_atom);
3188
3189    cookie_owner = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, atom);
3190    reply_owner = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie_owner, NULL);
3191    if (!reply_owner) return 0;
3192
3193    window = reply_owner->owner;
3194    free(reply_owner);
3195
3196    return window != XCB_NONE;
3197 }