Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_x / xlib / ecore_x_netwm.c
1 /*
2  * _NET_WM... aka Extended Window Manager Hint (EWMH) functions.
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "Ecore.h"
14 #include "ecore_x_private.h"
15 #include "Ecore_X.h"
16
17 typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info;
18
19 struct _Ecore_X_Startup_Info
20 {
21    Ecore_X_Window win;
22
23    int            init;
24
25    int            buffer_size;
26    char          *buffer;
27
28    int            length;
29
30    /* These are the sequence info fields */
31    char          *id;
32    char          *name;
33    int            screen;
34    char          *bin;
35    char          *icon;
36    int            desktop;
37    int            timestamp;
38    char          *description;
39    char          *wmclass;
40    int            silent;
41 };
42
43 static void  _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win,
44                                                   Ecore_X_Atom atom,
45                                                   const char *str);
46 static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win,
47                                                   Ecore_X_Atom atom);
48 #if 0 /* Unused */
49 static int   _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info);
50 static int   _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
51                                                char *data);
52 #endif /* if 0 */
53 static void  _ecore_x_netwm_startup_info_free(void *data);
54
55 /*
56  * Convenience macros
57  */
58 #define _ATOM_SET_UTF8_STRING_LIST(win, atom, string, cnt) \
59   XChangeProperty(_ecore_x_disp,                           \
60                   win,                                     \
61                   atom,                                    \
62                   ECORE_X_ATOM_UTF8_STRING,                \
63                   8,                                       \
64                   PropModeReplace,                         \
65                   (unsigned char *)string,                 \
66                   cnt)
67
68 /*
69  * Local variables
70  */
71
72 static Eina_Hash *startup_info = NULL;
73
74 EAPI void
75 ecore_x_netwm_init(void)
76 {
77    LOGFN(__FILE__, __LINE__, __FUNCTION__);
78    startup_info = eina_hash_string_superfast_new(
79        _ecore_x_netwm_startup_info_free);
80 }
81
82 EAPI void
83 ecore_x_netwm_shutdown(void)
84 {
85    LOGFN(__FILE__, __LINE__, __FUNCTION__);
86    if (startup_info)
87      eina_hash_free(startup_info);
88
89    startup_info = NULL;
90 }
91
92 /*
93  * WM identification
94  */
95 EAPI void
96 ecore_x_netwm_wm_identify(Ecore_X_Window root,
97                           Ecore_X_Window check,
98                           const char *wm_name)
99 {
100    LOGFN(__FILE__, __LINE__, __FUNCTION__);
101    ecore_x_window_prop_window_set(check,
102                                   ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
103                                   &check,
104                                   1);
105    _ecore_x_window_prop_string_utf8_set(check,
106                                         ECORE_X_ATOM_NET_WM_NAME,
107                                         wm_name);
108    /* This one isn't mandatory */
109    _ecore_x_window_prop_string_utf8_set(root,
110                                         ECORE_X_ATOM_NET_WM_NAME,
111                                         wm_name);
112    ecore_x_window_prop_window_set(root,
113                                   ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
114                                   &check,
115                                   1);
116 }
117
118 /*
119  * Set supported atoms
120  */
121 EAPI void
122 ecore_x_netwm_supported_set(Ecore_X_Window root,
123                             Ecore_X_Atom *supported,
124                             int num)
125 {
126    LOGFN(__FILE__, __LINE__, __FUNCTION__);
127    ecore_x_window_prop_atom_set(root,
128                                 ECORE_X_ATOM_NET_SUPPORTED,
129                                 supported,
130                                 num);
131 }
132
133 EAPI Eina_Bool
134 ecore_x_netwm_supported_get(Ecore_X_Window root,
135                             Ecore_X_Atom **supported,
136                             int *num)
137 {
138    int num_ret;
139
140    if (num)
141      *num = 0;
142
143    if (supported)
144      *supported = NULL;
145
146    LOGFN(__FILE__, __LINE__, __FUNCTION__);
147    num_ret = ecore_x_window_prop_atom_list_get(root, ECORE_X_ATOM_NET_SUPPORTED,
148                                                supported);
149    if (num_ret <= 0)
150      return EINA_FALSE;
151
152    if (num)
153      *num = num_ret;
154
155    return EINA_TRUE;
156 }
157
158 /*
159  * Desktop configuration and status
160  */
161 EAPI void
162 ecore_x_netwm_desk_count_set(Ecore_X_Window root,
163                              unsigned int n_desks)
164 {
165    LOGFN(__FILE__, __LINE__, __FUNCTION__);
166    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS,
167                                   &n_desks, 1);
168 }
169
170 EAPI void
171 ecore_x_netwm_desk_roots_set(Ecore_X_Window root,
172                              Ecore_X_Window *vroots,
173                              unsigned int n_desks)
174 {
175    LOGFN(__FILE__, __LINE__, __FUNCTION__);
176    ecore_x_window_prop_window_set(root,
177                                   ECORE_X_ATOM_NET_VIRTUAL_ROOTS,
178                                   vroots,
179                                   n_desks);
180 }
181
182 EAPI void
183 ecore_x_netwm_desk_names_set(Ecore_X_Window root,
184                              const char **names,
185                              unsigned int n_desks)
186 {
187    char ss[32], *buf, *t;
188    const char *s;
189    unsigned int i;
190    int l, len;
191
192    LOGFN(__FILE__, __LINE__, __FUNCTION__);
193    buf = NULL;
194    len = 0;
195
196    for (i = 0; i < n_desks; i++)
197      {
198         s = (names) ? names[i] : NULL;
199         if (!s)
200           {
201              /* Default to "Desk-<number>" */
202              sprintf(ss, "Desk-%d", i);
203              s = ss;
204           }
205
206         l = strlen(s) + 1;
207         t = realloc(buf, len + l);
208         if (t)
209           {
210              buf = t;
211              memcpy(buf + len, s, l);
212           }
213         len += l;
214      }
215
216    _ATOM_SET_UTF8_STRING_LIST(root, ECORE_X_ATOM_NET_DESKTOP_NAMES, buf, len);
217
218    free(buf);
219 }
220
221 EAPI void
222 ecore_x_netwm_desk_size_set(Ecore_X_Window root,
223                             unsigned int width,
224                             unsigned int height)
225 {
226    unsigned int size[2];
227
228    LOGFN(__FILE__, __LINE__, __FUNCTION__);
229    size[0] = width;
230    size[1] = height;
231    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, size,
232                                   2);
233 }
234
235 EAPI void
236 ecore_x_netwm_desk_viewports_set(Ecore_X_Window root,
237                                  unsigned int *origins,
238                                  unsigned int n_desks)
239 {
240    LOGFN(__FILE__, __LINE__, __FUNCTION__);
241    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT,
242                                   origins, 2 * n_desks);
243 }
244
245 EAPI void
246 ecore_x_netwm_desk_layout_set(Ecore_X_Window root,
247                               int orientation,
248                               int columns,
249                               int rows,
250                               int starting_corner)
251 {
252    unsigned int layout[4];
253
254    LOGFN(__FILE__, __LINE__, __FUNCTION__);
255    layout[0] = orientation;
256    layout[1] = columns;
257    layout[2] = rows;
258    layout[3] = starting_corner;
259    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT,
260                                   layout, 4);
261 }
262
263 EAPI void
264 ecore_x_netwm_desk_workareas_set(Ecore_X_Window root,
265                                  unsigned int *areas,
266                                  unsigned int n_desks)
267 {
268    LOGFN(__FILE__, __LINE__, __FUNCTION__);
269    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas,
270                                   4 * n_desks);
271 }
272
273 EAPI unsigned int *
274 ecore_x_netwm_desk_workareas_get(Ecore_X_Window root, unsigned int *n_desks)
275 {
276    int ret;
277    unsigned int *areas = NULL;
278
279    if (!root) root = DefaultRootWindow(_ecore_x_disp);
280
281    ret = ecore_x_window_prop_card32_list_get(root, ECORE_X_ATOM_NET_WORKAREA,
282                                              &areas);
283    if (!areas)
284      {
285         if (n_desks) *n_desks = 0;
286         return 0;
287      }
288    if (n_desks) *n_desks = ret / 4;
289    return areas;
290 }
291
292 EAPI void
293 ecore_x_netwm_desk_current_set(Ecore_X_Window root,
294                                unsigned int desk)
295 {
296    LOGFN(__FILE__, __LINE__, __FUNCTION__);
297    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, &desk,
298                                   1);
299 }
300
301 EAPI void
302 ecore_x_netwm_showing_desktop_set(Ecore_X_Window root,
303                                   Eina_Bool on)
304 {
305    unsigned int val;
306
307    LOGFN(__FILE__, __LINE__, __FUNCTION__);
308    val = (on) ? 1 : 0;
309    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, &val,
310                                   1);
311 }
312
313 /*
314  * Client status
315  */
316
317 /* Mapping order */
318 EAPI void
319 ecore_x_netwm_client_list_set(Ecore_X_Window root,
320                               Ecore_X_Window *p_clients,
321                               unsigned int n_clients)
322 {
323    LOGFN(__FILE__, __LINE__, __FUNCTION__);
324    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST,
325                                   p_clients, n_clients);
326 }
327
328 /* Stacking order */
329 EAPI void
330 ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root,
331                                        Ecore_X_Window *p_clients,
332                                        unsigned int n_clients)
333 {
334    LOGFN(__FILE__, __LINE__, __FUNCTION__);
335    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING,
336                                   p_clients, n_clients);
337 }
338
339 EAPI void
340 ecore_x_netwm_client_active_set(Ecore_X_Window root,
341                                 Ecore_X_Window win)
342 {
343    LOGFN(__FILE__, __LINE__, __FUNCTION__);
344    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_ACTIVE_WINDOW,
345                                   &win, 1);
346 }
347
348 EAPI void
349 ecore_x_netwm_client_active_request(Ecore_X_Window root,
350                                     Ecore_X_Window win,
351                                     int type,
352                                     Ecore_X_Window current_win)
353 {
354    XEvent xev;
355
356    LOGFN(__FILE__, __LINE__, __FUNCTION__);
357    if (!root)
358      root = DefaultRootWindow(_ecore_x_disp);
359
360    xev.xclient.type = ClientMessage;
361    xev.xclient.display = _ecore_x_disp;
362    xev.xclient.window = win;
363    xev.xclient.message_type = ECORE_X_ATOM_NET_ACTIVE_WINDOW;
364    xev.xclient.format = 32;
365    xev.xclient.data.l[0] = type;
366    xev.xclient.data.l[1] = CurrentTime;
367    xev.xclient.data.l[2] = current_win;
368    xev.xclient.data.l[3] = 0;
369    xev.xclient.data.l[4] = 0;
370
371    XSendEvent(_ecore_x_disp, root, False,
372               SubstructureRedirectMask | SubstructureNotifyMask, &xev);
373 }
374
375 EAPI void
376 ecore_x_netwm_name_set(Ecore_X_Window win,
377                        const char *name)
378 {
379    LOGFN(__FILE__, __LINE__, __FUNCTION__);
380    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_NAME, name);
381 }
382
383 EAPI int
384 ecore_x_netwm_name_get(Ecore_X_Window win,
385                        char **name)
386 {
387    LOGFN(__FILE__, __LINE__, __FUNCTION__);
388    if (name)
389      *name = _ecore_x_window_prop_string_utf8_get(win,
390                                                   ECORE_X_ATOM_NET_WM_NAME);
391
392    return 1;
393 }
394
395 EAPI void
396 ecore_x_netwm_startup_id_set(Ecore_X_Window win,
397                              const char *id)
398 {
399    LOGFN(__FILE__, __LINE__, __FUNCTION__);
400    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_STARTUP_ID, id);
401 }
402
403 EAPI int
404 ecore_x_netwm_startup_id_get(Ecore_X_Window win,
405                              char **id)
406 {
407    LOGFN(__FILE__, __LINE__, __FUNCTION__);
408    if (id)
409      *id = _ecore_x_window_prop_string_utf8_get(win,
410                                                 ECORE_X_ATOM_NET_STARTUP_ID);
411
412    return 1;
413 }
414
415 EAPI void
416 ecore_x_netwm_visible_name_set(Ecore_X_Window win,
417                                const char *name)
418 {
419    LOGFN(__FILE__, __LINE__, __FUNCTION__);
420    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME,
421                                         name);
422 }
423
424 EAPI int
425 ecore_x_netwm_visible_name_get(Ecore_X_Window win,
426                                char **name)
427 {
428    LOGFN(__FILE__, __LINE__, __FUNCTION__);
429    if (name)
430      *name = _ecore_x_window_prop_string_utf8_get(
431          win,
432          ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
433
434    return 1;
435 }
436
437 EAPI void
438 ecore_x_netwm_icon_name_set(Ecore_X_Window win,
439                             const char *name)
440 {
441    LOGFN(__FILE__, __LINE__, __FUNCTION__);
442    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME,
443                                         name);
444 }
445
446 EAPI int
447 ecore_x_netwm_icon_name_get(Ecore_X_Window win,
448                             char **name)
449 {
450    LOGFN(__FILE__, __LINE__, __FUNCTION__);
451    if (name)
452      *name = _ecore_x_window_prop_string_utf8_get(
453          win,
454          ECORE_X_ATOM_NET_WM_ICON_NAME);
455
456    return 1;
457 }
458
459 EAPI void
460 ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win,
461                                     const char *name)
462 {
463    LOGFN(__FILE__, __LINE__, __FUNCTION__);
464    _ecore_x_window_prop_string_utf8_set(win,
465                                         ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME,
466                                         name);
467 }
468
469 EAPI int
470 ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win,
471                                     char **name)
472 {
473    LOGFN(__FILE__, __LINE__, __FUNCTION__);
474    if (name)
475      *name = _ecore_x_window_prop_string_utf8_get(
476          win,
477          ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
478
479    return 1;
480 }
481
482 EAPI void
483 ecore_x_netwm_desktop_set(Ecore_X_Window win,
484                           unsigned int desk)
485 {
486    LOGFN(__FILE__, __LINE__, __FUNCTION__);
487    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1);
488 }
489
490 EAPI Eina_Bool
491 ecore_x_netwm_desktop_get(Ecore_X_Window win,
492                           unsigned int *desk)
493 {
494    int ret;
495    unsigned int tmp;
496
497    LOGFN(__FILE__, __LINE__, __FUNCTION__);
498    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP,
499                                         &tmp, 1);
500
501    if (desk)
502      *desk = tmp;
503
504    return ret == 1 ? EINA_TRUE : EINA_FALSE;
505 }
506
507 /*
508  * _NET_WM_STRUT is deprecated
509  */
510 EAPI void
511 ecore_x_netwm_strut_set(Ecore_X_Window win,
512                         int left,
513                         int right,
514                         int top,
515                         int bottom)
516 {
517    unsigned int strut[4];
518
519    LOGFN(__FILE__, __LINE__, __FUNCTION__);
520    strut[0] = left;
521    strut[1] = right;
522    strut[2] = top;
523    strut[3] = bottom;
524    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
525 }
526
527 /*
528  * _NET_WM_STRUT is deprecated
529  */
530 EAPI Eina_Bool
531 ecore_x_netwm_strut_get(Ecore_X_Window win,
532                         int *left,
533                         int *right,
534                         int *top,
535                         int *bottom)
536 {
537    int ret = 0;
538    unsigned int strut[4];
539
540    LOGFN(__FILE__, __LINE__, __FUNCTION__);
541    ret = ecore_x_window_prop_card32_get(win,
542                                         ECORE_X_ATOM_NET_WM_STRUT,
543                                         strut,
544                                         4);
545    if (ret != 4)
546      return EINA_FALSE;
547
548    if (left)
549      *left = strut[0];
550
551    if (right)
552      *right = strut[1];
553
554    if (top)
555      *top = strut[2];
556
557    if (bottom)
558      *bottom = strut[3];
559
560    return EINA_TRUE;
561 }
562
563 EAPI void
564 ecore_x_netwm_strut_partial_set(Ecore_X_Window win,
565                                 int left,
566                                 int right,
567                                 int top,
568                                 int bottom,
569                                 int left_start_y,
570                                 int left_end_y,
571                                 int right_start_y,
572                                 int right_end_y,
573                                 int top_start_x,
574                                 int top_end_x,
575                                 int bottom_start_x,
576                                 int bottom_end_x)
577 {
578    unsigned int strut[12];
579
580    LOGFN(__FILE__, __LINE__, __FUNCTION__);
581    strut[0] = left;
582    strut[1] = right;
583    strut[2] = top;
584    strut[3] = bottom;
585    strut[4] = left_start_y;
586    strut[5] = left_end_y;
587    strut[6] = right_start_y;
588    strut[7] = right_end_y;
589    strut[8] = top_start_x;
590    strut[9] = top_end_x;
591    strut[10] = bottom_start_x;
592    strut[11] = bottom_end_x;
593    ecore_x_window_prop_card32_set(win,
594                                   ECORE_X_ATOM_NET_WM_STRUT_PARTIAL,
595                                   strut,
596                                   12);
597 }
598
599 EAPI Eina_Bool
600 ecore_x_netwm_strut_partial_get(Ecore_X_Window win,
601                                 int *left,
602                                 int *right,
603                                 int *top,
604                                 int *bottom,
605                                 int *left_start_y,
606                                 int *left_end_y,
607                                 int *right_start_y,
608                                 int *right_end_y,
609                                 int *top_start_x,
610                                 int *top_end_x,
611                                 int *bottom_start_x,
612                                 int *bottom_end_x)
613 {
614    int ret = 0;
615    unsigned int strut[12];
616
617    LOGFN(__FILE__, __LINE__, __FUNCTION__);
618    ret = ecore_x_window_prop_card32_get(win,
619                                         ECORE_X_ATOM_NET_WM_STRUT_PARTIAL,
620                                         strut,
621                                         12);
622    if (ret != 12)
623      return EINA_FALSE;
624
625    if (left)
626      *left = strut[0];
627
628    if (right)
629      *right = strut[1];
630
631    if (top)
632      *top = strut[2];
633
634    if (bottom)
635      *bottom = strut[3];
636
637    if (left_start_y)
638      *left_start_y = strut[4];
639
640    if (left_end_y)
641      *left_end_y = strut[5];
642
643    if (right_start_y)
644      *right_start_y = strut[6];
645
646    if (right_end_y)
647      *right_end_y = strut[7];
648
649    if (top_start_x)
650      *top_start_x = strut[8];
651
652    if (top_end_x)
653      *top_end_x = strut[9];
654
655    if (bottom_start_x)
656      *bottom_start_x = strut[10];
657
658    if (bottom_end_x)
659      *bottom_end_x = strut[11];
660
661    return EINA_TRUE;
662 }
663
664 EAPI void
665 ecore_x_netwm_icons_set(Ecore_X_Window win,
666                         Ecore_X_Icon *icon,
667                         int num)
668 {
669    unsigned int *data, *p, *p2;
670    unsigned int i, size, x, y;
671    
672    LOGFN(__FILE__, __LINE__, __FUNCTION__);
673    size = 0;
674    for (i = 0; i < (unsigned int)num; i++)
675      {
676         size += 2 + (icon[i].width * icon[i].height);
677      }
678    data = malloc(size * sizeof(unsigned int));
679    if (!data) return;
680    p = data;
681    for (i = 0; i < (unsigned int)num; i++)
682      {
683         p[0] = icon[i].width;
684         p[1] = icon[i].height;
685         p += 2;
686         p2 = icon[i].data;
687         for (y = 0; y < icon[i].height; y++)
688           {
689              for (x = 0; x < icon[i].width; x++)
690                {
691                   unsigned int r, g, b, a;
692                   
693                   a = (*p2 >> 24) & 0xff;
694                   r = (*p2 >> 16) & 0xff;
695                   g = (*p2 >> 8 ) & 0xff;
696                   b = (*p2      ) & 0xff;
697                   if ((a > 0) && (a < 255))
698                     {
699                        // unpremul
700                        r = (r * 255) / a;
701                        g = (g * 255) / a;
702                        b = (b * 255) / a;
703                     }
704                   *p = (a << 24) | (r << 16) | (g << 8) | b;
705                   p++;
706                   p2++;
707                }
708           }
709      }
710    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_ICON,
711                                   data, size);
712    free(data);
713 }
714
715 EAPI Eina_Bool
716 ecore_x_netwm_icons_get(Ecore_X_Window win,
717                         Ecore_X_Icon **icon,
718                         int *num)
719 {
720    unsigned int *data, *p;
721    unsigned int *src;
722    unsigned int len, icons, i;
723    int num_ret;
724
725    LOGFN(__FILE__, __LINE__, __FUNCTION__);
726    if (num)
727      *num = 0;
728
729    if (icon)
730      *icon = NULL;
731
732    num_ret = ecore_x_window_prop_card32_list_get(win, ECORE_X_ATOM_NET_WM_ICON,
733                                                  &data);
734    if (num_ret <= 0)
735      return EINA_FALSE;
736
737    if (!data)
738      return EINA_FALSE;
739
740    if (num_ret < 2)
741      {
742         free(data);
743         return EINA_FALSE;
744      }
745
746    /* Check how many icons there are */
747    icons = 0;
748    p = data;
749    while (p)
750      {
751         len = p[0] * p[1];
752         p += (len + 2);
753         if ((p - data) > num_ret)
754           {
755              free(data);
756              return EINA_FALSE;
757           }
758
759         icons++;
760
761         if ((p - data) == num_ret)
762           p = NULL;
763      }
764    if (num)
765      *num = icons;
766
767    /* If the user doesn't want the icons, return */
768    if (!icon)
769      {
770         free(data);
771         return EINA_TRUE;
772      }
773
774    /* Allocate memory */
775    *icon = malloc(icons * sizeof(Ecore_X_Icon));
776    if (!(*icon))
777      {
778         free(data);
779         return EINA_FALSE;
780      }
781
782    /* Fetch the icons */
783    p = data;
784    for (i = 0; i < icons; i++)
785      {
786         unsigned int *ps, *pd, *pe;
787
788         len = p[0] * p[1];
789         ((*icon)[i]).width = p[0];
790         ((*icon)[i]).height = p[1];
791         src = &(p[2]);
792         ((*icon)[i]).data = malloc(len * sizeof(unsigned int));
793         if (!((*icon)[i]).data)
794           {
795              while (i)
796                free(((*icon)[--i]).data);
797              free(*icon);
798              free(data);
799              return EINA_FALSE;
800           }
801
802         pd = ((*icon)[i]).data;
803         ps = src;
804         pe = ps + len;
805         for (; ps < pe; ps++)
806           {
807              unsigned int r, g, b, a;
808
809              a = (*ps >> 24) & 0xff;
810              r = (((*ps >> 16) & 0xff) * a) / 255;
811              g = (((*ps >> 8) & 0xff) * a) / 255;
812              b = (((*ps) & 0xff) * a) / 255;
813              *pd = (a << 24) | (r << 16) | (g << 8) | (b);
814              pd++;
815           }
816         p += (len + 2);
817      }
818
819    free(data);
820
821    return EINA_TRUE;
822 }
823
824 EAPI void
825 ecore_x_netwm_icon_geometry_set(Ecore_X_Window win,
826                                 int x,
827                                 int y,
828                                 int width,
829                                 int height)
830 {
831    unsigned int geometry[4];
832
833    LOGFN(__FILE__, __LINE__, __FUNCTION__);
834    geometry[0] = x;
835    geometry[1] = y;
836    geometry[2] = width;
837    geometry[3] = height;
838    ecore_x_window_prop_card32_set(win,
839                                   ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
840                                   geometry,
841                                   4);
842 }
843
844 EAPI Eina_Bool
845 ecore_x_netwm_icon_geometry_get(Ecore_X_Window win,
846                                 int *x,
847                                 int *y,
848                                 int *width,
849                                 int *height)
850 {
851    int ret;
852    unsigned int geometry[4];
853
854    LOGFN(__FILE__, __LINE__, __FUNCTION__);
855    ret = ecore_x_window_prop_card32_get(win,
856                                         ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
857                                         geometry,
858                                         4);
859    if (ret != 4)
860      return EINA_FALSE;
861
862    if (x)
863      *x = geometry[0];
864
865    if (y)
866      *y = geometry[1];
867
868    if (width)
869      *width = geometry[2];
870
871    if (height)
872      *height = geometry[3];
873
874    return EINA_TRUE;
875 }
876
877 EAPI void
878 ecore_x_netwm_pid_set(Ecore_X_Window win,
879                       int pid)
880 {
881    unsigned int tmp;
882
883    LOGFN(__FILE__, __LINE__, __FUNCTION__);
884    tmp = pid;
885    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_PID,
886                                   &tmp, 1);
887 }
888
889 EAPI Eina_Bool
890 ecore_x_netwm_pid_get(Ecore_X_Window win,
891                       int *pid)
892 {
893    int ret;
894    unsigned int tmp;
895
896    LOGFN(__FILE__, __LINE__, __FUNCTION__);
897    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_PID,
898                                         &tmp, 1);
899    if (pid)
900      *pid = tmp;
901
902    return ret == 1 ? EINA_TRUE : EINA_FALSE;
903 }
904
905 EAPI void
906 ecore_x_netwm_handled_icons_set(Ecore_X_Window win)
907 {
908    LOGFN(__FILE__, __LINE__, __FUNCTION__);
909    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
910                                   NULL, 0);
911 }
912
913 EAPI Eina_Bool
914 ecore_x_netwm_handled_icons_get(Ecore_X_Window win)
915 {
916    int ret = 0;
917    LOGFN(__FILE__, __LINE__, __FUNCTION__);
918    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
919                                         NULL, 0);
920    return ret == 0 ? EINA_TRUE : EINA_FALSE;
921 }
922
923 EAPI void
924 ecore_x_netwm_user_time_set(Ecore_X_Window win,
925                             unsigned int tim)
926 {
927    LOGFN(__FILE__, __LINE__, __FUNCTION__);
928    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_USER_TIME,
929                                   &tim, 1);
930 }
931
932 EAPI Eina_Bool
933 ecore_x_netwm_user_time_get(Ecore_X_Window win,
934                             unsigned int *tim)
935 {
936    int ret;
937    unsigned int tmp;
938
939    LOGFN(__FILE__, __LINE__, __FUNCTION__);
940    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME,
941                                         &tmp, 1);
942    if (tim)
943      *tim = tmp;
944
945    return ret == 1 ? EINA_TRUE : EINA_FALSE;
946 }
947
948 Ecore_X_Window_State
949 _ecore_x_netwm_state_get(Ecore_X_Atom a)
950 {
951    if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL)
952      return ECORE_X_WINDOW_STATE_MODAL;
953    else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY)
954      return ECORE_X_WINDOW_STATE_STICKY;
955    else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT)
956      return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
957    else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ)
958      return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
959    else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED)
960      return ECORE_X_WINDOW_STATE_SHADED;
961    else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR)
962      return ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
963    else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER)
964      return ECORE_X_WINDOW_STATE_SKIP_PAGER;
965    else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN)
966      return ECORE_X_WINDOW_STATE_HIDDEN;
967    else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN)
968      return ECORE_X_WINDOW_STATE_FULLSCREEN;
969    else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE)
970      return ECORE_X_WINDOW_STATE_ABOVE;
971    else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW)
972      return ECORE_X_WINDOW_STATE_BELOW;
973    else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION)
974      return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION;
975    else
976      return ECORE_X_WINDOW_STATE_UNKNOWN;
977 }
978
979 static Ecore_X_Atom
980 _ecore_x_netwm_state_atom_get(Ecore_X_Window_State s)
981 {
982    switch (s)
983      {
984       case ECORE_X_WINDOW_STATE_MODAL:
985         return ECORE_X_ATOM_NET_WM_STATE_MODAL;
986
987       case ECORE_X_WINDOW_STATE_STICKY:
988         return ECORE_X_ATOM_NET_WM_STATE_STICKY;
989
990       case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
991         return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
992
993       case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
994         return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
995
996       case ECORE_X_WINDOW_STATE_SHADED:
997         return ECORE_X_ATOM_NET_WM_STATE_SHADED;
998
999       case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
1000         return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
1001
1002       case ECORE_X_WINDOW_STATE_SKIP_PAGER:
1003         return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
1004
1005       case ECORE_X_WINDOW_STATE_HIDDEN:
1006         return ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
1007
1008       case ECORE_X_WINDOW_STATE_FULLSCREEN:
1009         return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
1010
1011       case ECORE_X_WINDOW_STATE_ABOVE:
1012         return ECORE_X_ATOM_NET_WM_STATE_ABOVE;
1013
1014       case ECORE_X_WINDOW_STATE_BELOW:
1015         return ECORE_X_ATOM_NET_WM_STATE_BELOW;
1016
1017       case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
1018         return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION;
1019
1020       default:
1021         return 0;
1022      }
1023 }
1024
1025 EAPI void
1026 ecore_x_netwm_window_state_set(Ecore_X_Window win,
1027                                Ecore_X_Window_State *state,
1028                                unsigned int num)
1029 {
1030    Ecore_X_Atom *set;
1031    unsigned int i;
1032
1033    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1034    if (!num)
1035      {
1036         ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_STATE);
1037         return;
1038      }
1039
1040    set = malloc(num * sizeof(Ecore_X_Atom));
1041    if (!set)
1042      return;
1043
1044    for (i = 0; i < num; i++)
1045      set[i] = _ecore_x_netwm_state_atom_get(state[i]);
1046
1047    ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_STATE, set, num);
1048
1049    free(set);
1050 }
1051
1052 EAPI Eina_Bool
1053 ecore_x_netwm_window_state_get(Ecore_X_Window win,
1054                                Ecore_X_Window_State **state,
1055                                unsigned int *num)
1056 {
1057    int num_ret, i;
1058    Ecore_X_Atom *atoms;
1059
1060    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1061    if (num)
1062      *num = 0;
1063
1064    if (state)
1065      *state = NULL;
1066
1067    num_ret = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_STATE,
1068                                                &atoms);
1069    if (num_ret <= 0)
1070      return EINA_FALSE;
1071
1072    if (state)
1073      {
1074         *state = malloc(num_ret * sizeof(Ecore_X_Window_State));
1075         if (*state)
1076           for (i = 0; i < num_ret; ++i)
1077             (*state)[i] = _ecore_x_netwm_state_get(atoms[i]);
1078
1079         if (num)
1080           *num = num_ret;
1081      }
1082
1083    free(atoms);
1084    return EINA_TRUE;
1085 }
1086
1087 static Ecore_X_Window_Type
1088 _ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom)
1089 {
1090    if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP)
1091      return ECORE_X_WINDOW_TYPE_DESKTOP;
1092    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK)
1093      return ECORE_X_WINDOW_TYPE_DOCK;
1094    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR)
1095      return ECORE_X_WINDOW_TYPE_TOOLBAR;
1096    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU)
1097      return ECORE_X_WINDOW_TYPE_MENU;
1098    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY)
1099      return ECORE_X_WINDOW_TYPE_UTILITY;
1100    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH)
1101      return ECORE_X_WINDOW_TYPE_SPLASH;
1102    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG)
1103      return ECORE_X_WINDOW_TYPE_DIALOG;
1104    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL)
1105      return ECORE_X_WINDOW_TYPE_NORMAL;
1106    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
1107      return ECORE_X_WINDOW_TYPE_DROPDOWN_MENU;
1108    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU)
1109      return ECORE_X_WINDOW_TYPE_POPUP_MENU;
1110    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP)
1111      return ECORE_X_WINDOW_TYPE_TOOLTIP;
1112    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION)
1113      return ECORE_X_WINDOW_TYPE_NOTIFICATION;
1114    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO)
1115      return ECORE_X_WINDOW_TYPE_COMBO;
1116    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND)
1117      return ECORE_X_WINDOW_TYPE_DND;
1118    else
1119      return ECORE_X_WINDOW_TYPE_UNKNOWN;
1120 }
1121
1122 static Ecore_X_Atom
1123 _ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type)
1124 {
1125    switch (type)
1126      {
1127       case ECORE_X_WINDOW_TYPE_DESKTOP:
1128         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
1129
1130       case ECORE_X_WINDOW_TYPE_DOCK:
1131         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
1132
1133       case ECORE_X_WINDOW_TYPE_TOOLBAR:
1134         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
1135
1136       case ECORE_X_WINDOW_TYPE_MENU:
1137         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
1138
1139       case ECORE_X_WINDOW_TYPE_UTILITY:
1140         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
1141
1142       case ECORE_X_WINDOW_TYPE_SPLASH:
1143         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
1144
1145       case ECORE_X_WINDOW_TYPE_DIALOG:
1146         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
1147
1148       case ECORE_X_WINDOW_TYPE_NORMAL:
1149         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
1150
1151       case ECORE_X_WINDOW_TYPE_DROPDOWN_MENU:
1152         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
1153
1154       case ECORE_X_WINDOW_TYPE_POPUP_MENU:
1155         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU;
1156
1157       case ECORE_X_WINDOW_TYPE_TOOLTIP:
1158         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP;
1159
1160       case ECORE_X_WINDOW_TYPE_NOTIFICATION:
1161         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION;
1162
1163       case ECORE_X_WINDOW_TYPE_COMBO:
1164         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO;
1165
1166       case ECORE_X_WINDOW_TYPE_DND:
1167         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND;
1168
1169       default:
1170         return 0;
1171      }
1172 }
1173
1174 /*
1175  * FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR
1176  * , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG
1177  */
1178 EAPI void
1179 ecore_x_netwm_window_type_set(Ecore_X_Window win,
1180                               Ecore_X_Window_Type type)
1181 {
1182    Ecore_X_Atom atom;
1183
1184    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1185    atom = _ecore_x_netwm_window_type_atom_get(type);
1186    ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1187                                 &atom, 1);
1188 }
1189
1190 /* FIXME: Maybe return 0 on some conditions? */
1191 EAPI Eina_Bool
1192 ecore_x_netwm_window_type_get(Ecore_X_Window win,
1193                               Ecore_X_Window_Type *type)
1194 {
1195    int num;
1196    Ecore_X_Atom *atoms = NULL;
1197
1198    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1199    if (type)
1200      *type = ECORE_X_WINDOW_TYPE_NORMAL;
1201
1202    num = ecore_x_window_prop_atom_list_get(win,
1203                                            ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1204                                            &atoms);
1205    if ((type) && (num >= 1) && (atoms))
1206      *type = _ecore_x_netwm_window_type_type_get(atoms[0]);
1207
1208    free(atoms);
1209    if (num >= 1)
1210      return EINA_TRUE;
1211
1212    return EINA_FALSE;
1213 }
1214
1215 EAPI int
1216 ecore_x_netwm_window_types_get(Ecore_X_Window win,
1217                                Ecore_X_Window_Type **types)
1218 {
1219    int num, i;
1220    Ecore_X_Atom *atoms = NULL;
1221    Ecore_X_Window_Type *atoms2 = NULL;
1222
1223    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1224    if (types)
1225      *types = NULL;
1226
1227    num = ecore_x_window_prop_atom_list_get(win,
1228                                            ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1229                                            &atoms);
1230    if ((num <= 0) || (!atoms))
1231      {
1232         if (atoms)
1233           free(atoms);
1234
1235         return 0;
1236      }
1237
1238    atoms2 = malloc(num * sizeof(Ecore_X_Window_Type));
1239    if (!atoms2)
1240      return 0;
1241
1242    for (i = 0; i < num; i++)
1243      atoms2[i] = _ecore_x_netwm_window_type_type_get(atoms[i]);
1244    free(atoms);
1245    if (types)
1246      *types = atoms2;
1247    else
1248      free(atoms2);
1249
1250    return num;
1251 }
1252
1253 static Ecore_X_Atom
1254 _ecore_x_netwm_action_atom_get(Ecore_X_Action action)
1255 {
1256    switch (action)
1257      {
1258       case ECORE_X_ACTION_MOVE:
1259         return ECORE_X_ATOM_NET_WM_ACTION_MOVE;
1260
1261       case ECORE_X_ACTION_RESIZE:
1262         return ECORE_X_ATOM_NET_WM_ACTION_RESIZE;
1263
1264       case ECORE_X_ACTION_MINIMIZE:
1265         return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE;
1266
1267       case ECORE_X_ACTION_SHADE:
1268         return ECORE_X_ATOM_NET_WM_ACTION_SHADE;
1269
1270       case ECORE_X_ACTION_STICK:
1271         return ECORE_X_ATOM_NET_WM_ACTION_STICK;
1272
1273       case ECORE_X_ACTION_MAXIMIZE_HORZ:
1274         return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ;
1275
1276       case ECORE_X_ACTION_MAXIMIZE_VERT:
1277         return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT;
1278
1279       case ECORE_X_ACTION_FULLSCREEN:
1280         return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN;
1281
1282       case ECORE_X_ACTION_CHANGE_DESKTOP:
1283         return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP;
1284
1285       case ECORE_X_ACTION_CLOSE:
1286         return ECORE_X_ATOM_NET_WM_ACTION_CLOSE;
1287
1288       case ECORE_X_ACTION_ABOVE:
1289         return ECORE_X_ATOM_NET_WM_ACTION_ABOVE;
1290
1291       case ECORE_X_ACTION_BELOW:
1292         return ECORE_X_ATOM_NET_WM_ACTION_BELOW;
1293
1294       default:
1295         return 0;
1296      }
1297 }
1298
1299 /* FIXME: Get complete list */
1300 EAPI Eina_Bool
1301 ecore_x_netwm_allowed_action_isset(Ecore_X_Window win,
1302                                    Ecore_X_Action action)
1303 {
1304    int num, i;
1305    Ecore_X_Atom *atoms, atom;
1306    Eina_Bool ret = EINA_FALSE;
1307
1308    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1309    num = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1310                                            &atoms);
1311    if (num <= 0)
1312      return ret;
1313
1314    atom = _ecore_x_netwm_action_atom_get(action);
1315
1316    for (i = 0; i < num; ++i)
1317      {
1318         if (atom == atoms[i])
1319           {
1320              ret = 1;
1321              break;
1322           }
1323      }
1324
1325    free(atoms);
1326    return ret;
1327 }
1328
1329 /* FIXME: Set complete list */
1330 EAPI void
1331 ecore_x_netwm_allowed_action_set(Ecore_X_Window win,
1332                                  Ecore_X_Action *action,
1333                                  unsigned int num)
1334 {
1335    Ecore_X_Atom *set;
1336    unsigned int i;
1337
1338    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1339    if (!num)
1340      {
1341         ecore_x_window_prop_property_del(win,
1342                                          ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS);
1343         return;
1344      }
1345
1346    set = malloc(num * sizeof(Ecore_X_Atom));
1347    if (!set)
1348      return;
1349
1350    for (i = 0; i < num; i++)
1351      set[i] = _ecore_x_netwm_action_atom_get(action[i]);
1352
1353    ecore_x_window_prop_atom_set(win,
1354                                 ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
1355                                 set,
1356                                 num);
1357
1358    free(set);
1359 }
1360
1361 EAPI Eina_Bool
1362 ecore_x_netwm_allowed_action_get(Ecore_X_Window win,
1363                                  Ecore_X_Action **action,
1364                                  unsigned int *num)
1365 {
1366    int num_ret, i;
1367    Ecore_X_Atom *atoms;
1368
1369    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1370    if (num)
1371      *num = 0;
1372
1373    if (action)
1374      *action = NULL;
1375
1376    num_ret = ecore_x_window_prop_atom_list_get(
1377        win,
1378        ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
1379        &atoms);
1380    if (num_ret <= 0)
1381      return EINA_FALSE;
1382
1383    if (action)
1384      {
1385         *action = malloc(num_ret * sizeof(Ecore_X_Action));
1386         if (*action)
1387           for (i = 0; i < num_ret; ++i)
1388             (*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]);
1389
1390         if (num)
1391           *num = num_ret;
1392      }
1393
1394    free(atoms);
1395    return EINA_TRUE;
1396 }
1397
1398 EAPI void
1399 ecore_x_netwm_opacity_set(Ecore_X_Window win,
1400                           unsigned int opacity)
1401 {
1402    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1403    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
1404                                   &opacity, 1);
1405 }
1406
1407 EAPI Eina_Bool
1408 ecore_x_netwm_opacity_get(Ecore_X_Window win,
1409                           unsigned int *opacity)
1410 {
1411    int ret;
1412    unsigned int tmp;
1413
1414    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1415    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
1416                                         &tmp, 1);
1417    if (opacity)
1418      *opacity = tmp;
1419
1420    return ret == 1 ? EINA_TRUE : EINA_FALSE;
1421 }
1422
1423 EAPI void
1424 ecore_x_netwm_frame_size_set(Ecore_X_Window win,
1425                              int fl,
1426                              int fr,
1427                              int ft,
1428                              int fb)
1429 {
1430    unsigned int frames[4];
1431
1432    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1433    frames[0] = fl;
1434    frames[1] = fr;
1435    frames[2] = ft;
1436    frames[3] = fb;
1437    ecore_x_window_prop_card32_set(win,
1438                                   ECORE_X_ATOM_NET_FRAME_EXTENTS,
1439                                   frames,
1440                                   4);
1441 }
1442
1443 EAPI Eina_Bool
1444 ecore_x_netwm_frame_size_get(Ecore_X_Window win,
1445                              int *fl,
1446                              int *fr,
1447                              int *ft,
1448                              int *fb)
1449 {
1450    int ret = 0;
1451    unsigned int frames[4];
1452
1453    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1454    ret = ecore_x_window_prop_card32_get(win,
1455                                         ECORE_X_ATOM_NET_FRAME_EXTENTS,
1456                                         frames,
1457                                         4);
1458    if (ret != 4)
1459      return EINA_FALSE;
1460
1461    if (fl)
1462      *fl = frames[0];
1463
1464    if (fr)
1465      *fr = frames[1];
1466
1467    if (ft)
1468      *ft = frames[2];
1469
1470    if (fb)
1471      *fb = frames[3];
1472
1473    return EINA_TRUE;
1474 }
1475
1476 EAPI Eina_Bool
1477 ecore_x_netwm_sync_counter_get(Ecore_X_Window win,
1478                                Ecore_X_Sync_Counter *counter)
1479 {
1480    int ret;
1481    unsigned int tmp;
1482
1483    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1484    ret = ecore_x_window_prop_card32_get(
1485        win,
1486        ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER,
1487        &tmp,
1488        1);
1489
1490    if (counter)
1491      *counter = tmp;
1492
1493    return ret == 1 ? EINA_TRUE : EINA_FALSE;
1494 }
1495
1496 EAPI void
1497 ecore_x_netwm_ping_send(Ecore_X_Window win)
1498 {
1499    XEvent xev;
1500
1501    if (!win)
1502      return;
1503
1504    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1505    xev.xclient.type = ClientMessage;
1506    xev.xclient.display = _ecore_x_disp;
1507    xev.xclient.window = win;
1508    xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
1509    xev.xclient.format = 32;
1510    xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_PING;
1511    xev.xclient.data.l[1] = _ecore_x_event_last_time;
1512    xev.xclient.data.l[2] = win;
1513    xev.xclient.data.l[3] = 0;
1514    xev.xclient.data.l[4] = 0;
1515
1516    XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
1517 }
1518
1519 EAPI void
1520 ecore_x_netwm_sync_request_send(Ecore_X_Window win,
1521                                 unsigned int serial)
1522 {
1523    XSyncValue value;
1524    XEvent xev;
1525
1526    if (!win)
1527      return;
1528
1529    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1530    XSyncIntToValue(&value, (int)serial);
1531
1532    xev.xclient.type = ClientMessage;
1533    xev.xclient.display = _ecore_x_disp;
1534    xev.xclient.window = win;
1535    xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
1536    xev.xclient.format = 32;
1537    xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
1538    xev.xclient.data.l[1] = _ecore_x_event_last_time;
1539    xev.xclient.data.l[2] = XSyncValueLow32(value);
1540    xev.xclient.data.l[3] = XSyncValueHigh32(value);
1541    xev.xclient.data.l[4] = 0;
1542
1543    XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
1544 }
1545
1546 EAPI void
1547 ecore_x_netwm_state_request_send(Ecore_X_Window win,
1548                                  Ecore_X_Window root,
1549                                  Ecore_X_Window_State s1,
1550                                  Ecore_X_Window_State s2,
1551                                  Eina_Bool set)
1552 {
1553    XEvent xev;
1554
1555    if (!win)
1556      return;
1557
1558    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1559    if (!root)
1560      root = DefaultRootWindow(_ecore_x_disp);
1561
1562    xev.xclient.type = ClientMessage;
1563    xev.xclient.serial = 0;
1564    xev.xclient.send_event = True;
1565    xev.xclient.display = _ecore_x_disp;
1566    xev.xclient.window = win;
1567    xev.xclient.format = 32;
1568    xev.xclient.message_type = ECORE_X_ATOM_NET_WM_STATE;
1569    xev.xclient.data.l[0] = !!set;
1570    xev.xclient.data.l[1] = _ecore_x_netwm_state_atom_get(s1);
1571    xev.xclient.data.l[2] = _ecore_x_netwm_state_atom_get(s2);
1572    /* 1 == normal client, if someone wants to use this
1573     * function in a pager, this should be 2 */
1574    xev.xclient.data.l[3] = 1;
1575    xev.xclient.data.l[4] = 0;
1576
1577    XSendEvent(_ecore_x_disp, root, False,
1578               SubstructureNotifyMask | SubstructureRedirectMask, &xev);
1579 }
1580
1581 EAPI void
1582 ecore_x_netwm_desktop_request_send(Ecore_X_Window win,
1583                                    Ecore_X_Window root,
1584                                    unsigned int desktop)
1585 {
1586    XEvent xev;
1587
1588    if (!win)
1589      return;
1590
1591    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1592    if (!root)
1593      root = DefaultRootWindow(_ecore_x_disp);
1594
1595    xev.xclient.type = ClientMessage;
1596    xev.xclient.serial = 0;
1597    xev.xclient.send_event = True;
1598    xev.xclient.display = _ecore_x_disp;
1599    xev.xclient.window = win;
1600    xev.xclient.format = 32;
1601    xev.xclient.message_type = ECORE_X_ATOM_NET_WM_DESKTOP;
1602    xev.xclient.data.l[0] = desktop;
1603
1604    XSendEvent(_ecore_x_disp, root, False,
1605               SubstructureNotifyMask | SubstructureRedirectMask, &xev);
1606 }
1607
1608 EAPI void
1609 ecore_x_netwm_moveresize_request_send(Ecore_X_Window win,
1610                                       int x,
1611                                       int y,
1612                                       Ecore_X_Netwm_Direction direction,
1613                                       unsigned int button)
1614 {
1615    XEvent xev;
1616
1617    if (!win)
1618      return;
1619
1620    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1621    xev.xclient.window = win;
1622    xev.xclient.type = ClientMessage;
1623    xev.xclient.message_type = ECORE_X_ATOM_NET_WM_MOVERESIZE;
1624    xev.xclient.format = 32;
1625    xev.xclient.data.l[0] = x;
1626    xev.xclient.data.l[1] = y;
1627    xev.xclient.data.l[2] = direction;
1628    xev.xclient.data.l[3] = button;
1629    xev.xclient.data.l[4] = 1;
1630
1631    XSendEvent(_ecore_x_disp, win, False,
1632               SubstructureNotifyMask | SubstructureRedirectMask, &xev);
1633 }
1634
1635 int
1636 _ecore_x_netwm_startup_info_begin(Ecore_X_Window win __UNUSED__,
1637                                   char *data __UNUSED__)
1638 {
1639 #if 0
1640    Ecore_X_Startup_Info *info;
1641    unsigned char *exists = 0;
1642
1643    if (!startup_info)
1644      return 0;
1645
1646    info = eina_hash_find(startup_info, (void *)win);
1647    if (info)
1648      {
1649         exists = 1;
1650         WRN("Already got info for win: 0x%x", win);
1651         _ecore_x_netwm_startup_info_free(info);
1652      }
1653
1654    info = calloc(1, sizeof(Ecore_X_Startup_Info));
1655    if (!info)
1656      return 0;
1657
1658    info->win = win;
1659    info->length = 0;
1660    info->buffer_size = 161;
1661    info->buffer = calloc(info->buffer_size, sizeof(char));
1662    if (!info->buffer)
1663      {
1664         _ecore_x_netwm_startup_info_free(info);
1665         return 0;
1666      }
1667
1668    memcpy(info->buffer, data, 20);
1669    info->length += 20;
1670    info->buffer[info->length] = 0;
1671    if (exists)
1672      eina_hash_modify(startup_info, (void *)info->win, info);
1673    else
1674      eina_hash_add(startup_info, (void *)info->win, info);
1675
1676    if (strlen(info->buffer) != 20)
1677      /* We have a '\0' in there, the message is done */
1678      _ecore_x_netwm_startup_info_process(info);
1679
1680 #endif /* if 0 */
1681    return 1;
1682 }
1683
1684 int
1685 _ecore_x_netwm_startup_info(Ecore_X_Window win __UNUSED__,
1686                             char *data __UNUSED__)
1687 {
1688 #if 0
1689    Ecore_X_Startup_Info *info;
1690    char *p;
1691
1692    if (!startup_info)
1693      return 0;
1694
1695    info = eina_hash_find(startup_info, (void *)win);
1696    if (!info)
1697      return 0;
1698
1699    if ((info->length + 20) > info->buffer_size)
1700      {
1701         info->buffer_size += 160;
1702         info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char));
1703         if (!info->buffer)
1704           {
1705              eina_hash_del(startup_info, (void *)info->win);
1706              _ecore_x_netwm_startup_info_free(info);
1707              return 0;
1708           }
1709      }
1710
1711    memcpy(info->buffer + info->length, data, 20);
1712    p = info->buffer + info->length;
1713    info->length += 20;
1714    info->buffer[info->length] = 0;
1715    if (strlen(p) != 20)
1716      /* We have a '\0' in there, the message is done */
1717      _ecore_x_netwm_startup_info_process(info);
1718
1719 #endif /* if 0 */
1720    return 1;
1721 }
1722
1723 /*
1724  * Set UTF-8 string property
1725  */
1726 static void
1727 _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win,
1728                                      Ecore_X_Atom atom,
1729                                      const char *str)
1730 {
1731    XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8,
1732                    PropModeReplace, (unsigned char *)str, strlen(str));
1733 }
1734
1735 /*
1736  * Get UTF-8 string property
1737  */
1738 static char *
1739 _ecore_x_window_prop_string_utf8_get(Ecore_X_Window win,
1740                                      Ecore_X_Atom atom)
1741 {
1742    char *str;
1743    unsigned char *prop_ret;
1744    Atom type_ret;
1745    unsigned long bytes_after, num_ret;
1746    int format_ret;
1747
1748    str = NULL;
1749    prop_ret = NULL;
1750    XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
1751                       ECORE_X_ATOM_UTF8_STRING, &type_ret,
1752                       &format_ret, &num_ret, &bytes_after, &prop_ret);
1753    if (prop_ret && num_ret > 0 && format_ret == 8)
1754      {
1755         str = malloc(num_ret + 1);
1756         if (str)
1757           {
1758              memcpy(str, prop_ret, num_ret);
1759              str[num_ret] = '\0';
1760           }
1761      }
1762
1763    if (prop_ret)
1764      XFree(prop_ret);
1765
1766    return str;
1767 }
1768
1769 #if 0 /* Unused */
1770 /*
1771  * Process startup info
1772  */
1773 static int
1774 _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info)
1775 {
1776    Ecore_X_Event_Startup_Sequence *e;
1777    int event;
1778    char *p;
1779
1780    p = strchr(info->buffer, ':');
1781    if (!p)
1782      {
1783         eina_hash_del(startup_info, (void *)info->win);
1784         _ecore_x_netwm_startup_info_free(info);
1785         return 0;
1786      }
1787
1788    *p = 0;
1789    if (!strcmp(info->buffer, "new"))
1790      {
1791         if (info->init)
1792           event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
1793         else
1794           event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW;
1795
1796         info->init = 1;
1797      }
1798    else if (!strcmp(info->buffer, "change"))
1799      event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
1800    else if (!strcmp(info->buffer, "remove"))
1801      event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE;
1802    else
1803      {
1804         eina_hash_del(startup_info, (void *)info->win);
1805         _ecore_x_netwm_startup_info_free(info);
1806         return 0;
1807      }
1808
1809    p++;
1810
1811    if (!_ecore_x_netwm_startup_info_parse(info, p))
1812      {
1813         eina_hash_del(startup_info, (void *)info->win);
1814         _ecore_x_netwm_startup_info_free(info);
1815         return 0;
1816      }
1817
1818    if (info->init)
1819      {
1820         e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence));
1821         if (!e)
1822           {
1823              eina_hash_del(startup_info, (void *)info->win);
1824              _ecore_x_netwm_startup_info_free(info);
1825              return 0;
1826           }
1827
1828         e->win = info->win;
1829         ecore_event_add(event, e, NULL, NULL);
1830      }
1831
1832    if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE)
1833      {
1834         eina_hash_del(startup_info, (void *)info->win);
1835         _ecore_x_netwm_startup_info_free(info);
1836      }
1837    else
1838      {
1839         /* Discard buffer */
1840         info->length = 0;
1841         info->buffer[0] = 0;
1842      }
1843
1844    return 1;
1845 }
1846
1847 /*
1848  * Parse startup info
1849  */
1850 static int
1851 _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
1852                                   char *data)
1853 {
1854    while (*data)
1855      {
1856         int in_quot_sing, in_quot_dbl, escaped;
1857         char *p, *pp;
1858         char *key;
1859         char value[1024];
1860
1861         /* Skip space */
1862         while (*data == ' ')
1863           data++;
1864         /* Get key */
1865         key = data;
1866         data = strchr(key, '=');
1867         if (!data)
1868           return 0;
1869
1870         *data = 0;
1871         data++;
1872
1873         /* Get value */
1874         p = data;
1875         pp = value;
1876         in_quot_dbl = 0;
1877         in_quot_sing = 0;
1878         escaped = 0;
1879         while (*p)
1880           {
1881              if ((pp - value) >= 1024)
1882                return 0;
1883
1884              if (escaped)
1885                {
1886                   *pp = *p;
1887                   pp++;
1888                   escaped = 0;
1889                }
1890              else if (in_quot_sing)
1891                {
1892                   if (*p == '\\')
1893                     escaped = 1;
1894                   else if (*p == '\'')
1895                     in_quot_sing = 0;
1896                   else
1897                     {
1898                        *pp = *p;
1899                        pp++;
1900                     }
1901                }
1902              else if (in_quot_dbl)
1903                {
1904                   if (*p == '\\')
1905                     escaped = 1;
1906                   else if (*p == '\"')
1907                     in_quot_dbl = 0;
1908                   else
1909                     {
1910                        *pp = *p;
1911                        pp++;
1912                     }
1913                }
1914              else
1915                {
1916                   if (*p == '\\')
1917                     escaped = 1;
1918                   else if (*p == '\'')
1919                     in_quot_sing = 1;
1920                   else if (*p == '\"')
1921                     in_quot_dbl = 1;
1922                   else if (*p == ' ')
1923                     break;
1924                   else
1925                     {
1926                        *pp = *p;
1927                        pp++;
1928                     }
1929                }
1930
1931              p++;
1932           }
1933         if ((in_quot_dbl) || (in_quot_sing))
1934           return 0;
1935
1936         data = p;
1937         *pp = 0;
1938
1939         /* Parse info */
1940         if (!strcmp(key, "ID"))
1941           {
1942              if ((info->id) && (strcmp(info->id, value)))
1943                return 0;
1944
1945              info->id = strdup(value);
1946              p = strstr(value, "_TIME");
1947              if (p)
1948                info->timestamp = atoi(p + 5);
1949           }
1950         else if (!strcmp(key, "NAME"))
1951           {
1952              if (info->name)
1953                free(info->name);
1954
1955              info->name = strdup(value);
1956           }
1957         else if (!strcmp(key, "SCREEN"))
1958           info->screen = atoi(value);
1959         else if (!strcmp(key, "BIN"))
1960           {
1961              if (info->bin)
1962                free(info->bin);
1963
1964              info->bin = strdup(value);
1965           }
1966         else if (!strcmp(key, "ICON"))
1967           {
1968              if (info->icon)
1969                free(info->icon);
1970
1971              info->icon = strdup(value);
1972           }
1973         else if (!strcmp(key, "DESKTOP"))
1974           info->desktop = atoi(value);
1975         else if (!strcmp(key, "TIMESTAMP"))
1976           {
1977              if (!info->timestamp)
1978                info->timestamp = atoi(value);
1979           }
1980         else if (!strcmp(key, "DESCRIPTION"))
1981           {
1982              if (info->description)
1983                free(info->description);
1984
1985              info->description = strdup(value);
1986           }
1987         else if (!strcmp(key, "WMCLASS"))
1988           {
1989              if (info->wmclass)
1990                free(info->wmclass);
1991
1992              info->wmclass = strdup(value);
1993           }
1994         else if (!strcmp(key, "SILENT"))
1995           info->silent = atoi(value);
1996         else
1997           ERR("Ecore X Sequence, Unknown: %s=%s", key, value);
1998      }
1999    if (!info->id)
2000      return 0;
2001
2002    return 1;
2003 }
2004
2005 #endif /* if 0 */
2006
2007 /*
2008  * Free startup info struct
2009  */
2010 static void
2011 _ecore_x_netwm_startup_info_free(void *data)
2012 {
2013    Ecore_X_Startup_Info *info;
2014
2015    info = data;
2016    if (!info)
2017      return;
2018
2019    if (info->buffer)
2020      free(info->buffer);
2021
2022    if (info->id)
2023      free(info->id);
2024
2025    if (info->name)
2026      free(info->name);
2027
2028    if (info->bin)
2029      free(info->bin);
2030
2031    if (info->icon)
2032      free(info->icon);
2033
2034    if (info->description)
2035      free(info->description);
2036
2037    if (info->wmclass)
2038      free(info->wmclass);
2039
2040    free(info);
2041 }
2042
2043 /*
2044  * Is screen composited?
2045  */
2046 EAPI Eina_Bool
2047 ecore_x_screen_is_composited(int screen)
2048 {
2049    Ecore_X_Window win;
2050    static Ecore_X_Atom atom = None;
2051    char buf[32];
2052
2053    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2054    snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
2055    if (atom == None)
2056      atom = XInternAtom(_ecore_x_disp, buf, False);
2057
2058    if (atom == None)
2059      return EINA_FALSE;
2060
2061    win = XGetSelectionOwner(_ecore_x_disp, atom);
2062
2063    return (win != None) ? EINA_TRUE : EINA_FALSE;
2064 }
2065
2066 EAPI void
2067 ecore_x_screen_is_composited_set(int screen,
2068                                  Ecore_X_Window win)
2069 {
2070    static Ecore_X_Atom atom = None;
2071    char buf[32];
2072
2073    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2074    snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
2075    if (atom == None)
2076      atom = XInternAtom(_ecore_x_disp, buf, False);
2077
2078    if (atom == None)
2079      return;
2080
2081    XSetSelectionOwner(_ecore_x_disp, atom, win, _ecore_x_event_last_time);
2082 }
2083