chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / e16-ecore_hints.c
1 /*
2  * Copyright (C) 2004-2008 Kim Woelders
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies of the Software, its documentation and marketing & publicity
13  * materials, and acknowledgment shall be given in the documentation, materials
14  * and software packages that this Software was used.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 /*
24  * Stuff for compiling without ecore_x.
25  */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <X11/Xatom.h>
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32
33 #include "config.h"
34 #include "e16-ecore_hints.h"
35
36 /* Window property change actions (must match _NET_WM_STATE_... ones) */
37 #define ECORE_X_PROP_LIST_REMOVE    0
38 #define ECORE_X_PROP_LIST_ADD       1
39 #define ECORE_X_PROP_LIST_TOGGLE    2
40
41 #ifdef USE_ECORE_X
42
43 extern Display     *_ecore_x_disp;
44
45 void
46 ecore_x_icccm_state_set_iconic(Ecore_X_Window win)
47 {
48    ecore_x_icccm_state_set(win, ECORE_X_WINDOW_STATE_HINT_ICONIC);
49 }
50
51 void
52 ecore_x_icccm_state_set_normal(Ecore_X_Window win)
53 {
54    ecore_x_icccm_state_set(win, ECORE_X_WINDOW_STATE_HINT_NORMAL);
55 }
56
57 void
58 ecore_x_icccm_state_set_withdrawn(Ecore_X_Window win)
59 {
60    ecore_x_icccm_state_set(win, ECORE_X_WINDOW_STATE_HINT_WITHDRAWN);
61 }
62
63 #else /* USE_ECORE_X */
64
65 #define DEBUG_CHECK 0
66 #if DEBUG_CHECK
67 #include <assert.h>
68 #endif
69 #include "hints.h"
70 #include "xwin.h"
71
72 #define _ecore_x_disp disp
73
74 #define N_ITEMS(x) (sizeof(x)/sizeof(x[0]))
75
76 /*
77  * General stuff
78  */
79
80 /*
81  * Send client message (format 32)
82  */
83 int
84 ecore_x_client_message32_send(Window win, Atom type, long mask, long d0,
85                               long d1, long d2, long d3, long d4)
86 {
87    XEvent              xev;
88
89    xev.xclient.type = ClientMessage;
90    xev.xclient.window = win;
91    xev.xclient.message_type = type;
92    xev.xclient.format = 32;
93    xev.xclient.data.l[0] = d0;
94    xev.xclient.data.l[1] = d1;
95    xev.xclient.data.l[2] = d2;
96    xev.xclient.data.l[3] = d3;
97    xev.xclient.data.l[4] = d4;
98
99    return XSendEvent(_ecore_x_disp, win, False, mask, &xev);
100 }
101
102 /*
103  * Set CARD32 (array) property
104  */
105 void
106 ecore_x_window_prop_card32_set(Ecore_X_Window win, Ecore_X_Atom atom,
107                                unsigned int *val, unsigned int num)
108 {
109 #if SIZEOF_INT == SIZEOF_LONG
110    XChangeProperty(_ecore_x_disp, win, atom, XA_CARDINAL, 32, PropModeReplace,
111                    (unsigned char *)val, num);
112 #else
113    unsigned long      *pl;
114    unsigned int        i;
115
116    pl = malloc(num * sizeof(long));
117    if (!pl)
118       return;
119    for (i = 0; i < num; i++)
120       pl[i] = val[i];
121    XChangeProperty(_ecore_x_disp, win, atom, XA_CARDINAL, 32, PropModeReplace,
122                    (unsigned char *)pl, num);
123    free(pl);
124 #endif
125 }
126
127 /*
128  * Get CARD32 (array) property
129  *
130  * At most len items are returned in val.
131  * If the property was successfully fetched the number of items stored in
132  * val is returned, otherwise -1 is returned.
133  * Note: Return value 0 means that the property exists but has no elements.
134  */
135 int
136 ecore_x_window_prop_card32_get(Ecore_X_Window win, Ecore_X_Atom atom,
137                                unsigned int *val, unsigned int len)
138 {
139    unsigned char      *prop_ret;
140    Atom                type_ret;
141    unsigned long       bytes_after, num_ret;
142    int                 format_ret;
143    unsigned int        i;
144    int                 num;
145
146    prop_ret = NULL;
147    if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
148                           XA_CARDINAL, &type_ret, &format_ret, &num_ret,
149                           &bytes_after, &prop_ret) != Success)
150       return -1;
151
152    if (type_ret == None || num_ret == 0)
153      {
154         num = 0;
155      }
156    else if (prop_ret && type_ret == XA_CARDINAL && format_ret == 32)
157      {
158         if (num_ret < len)
159            len = num_ret;
160         for (i = 0; i < len; i++)
161            val[i] = ((unsigned long *)prop_ret)[i];
162         num = len;
163      }
164    else
165      {
166         num = -1;
167      }
168    if (prop_ret)
169       XFree(prop_ret);
170
171    return num;
172 }
173
174 /*
175  * Get CARD32 (array) property of any length
176  *
177  * If the property was successfully fetched the number of items stored in
178  * val is returned, otherwise -1 is returned.
179  * Note: Return value 0 means that the property exists but has no elements.
180  */
181 int
182 ecore_x_window_prop_card32_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
183                                     unsigned int **plst)
184 {
185    unsigned char      *prop_ret;
186    Atom                type_ret;
187    unsigned long       bytes_after, num_ret;
188    int                 format_ret;
189    unsigned int        i, *val;
190    int                 num;
191
192    prop_ret = NULL;
193    if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
194                           XA_CARDINAL, &type_ret, &format_ret, &num_ret,
195                           &bytes_after, &prop_ret) != Success)
196       return -1;
197
198    if (type_ret == None || num_ret == 0)
199      {
200         num = 0;
201         *plst = NULL;
202      }
203    else if (prop_ret && type_ret == XA_CARDINAL && format_ret == 32)
204      {
205         val = (unsigned int *)malloc(num_ret * sizeof(unsigned int));
206         for (i = 0; i < num_ret; i++)
207            val[i] = ((unsigned long *)prop_ret)[i];
208         num = num_ret;
209         *plst = val;
210      }
211    else
212      {
213         num = -1;
214         *plst = NULL;
215      }
216    if (prop_ret)
217       XFree(prop_ret);
218
219    return num;
220 }
221
222 #endif /* USE_ECORE_X */
223
224 /*
225  * Set simple string list property
226  */
227 void
228 ecore_x_window_prop_string_list_set(Ecore_X_Window win, Ecore_X_Atom atom,
229                                     char **lst, int num)
230 {
231    XTextProperty       xtp;
232
233    if (XmbTextListToTextProperty(_ecore_x_disp, lst, num,
234                                  XStdICCTextStyle, &xtp) != Success)
235       return;
236    XSetTextProperty(_ecore_x_disp, win, &xtp, atom);
237    XFree(xtp.value);
238 }
239
240 /*
241  * Get simple string list property
242  *
243  * If the property was successfully fetched the number of items stored in
244  * lst is returned, otherwise -1 is returned.
245  * Note: Return value 0 means that the property exists but has no elements.
246  */
247 int
248 ecore_x_window_prop_string_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
249                                     char ***plst)
250 {
251    char              **pstr = NULL;
252    XTextProperty       xtp;
253    int                 i, items;
254    char              **list;
255    Status              s;
256
257    *plst = NULL;
258
259    if (!XGetTextProperty(_ecore_x_disp, win, &xtp, atom))
260       return -1;
261
262    if (xtp.format == 8)
263      {
264         s = XmbTextPropertyToTextList(_ecore_x_disp, &xtp, &list, &items);
265         if (s == Success)
266           {
267              if (items > 0)
268                {
269                   pstr = (char **)malloc(items * sizeof(char *));
270                   for (i = 0; i < items; i++)
271                      pstr[i] = (list[i] && (*list[i] || i < items - 1)) ?
272                         strdup(list[i]) : NULL;
273                }
274              if (list)
275                 XFreeStringList(list);
276              goto done;
277           }
278      }
279
280    /* Bad format or XmbTextPropertyToTextList failed - Now what? */
281    pstr = (char **)malloc(sizeof(char *));
282    pstr[0] = (xtp.value) ? strdup((char *)xtp.value) : NULL;
283    items = 1;
284
285  done:
286    XFree(xtp.value);
287
288    *plst = pstr;
289    return items;
290 }
291
292 #ifndef USE_ECORE_X
293
294 /*
295  * Set simple string property
296  */
297 void
298 ecore_x_window_prop_string_set(Ecore_X_Window win, Ecore_X_Atom atom,
299                                const char *str)
300 {
301    ecore_x_window_prop_string_list_set(win, atom, (char **)(&str), 1);
302 }
303
304 /*
305  * Get simple string property
306  */
307 char               *
308 ecore_x_window_prop_string_get(Ecore_X_Window win, Ecore_X_Atom atom)
309 {
310    XTextProperty       xtp;
311    char               *str;
312    int                 items;
313    char              **list;
314    Status              s;
315
316    if (!XGetTextProperty(_ecore_x_disp, win, &xtp, atom))
317       return NULL;
318
319    if (xtp.format == 8)
320      {
321         s = XmbTextPropertyToTextList(_ecore_x_disp, &xtp, &list, &items);
322         if ((s == Success) && (items > 0))
323           {
324              str = (*list) ? strdup(*list) : NULL;
325              XFreeStringList(list);
326           }
327         else
328            str = (xtp.value) ? strdup((char *)xtp.value) : NULL;
329      }
330    else
331       str = (xtp.value) ? strdup((char *)xtp.value) : NULL;
332
333    XFree(xtp.value);
334
335    return str;
336 }
337
338 /*
339  * Set UTF-8 string property
340  */
341 static void
342 _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win, Ecore_X_Atom atom,
343                                      const char *str)
344 {
345    XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8,
346                    PropModeReplace, (unsigned char *)str, strlen(str));
347 }
348
349 /*
350  * Get UTF-8 string property
351  */
352 static char        *
353 _ecore_x_window_prop_string_utf8_get(Ecore_X_Window win, Ecore_X_Atom atom)
354 {
355    char               *str;
356    unsigned char      *prop_ret;
357    Atom                type_ret;
358    unsigned long       bytes_after, num_ret;
359    int                 format_ret;
360
361    str = NULL;
362    prop_ret = NULL;
363    XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
364                       ECORE_X_ATOM_UTF8_STRING, &type_ret,
365                       &format_ret, &num_ret, &bytes_after, &prop_ret);
366    if (prop_ret && num_ret > 0 && format_ret == 8)
367      {
368         str = (char *)malloc(num_ret + 1);
369         if (str)
370           {
371              memcpy(str, prop_ret, num_ret);
372              str[num_ret] = '\0';
373           }
374      }
375    if (prop_ret)
376       XFree(prop_ret);
377
378    return str;
379 }
380
381 /*
382  * Set X ID (array) property
383  */
384 void
385 ecore_x_window_prop_xid_set(Ecore_X_Window win, Ecore_X_Atom atom,
386                             Ecore_X_Atom type, Ecore_X_ID * lst,
387                             unsigned int num)
388 {
389 #if SIZEOF_INT == SIZEOF_LONG
390    XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace,
391                    (unsigned char *)lst, num);
392 #else
393    unsigned long      *pl;
394    unsigned int        i;
395
396    pl = malloc(num * sizeof(long));
397    if (!pl)
398       return;
399    for (i = 0; i < num; i++)
400       pl[i] = lst[i];
401    XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace,
402                    (unsigned char *)pl, num);
403    free(pl);
404 #endif
405 }
406
407 /*
408  * Get X ID (array) property
409  *
410  * At most len items are returned in val.
411  * If the property was successfully fetched the number of items stored in
412  * val is returned, otherwise -1 is returned.
413  * Note: Return value 0 means that the property exists but has no elements.
414  */
415 int
416 ecore_x_window_prop_xid_get(Ecore_X_Window win, Ecore_X_Atom atom,
417                             Ecore_X_Atom type, Ecore_X_ID * lst,
418                             unsigned int len)
419 {
420    unsigned char      *prop_ret;
421    Atom                type_ret;
422    unsigned long       bytes_after, num_ret;
423    int                 format_ret;
424    int                 num;
425    unsigned            i;
426
427    prop_ret = NULL;
428    if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
429                           type, &type_ret, &format_ret, &num_ret,
430                           &bytes_after, &prop_ret) != Success)
431       return -1;
432
433    if (type_ret == None)
434      {
435         num = 0;
436      }
437    else if (prop_ret && type_ret == type && format_ret == 32)
438      {
439         if (num_ret < len)
440            len = num_ret;
441         for (i = 0; i < len; i++)
442            lst[i] = ((unsigned long *)prop_ret)[i];
443         num = len;
444      }
445    else
446      {
447         num = -1;
448      }
449    if (prop_ret)
450       XFree(prop_ret);
451
452    return num;
453 }
454
455 /*
456  * Get X ID (array) property
457  *
458  * If the property was successfully fetched the number of items stored in
459  * val is returned, otherwise -1 is returned.
460  * The returned array must be freed with free().
461  * Note: Return value 0 means that the property exists but has no elements.
462  */
463 int
464 ecore_x_window_prop_xid_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
465                                  Ecore_X_Atom type, Ecore_X_ID ** val)
466 {
467    unsigned char      *prop_ret;
468    Atom                type_ret;
469    unsigned long       bytes_after, num_ret;
470    int                 format_ret;
471    Ecore_X_Atom       *alst;
472    int                 num;
473    unsigned            i;
474
475    *val = NULL;
476    prop_ret = NULL;
477    if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
478                           type, &type_ret, &format_ret, &num_ret,
479                           &bytes_after, &prop_ret) != Success)
480       return -1;
481
482    if (type_ret == None || num_ret == 0)
483      {
484         num = 0;
485      }
486    else if (prop_ret && type_ret == type && format_ret == 32)
487      {
488         alst = (Ecore_X_Atom *) malloc(num_ret * sizeof(Ecore_X_ID));
489         for (i = 0; i < num_ret; i++)
490            alst[i] = ((unsigned long *)prop_ret)[i];
491         *val = alst;
492         num = num_ret;
493      }
494    else
495      {
496         num = -1;
497      }
498    if (prop_ret)
499       XFree(prop_ret);
500
501    return num;
502 }
503
504 /*
505  * Remove/add/toggle X ID list item.
506  */
507 void
508 ecore_x_window_prop_xid_list_change(Ecore_X_Window win, Ecore_X_Atom atom,
509                                     Ecore_X_Atom type, Ecore_X_ID item, int op)
510 {
511    Ecore_X_ID         *lst;
512    int                 i, num;
513
514    num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst);
515    if (num < 0)
516       return;                   /* Error - assuming invalid window */
517
518    /* Is it there? */
519    for (i = 0; i < num; i++)
520      {
521         if (lst[i] == item)
522            break;
523      }
524
525    if (i < num)
526      {
527         /* Was in list */
528         if (op == ECORE_X_PROP_LIST_ADD)
529            goto done;
530         /* Remove it */
531         num--;
532         for (; i < num; i++)
533            lst[i] = lst[i + 1];
534      }
535    else
536      {
537         /* Was not in list */
538         if (op == ECORE_X_PROP_LIST_REMOVE)
539            goto done;
540         /* Add it */
541         num++;
542         lst = (Ecore_X_ID *) realloc(lst, num * sizeof(Ecore_X_ID));
543         lst[i] = item;
544      }
545
546    ecore_x_window_prop_xid_set(win, atom, type, lst, num);
547
548  done:
549    if (lst)
550       free(lst);
551 }
552
553 /*
554  * Set Atom (array) property
555  */
556 void
557 ecore_x_window_prop_atom_set(Ecore_X_Window win, Ecore_X_Atom atom,
558                              Ecore_X_Atom * lst, unsigned int num)
559 {
560    ecore_x_window_prop_xid_set(win, atom, XA_ATOM, lst, num);
561 }
562
563 /*
564  * Get Atom (array) property
565  *
566  * At most len items are returned in val.
567  * If the property was successfully fetched the number of items stored in
568  * val is returned, otherwise -1 is returned.
569  * Note: Return value 0 means that the property exists but has no elements.
570  */
571 int
572 ecore_x_window_prop_atom_get(Ecore_X_Window win, Ecore_X_Atom atom,
573                              Ecore_X_Atom * lst, unsigned int len)
574 {
575    return ecore_x_window_prop_xid_get(win, atom, XA_ATOM, lst, len);
576 }
577
578 /*
579  * Get Atom (array) property
580  *
581  * If the property was successfully fetched the number of items stored in
582  * val is returned, otherwise -1 is returned.
583  * The returned array must be freed with free().
584  * Note: Return value 0 means that the property exists but has no elements.
585  */
586 int
587 ecore_x_window_prop_atom_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
588                                   Ecore_X_Atom ** plst)
589 {
590    return ecore_x_window_prop_xid_list_get(win, atom, XA_ATOM, plst);
591 }
592
593 /*
594  * Remove/add/toggle atom list item.
595  */
596 void
597 ecore_x_window_prop_atom_list_change(Ecore_X_Window win, Ecore_X_Atom atom,
598                                      Ecore_X_Atom item, int op)
599 {
600    ecore_x_window_prop_xid_list_change(win, atom, XA_ATOM, item, op);
601 }
602
603 /*
604  * Set Window (array) property
605  */
606 void
607 ecore_x_window_prop_window_set(Ecore_X_Window win, Ecore_X_Atom atom,
608                                Ecore_X_Window * lst, unsigned int num)
609 {
610    ecore_x_window_prop_xid_set(win, atom, XA_WINDOW, lst, num);
611 }
612
613 /*
614  * Get Window (array) property
615  *
616  * At most len items are returned in val.
617  * If the property was successfully fetched the number of items stored in
618  * val is returned, otherwise -1 is returned.
619  * Note: Return value 0 means that the property exists but has no elements.
620  */
621 int
622 ecore_x_window_prop_window_get(Ecore_X_Window win, Ecore_X_Atom atom,
623                                Ecore_X_Window * lst, unsigned int len)
624 {
625    return ecore_x_window_prop_xid_get(win, atom, XA_WINDOW, lst, len);
626 }
627
628 /*
629  * Get Window (array) property
630  *
631  * If the property was successfully fetched the number of items stored in
632  * val is returned, otherwise -1 is returned.
633  * The returned array must be freed with free().
634  * Note: Return value 0 means that the property exists but has no elements.
635  */
636 int
637 ecore_x_window_prop_window_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
638                                     Ecore_X_Window ** plst)
639 {
640    return ecore_x_window_prop_xid_list_get(win, atom, XA_WINDOW, plst);
641 }
642
643 #endif /* USE_ECORE_X */
644
645 #ifndef USE_ECORE_X
646 /*
647  * ICCCM stuff
648  */
649
650 static const char  *const atoms_icccm_names[] = {
651 /* *INDENT-OFF* */
652
653    /* ICCCM */
654    "WM_STATE",
655    "WM_WINDOW_ROLE",
656    "WM_CLIENT_LEADER",
657    "WM_COLORMAP_WINDOWS",
658    "WM_CHANGE_STATE",
659    "WM_PROTOCOLS",
660    "WM_DELETE_WINDOW",
661    "WM_TAKE_FOCUS",
662 #if 0
663    "WM_SAVE_YOURSELF",
664 #endif
665
666    /* Misc. */
667    "UTF8_STRING",
668
669 /* *INDENT-ON* */
670 };
671 unsigned int        atoms_icccm[CHECK_COUNT_ICCCM];
672
673 void
674 ecore_x_icccm_init(void)
675 {
676 #if DEBUG_CHECK
677    assert(CHECK_COUNT_ICCCM == N_ITEMS(atoms_icccm));
678 #endif
679    AtomListIntern(atoms_icccm_names, N_ITEMS(atoms_icccm), atoms_icccm);
680 }
681
682 static void
683 ecore_x_icccm_state_set(Ecore_X_Window win, unsigned int state)
684 {
685    unsigned long       c[2];
686
687    c[0] = state;
688    c[1] = 0;
689    XChangeProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE,
690                    ECORE_X_ATOM_WM_STATE, 32, PropModeReplace,
691                    (unsigned char *)c, 2);
692 }
693
694 void
695 ecore_x_icccm_state_set_iconic(Ecore_X_Window win)
696 {
697    ecore_x_icccm_state_set(win, IconicState);
698 }
699
700 void
701 ecore_x_icccm_state_set_normal(Ecore_X_Window win)
702 {
703    ecore_x_icccm_state_set(win, NormalState);
704 }
705
706 void
707 ecore_x_icccm_state_set_withdrawn(Ecore_X_Window win)
708 {
709    ecore_x_icccm_state_set(win, WithdrawnState);
710 }
711
712 static void
713 ecore_x_icccm_client_message_send(Ecore_X_Window win,
714                                   Ecore_X_Atom atom, Ecore_X_Time ts)
715 {
716    ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, NoEventMask,
717                                  atom, ts, 0, 0, 0);
718 }
719
720 void
721 ecore_x_icccm_delete_window_send(Ecore_X_Window win, Ecore_X_Time ts)
722 {
723    ecore_x_icccm_client_message_send(win, ECORE_X_ATOM_WM_DELETE_WINDOW, ts);
724 }
725
726 void
727 ecore_x_icccm_take_focus_send(Ecore_X_Window win, Ecore_X_Time ts)
728 {
729    ecore_x_icccm_client_message_send(win, ECORE_X_ATOM_WM_TAKE_FOCUS, ts);
730 }
731
732 #if 0
733 void
734 ecore_x_icccm_save_yourself_send(Ecore_X_Window win, Ecore_X_Time ts)
735 {
736    ecore_x_icccm_client_message_send(win, ECORE_X_ATOM_WM_SAVE_YOURSELF, ts);
737 }
738 #endif
739
740 void
741 ecore_x_icccm_title_set(Ecore_X_Window win, const char *title)
742 {
743    ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_NAME, title);
744 }
745
746 char               *
747 ecore_x_icccm_title_get(Ecore_X_Window win)
748 {
749    return ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_NAME);
750 }
751
752 void
753 ecore_x_icccm_name_class_set(Ecore_X_Window win, const char *name,
754                              const char *clss)
755 {
756    XClassHint         *xch;
757
758    xch = XAllocClassHint();
759    if (!xch)
760       return;
761    xch->res_name = (char *)name;
762    xch->res_class = (char *)clss;
763    XSetClassHint(_ecore_x_disp, win, xch);
764    XFree(xch);
765 }
766
767 void
768 ecore_x_icccm_name_class_get(Ecore_X_Window win, char **name, char **clss)
769 {
770    XClassHint          xch;
771
772    *name = *clss = NULL;
773    xch.res_name = NULL;
774    xch.res_class = NULL;
775    if (XGetClassHint(_ecore_x_disp, win, &xch))
776      {
777         if (name && xch.res_name)
778            *name = strdup(xch.res_name);
779         if (clss && xch.res_class)
780            *clss = strdup(xch.res_class);
781         XFree(xch.res_name);
782         XFree(xch.res_class);
783      }
784 }
785
786 #endif /* USE_ECORE_X */
787
788 #ifndef USE_ECORE_X
789 /*
790  * _NET_WM hints (EWMH)
791  */
792
793 static const char  *const atoms_netwm_names[] = {
794 /* *INDENT-OFF* */
795
796    /* Window manager info */
797    "_NET_SUPPORTED",
798    "_NET_SUPPORTING_WM_CHECK",
799
800    /* Desktop status/requests */
801    "_NET_NUMBER_OF_DESKTOPS",
802    "_NET_VIRTUAL_ROOTS",
803    "_NET_DESKTOP_GEOMETRY",
804    "_NET_DESKTOP_NAMES",
805    "_NET_DESKTOP_VIEWPORT",
806    "_NET_WORKAREA",
807    "_NET_CURRENT_DESKTOP",
808    "_NET_SHOWING_DESKTOP",
809
810    "_NET_ACTIVE_WINDOW",
811    "_NET_CLIENT_LIST",
812    "_NET_CLIENT_LIST_STACKING",
813
814    /* Client window props/client messages */
815    "_NET_WM_NAME",
816    "_NET_WM_VISIBLE_NAME",
817    "_NET_WM_ICON_NAME",
818    "_NET_WM_VISIBLE_ICON_NAME",
819
820    "_NET_WM_DESKTOP",
821
822    "_NET_WM_WINDOW_TYPE",
823    "_NET_WM_WINDOW_TYPE_DESKTOP",
824    "_NET_WM_WINDOW_TYPE_DOCK",
825    "_NET_WM_WINDOW_TYPE_TOOLBAR",
826    "_NET_WM_WINDOW_TYPE_MENU",
827    "_NET_WM_WINDOW_TYPE_UTILITY",
828    "_NET_WM_WINDOW_TYPE_SPLASH",
829    "_NET_WM_WINDOW_TYPE_DIALOG",
830    "_NET_WM_WINDOW_TYPE_NORMAL",
831
832    "_NET_WM_STATE",
833    "_NET_WM_STATE_MODAL",
834    "_NET_WM_STATE_STICKY",
835    "_NET_WM_STATE_MAXIMIZED_VERT",
836    "_NET_WM_STATE_MAXIMIZED_HORZ",
837    "_NET_WM_STATE_SHADED",
838    "_NET_WM_STATE_SKIP_TASKBAR",
839    "_NET_WM_STATE_SKIP_PAGER",
840    "_NET_WM_STATE_HIDDEN",
841    "_NET_WM_STATE_FULLSCREEN",
842    "_NET_WM_STATE_ABOVE",
843    "_NET_WM_STATE_BELOW",
844    "_NET_WM_STATE_DEMANDS_ATTENTION",
845
846    "_NET_WM_ALLOWED_ACTIONS",
847    "_NET_WM_ACTION_MOVE",
848    "_NET_WM_ACTION_RESIZE",
849    "_NET_WM_ACTION_MINIMIZE",
850    "_NET_WM_ACTION_SHADE",
851    "_NET_WM_ACTION_STICK",
852    "_NET_WM_ACTION_MAXIMIZE_HORZ",
853    "_NET_WM_ACTION_MAXIMIZE_VERT",
854    "_NET_WM_ACTION_FULLSCREEN",
855    "_NET_WM_ACTION_CHANGE_DESKTOP",
856    "_NET_WM_ACTION_CLOSE",
857    "_NET_WM_ACTION_ABOVE",
858    "_NET_WM_ACTION_BELOW",
859
860    "_NET_WM_STRUT",
861    "_NET_WM_STRUT_PARTIAL",
862
863    "_NET_FRAME_EXTENTS",
864
865    "_NET_WM_ICON",
866
867    "_NET_WM_USER_TIME",
868
869 #if 0                           /* Not used */
870    "_NET_WM_ICON_GEOMETRY",
871    "_NET_WM_PID",
872    "_NET_WM_HANDLED_ICONS",
873
874    "_NET_WM_PING",
875 #endif
876    "_NET_WM_SYNC_REQUEST",
877    "_NET_WM_SYNC_REQUEST_COUNTER",
878
879    "_NET_WM_WINDOW_OPACITY",
880
881    /* Misc window ops */
882    "_NET_CLOSE_WINDOW",
883    "_NET_MOVERESIZE_WINDOW",
884    "_NET_WM_MOVERESIZE",
885    "_NET_RESTACK_WINDOW",
886
887 #if 0                           /* Not yet implemented */
888    "_NET_REQUEST_FRAME_EXTENTS",
889 #endif
890
891    /* Startup notification */
892    "_NET_STARTUP_ID",
893    "_NET_STARTUP_INFO_BEGIN",
894    "_NET_STARTUP_INFO",
895
896 /* *INDENT-ON* */
897 };
898 unsigned int        atoms_netwm[CHECK_COUNT_NETWM];
899
900 void
901 ecore_x_netwm_init(void)
902 {
903 #if DEBUG_CHECK
904    assert(CHECK_COUNT_NETWM == N_ITEMS(atoms_netwm));
905 #endif
906    AtomListIntern(atoms_netwm_names, N_ITEMS(atoms_netwm), atoms_netwm);
907 }
908
909 /*
910  * WM identification
911  */
912 void
913 ecore_x_netwm_wm_identify(Ecore_X_Window root, Ecore_X_Window check,
914                           const char *wm_name)
915 {
916    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
917                                   &check, 1);
918    ecore_x_window_prop_window_set(check, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
919                                   &check, 1);
920    _ecore_x_window_prop_string_utf8_set(check, ECORE_X_ATOM_NET_WM_NAME,
921                                         wm_name);
922    /* This one isn't mandatory */
923    _ecore_x_window_prop_string_utf8_set(root, ECORE_X_ATOM_NET_WM_NAME,
924                                         wm_name);
925 }
926
927 /*
928  * Desktop configuration and status
929  */
930
931 void
932 ecore_x_netwm_desk_count_set(Ecore_X_Window root, unsigned int n_desks)
933 {
934    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS,
935                                   &n_desks, 1);
936 }
937
938 void
939 ecore_x_netwm_desk_roots_set(Ecore_X_Window root, Ecore_X_Window * vroots,
940                              unsigned int n_desks)
941 {
942    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_VIRTUAL_ROOTS, vroots,
943                                   n_desks);
944 }
945
946 void
947 ecore_x_netwm_desk_names_set(Ecore_X_Window root, const char **names,
948                              unsigned int n_desks)
949 {
950    char                ss[32], *buf;
951    const char         *s;
952    unsigned int        i;
953    int                 l, len;
954
955    buf = NULL;
956    len = 0;
957
958    for (i = 0; i < n_desks; i++)
959      {
960         s = (names) ? names[i] : NULL;
961         if (!s)
962           {
963              /* Default to "Desk-<number>" */
964              sprintf(ss, "Desk-%d", i);
965              s = ss;
966           }
967
968         l = strlen(s) + 1;
969         buf = (char *)realloc(buf, len + l);
970         memcpy(buf + len, s, l);
971         len += l;
972      }
973
974    XChangeProperty(_ecore_x_disp, root, ECORE_X_ATOM_NET_DESKTOP_NAMES,
975                    ECORE_X_ATOM_UTF8_STRING, 8, PropModeReplace,
976                    (unsigned char *)buf, len);
977
978    free(buf);
979 }
980
981 void
982 ecore_x_netwm_desk_size_set(Ecore_X_Window root, unsigned int width,
983                             unsigned int height)
984 {
985    unsigned int        size[2];
986
987    size[0] = width;
988    size[1] = height;
989    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, size,
990                                   2);
991 }
992
993 void
994 ecore_x_netwm_desk_workareas_set(Ecore_X_Window root, unsigned int *areas,
995                                  unsigned int n_desks)
996 {
997    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas,
998                                   4 * n_desks);
999 }
1000
1001 void
1002 ecore_x_netwm_desk_current_set(Ecore_X_Window root, unsigned int desk)
1003 {
1004    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, &desk,
1005                                   1);
1006 }
1007
1008 void
1009 ecore_x_netwm_desk_viewports_set(Ecore_X_Window root, unsigned int *origins,
1010                                  unsigned int n_desks)
1011 {
1012    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT,
1013                                   origins, 2 * n_desks);
1014 }
1015
1016 void
1017 ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, int on)
1018 {
1019    unsigned int        val;
1020
1021    val = (on) ? 1 : 0;
1022    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, &val,
1023                                   1);
1024 }
1025
1026 /*
1027  * Client status
1028  */
1029
1030 /* Mapping order */
1031 void
1032 ecore_x_netwm_client_list_set(Ecore_X_Window root, Ecore_X_Window * p_clients,
1033                               unsigned int n_clients)
1034 {
1035    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST, p_clients,
1036                                   n_clients);
1037 }
1038
1039 /* Stacking order */
1040 void
1041 ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root,
1042                                        Ecore_X_Window * p_clients,
1043                                        unsigned int n_clients)
1044 {
1045    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING,
1046                                   p_clients, n_clients);
1047 }
1048
1049 void
1050 ecore_x_netwm_client_active_set(Ecore_X_Window root, Ecore_X_Window win)
1051 {
1052    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_ACTIVE_WINDOW, &win,
1053                                   1);
1054 }
1055
1056 /*
1057  * Client window properties
1058  */
1059
1060 void
1061 ecore_x_netwm_name_set(Ecore_X_Window win, const char *name)
1062 {
1063    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_NAME, name);
1064 }
1065
1066 int
1067 ecore_x_netwm_name_get(Ecore_X_Window win, char **name)
1068 {
1069    char               *s;
1070
1071    s = _ecore_x_window_prop_string_utf8_get(win, ECORE_X_ATOM_NET_WM_NAME);
1072    *name = s;
1073
1074    return s != NULL;
1075 }
1076
1077 void
1078 ecore_x_netwm_visible_name_set(Ecore_X_Window win, const char *name)
1079 {
1080    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME,
1081                                         name);
1082 }
1083
1084 int
1085 ecore_x_netwm_visible_name_get(Ecore_X_Window win, char **name)
1086 {
1087    char               *s;
1088
1089    s = _ecore_x_window_prop_string_utf8_get(win,
1090                                             ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
1091    *name = s;
1092
1093    return s != NULL;
1094 }
1095
1096 void
1097 ecore_x_netwm_icon_name_set(Ecore_X_Window win, const char *name)
1098 {
1099    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME,
1100                                         name);
1101 }
1102
1103 int
1104 ecore_x_netwm_icon_name_get(Ecore_X_Window win, char **name)
1105 {
1106    char               *s;
1107
1108    s = _ecore_x_window_prop_string_utf8_get(win, ECORE_X_ATOM_NET_WM_ICON_NAME);
1109    *name = s;
1110
1111    return s != NULL;
1112 }
1113
1114 void
1115 ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, const char *name)
1116 {
1117    _ecore_x_window_prop_string_utf8_set(win,
1118                                         ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME,
1119                                         name);
1120 }
1121
1122 int
1123 ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, char **name)
1124 {
1125    char               *s;
1126
1127    s = _ecore_x_window_prop_string_utf8_get(win,
1128                                             ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
1129    *name = s;
1130
1131    return s != NULL;
1132 }
1133
1134 void
1135 ecore_x_netwm_desktop_set(Ecore_X_Window win, unsigned int desk)
1136 {
1137    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1);
1138 }
1139
1140 int
1141 ecore_x_netwm_desktop_get(Ecore_X_Window win, unsigned int *desk)
1142 {
1143    return ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP,
1144                                          desk, 1);
1145 }
1146
1147 int
1148 ecore_x_netwm_user_time_get(Ecore_X_Window win, unsigned int *ts)
1149 {
1150    return ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME,
1151                                          ts, 1);
1152 }
1153
1154 void
1155 ecore_x_netwm_opacity_set(Ecore_X_Window win, unsigned int opacity)
1156 {
1157    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
1158                                   &opacity, 1);
1159 }
1160
1161 int
1162 ecore_x_netwm_opacity_get(Ecore_X_Window win, unsigned int *opacity)
1163 {
1164    return ecore_x_window_prop_card32_get(win,
1165                                          ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
1166                                          opacity, 1);
1167 }
1168
1169 #if 0                           /* Not used */
1170 void
1171 ecore_x_netwm_startup_id_set(Ecore_X_Window win, const char *id)
1172 {
1173    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_STARTUP_ID, id);
1174 }
1175 #endif
1176
1177 int
1178 ecore_x_netwm_startup_id_get(Ecore_X_Window win, char **id)
1179 {
1180    char               *s;
1181
1182    s = _ecore_x_window_prop_string_utf8_get(win, ECORE_X_ATOM_NET_STARTUP_ID);
1183    *id = s;
1184
1185    return s != NULL;
1186 }
1187
1188 #endif /* USE_ECORE_X */