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