60816800fd6a649763dbab359e65e8d51c5762ac
[framework/uifw/ecore.git] / src / lib / ecore_x / xlib / ecore_x_window_prop.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4 #include "Ecore.h"
5 #include "ecore_x_private.h"
6 #include "Ecore_X.h"
7 #include "Ecore_X_Atoms.h"
8 #include <inttypes.h>
9 #include <limits.h>
10
11 #define _ATOM_SET_CARD32(win, atom, p_val, cnt) \
12    XChangeProperty(_ecore_x_disp, win, atom, XA_CARDINAL, 32, PropModeReplace, \
13                    (unsigned char *)p_val, cnt)
14
15 /*
16  * Set CARD32 (array) property
17  */
18 EAPI void
19 ecore_x_window_prop_card32_set(Ecore_X_Window win, Ecore_X_Atom atom,
20                                unsigned int *val, unsigned int num)
21 {
22 #if SIZEOF_INT == SIZEOF_LONG
23    _ATOM_SET_CARD32(win, atom, val, num);
24 #else
25    long               *v2;
26    unsigned int        i;
27
28    v2 = malloc(num * sizeof(long));
29    if (!v2)
30       return;
31    for (i = 0; i < num; i++)
32       v2[i] = val[i];
33    _ATOM_SET_CARD32(win, atom, v2, num);
34    free(v2);
35 #endif
36 }
37
38 /*
39  * Get CARD32 (array) property
40  *
41  * At most len items are returned in val.
42  * If the property was successfully fetched the number of items stored in
43  * val is returned, otherwise -1 is returned.
44  * Note: Return value 0 means that the property exists but has no elements.
45  */
46 EAPI int
47 ecore_x_window_prop_card32_get(Ecore_X_Window win, Ecore_X_Atom atom,
48                                unsigned int *val, unsigned int len)
49 {
50    unsigned char      *prop_ret;
51    Atom                type_ret;
52    unsigned long       bytes_after, num_ret;
53    int                 format_ret;
54    unsigned int        i;
55    int                 num;
56
57    prop_ret = NULL;
58    XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
59                       XA_CARDINAL, &type_ret, &format_ret, &num_ret,
60                       &bytes_after, &prop_ret);
61    if (prop_ret && type_ret == XA_CARDINAL && format_ret == 32)
62      {
63         if (num_ret < len)
64            len = num_ret;
65
66         for (i = 0; i < len; i++)
67            val[i] = ((unsigned long*)prop_ret)[i];
68         
69         num = len;
70      }
71    else
72      {
73         num = -1;
74      }
75    if (prop_ret)
76       XFree(prop_ret);
77
78    return num;
79 }
80
81 /*
82  * Get CARD32 (array) property of any length
83  *
84  * If the property was successfully fetched the number of items stored in
85  * val is returned, otherwise -1 is returned.
86  * Note: Return value 0 means that the property exists but has no elements.
87  */
88 EAPI int
89 ecore_x_window_prop_card32_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
90                                     unsigned int **plst)
91 {
92    unsigned char      *prop_ret;
93    Atom                type_ret;
94    unsigned long       bytes_after, num_ret;
95    int                 format_ret;
96    unsigned int        i, *val;
97    int                 num;
98
99    prop_ret = NULL;
100    if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
101                           XA_CARDINAL, &type_ret, &format_ret, &num_ret,
102                           &bytes_after, &prop_ret) != Success)
103       return -1;
104
105    if (type_ret == None || num_ret == 0)
106      {
107         num = 0;
108         *plst = NULL;
109      }
110    else if (prop_ret && type_ret == XA_CARDINAL && format_ret == 32)
111      {
112         val = malloc(num_ret * sizeof(unsigned int));
113         for (i = 0; i < num_ret; i++)
114            val[i] = ((unsigned long *)prop_ret)[i];
115         num = num_ret;
116         *plst = val;
117      }
118    else
119      {
120         num = -1;
121         *plst = NULL;
122      }
123    if (prop_ret)
124       XFree(prop_ret);
125
126    return num;
127 }
128
129 /*
130  * Set X ID (array) property
131  */
132 EAPI void
133 ecore_x_window_prop_xid_set(Ecore_X_Window win, Ecore_X_Atom atom,
134                             Ecore_X_Atom type, Ecore_X_ID * lst,
135                             unsigned int num)
136 {
137 #if SIZEOF_INT == SIZEOF_LONG
138    XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace,
139                    (unsigned char *)lst, num);
140 #else
141    unsigned long      *pl;
142    unsigned int        i;
143
144    pl = malloc(num * sizeof(long));
145    if (!pl)
146       return;
147    for (i = 0; i < num; i++)
148       pl[i] = lst[i];
149    XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace,
150                    (unsigned char *)pl, num);
151    free(pl);
152 #endif
153 }
154
155 /*
156  * Get X ID (array) property
157  *
158  * At most len items are returned in val.
159  * If the property was successfully fetched the number of items stored in
160  * val is returned, otherwise -1 is returned.
161  * Note: Return value 0 means that the property exists but has no elements.
162  */
163 EAPI int
164 ecore_x_window_prop_xid_get(Ecore_X_Window win, Ecore_X_Atom atom,
165                             Ecore_X_Atom type, Ecore_X_ID * lst,
166                             unsigned int len)
167 {
168    unsigned char      *prop_ret;
169    Atom                type_ret;
170    unsigned long       bytes_after, num_ret;
171    int                 format_ret;
172    int                 num;
173    unsigned            i;
174
175    prop_ret = NULL;
176    if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
177                           type, &type_ret, &format_ret, &num_ret,
178                           &bytes_after, &prop_ret) != Success)
179       return -1;
180
181    if (type_ret == None)
182      {
183         num = 0;
184      }
185    else if (prop_ret && type_ret == type && format_ret == 32)
186      {
187         if (num_ret < len)
188            len = num_ret;
189         for (i = 0; i < len; i++)
190            lst[i] = ((unsigned long *)prop_ret)[i];
191         num = len;
192      }
193    else
194      {
195         num = -1;
196      }
197    if (prop_ret)
198       XFree(prop_ret);
199
200    return num;
201 }
202
203 /*
204  * Get X ID (array) property
205  *
206  * If the property was successfully fetched the number of items stored in
207  * val is returned, otherwise -1 is returned.
208  * The returned array must be freed with free().
209  * Note: Return value 0 means that the property exists but has no elements.
210  */
211 EAPI int
212 ecore_x_window_prop_xid_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
213                                  Ecore_X_Atom type, Ecore_X_ID ** val)
214 {
215    unsigned char      *prop_ret;
216    Atom                type_ret;
217    unsigned long       bytes_after, num_ret;
218    int                 format_ret;
219    Ecore_X_Atom       *alst;
220    int                 num;
221    unsigned            i;
222
223    *val = NULL;
224    prop_ret = NULL;
225    if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
226                           type, &type_ret, &format_ret, &num_ret,
227                           &bytes_after, &prop_ret) != Success)
228       return -1;
229
230    if (type_ret == None || num_ret == 0)
231      {
232         num = 0;
233      }
234    else if (prop_ret && type_ret == type && format_ret == 32)
235      {
236         alst = malloc(num_ret * sizeof(Ecore_X_ID));
237         for (i = 0; i < num_ret; i++)
238            alst[i] = ((unsigned long *)prop_ret)[i];
239         *val = alst;
240         num = num_ret;
241      }
242    else
243      {
244         num = -1;
245      }
246    if (prop_ret)
247       XFree(prop_ret);
248
249    return num;
250 }
251
252 /*
253  * Remove/add/toggle X ID list item.
254  */
255 EAPI void
256 ecore_x_window_prop_xid_list_change(Ecore_X_Window win, Ecore_X_Atom atom,
257                                     Ecore_X_Atom type, Ecore_X_ID item, int op)
258 {
259    Ecore_X_ID         *lst;
260    int                 i, num;
261
262    num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst);
263    if (num < 0)
264       return;                   /* Error - assuming invalid window */
265
266    /* Is it there? */
267    for (i = 0; i < num; i++)
268      {
269         if (lst[i] == item)
270            break;
271      }
272
273    if (i < num)
274      {
275         /* Was in list */
276         if (op == ECORE_X_PROP_LIST_ADD)
277            goto done;
278         /* Remove it */
279         num--;
280         for (; i < num; i++)
281            lst[i] = lst[i + 1];
282      }
283    else
284      {
285         /* Was not in list */
286         if (op == ECORE_X_PROP_LIST_REMOVE)
287            goto done;
288         /* Add it */
289         num++;
290         lst = realloc(lst, num * sizeof(Ecore_X_ID));
291         lst[i] = item;
292      }
293
294    ecore_x_window_prop_xid_set(win, atom, type, lst, num);
295
296  done:
297    if (lst)
298       free(lst);
299 }
300
301 /*
302  * Set Atom (array) property
303  */
304 EAPI void
305 ecore_x_window_prop_atom_set(Ecore_X_Window win, Ecore_X_Atom atom,
306                              Ecore_X_Atom * lst, unsigned int num)
307 {
308    ecore_x_window_prop_xid_set(win, atom, XA_ATOM, lst, num);
309 }
310
311 /*
312  * Get Atom (array) property
313  *
314  * At most len items are returned in val.
315  * If the property was successfully fetched the number of items stored in
316  * val is returned, otherwise -1 is returned.
317  * Note: Return value 0 means that the property exists but has no elements.
318  */
319 EAPI int
320 ecore_x_window_prop_atom_get(Ecore_X_Window win, Ecore_X_Atom atom,
321                              Ecore_X_Atom * lst, unsigned int len)
322 {
323    return ecore_x_window_prop_xid_get(win, atom, XA_ATOM, lst, len);
324 }
325
326 /*
327  * Get Atom (array) property
328  *
329  * If the property was successfully fetched the number of items stored in
330  * val is returned, otherwise -1 is returned.
331  * The returned array must be freed with free().
332  * Note: Return value 0 means that the property exists but has no elements.
333  */
334 EAPI int
335 ecore_x_window_prop_atom_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
336                                   Ecore_X_Atom ** plst)
337 {
338    return ecore_x_window_prop_xid_list_get(win, atom, XA_ATOM, plst);
339 }
340
341 /*
342  * Remove/add/toggle atom list item.
343  */
344 EAPI void
345 ecore_x_window_prop_atom_list_change(Ecore_X_Window win, Ecore_X_Atom atom,
346                                      Ecore_X_Atom item, int op)
347 {
348    ecore_x_window_prop_xid_list_change(win, atom, XA_ATOM, item, op);
349 }
350
351 /*
352  * Set Window (array) property
353  */
354 EAPI void
355 ecore_x_window_prop_window_set(Ecore_X_Window win, Ecore_X_Atom atom,
356                                Ecore_X_Window * lst, unsigned int num)
357 {
358    ecore_x_window_prop_xid_set(win, atom, XA_WINDOW, lst, num);
359 }
360
361 /*
362  * Get Window (array) property
363  *
364  * At most len items are returned in val.
365  * If the property was successfully fetched the number of items stored in
366  * val is returned, otherwise -1 is returned.
367  * Note: Return value 0 means that the property exists but has no elements.
368  */
369 EAPI int
370 ecore_x_window_prop_window_get(Ecore_X_Window win, Ecore_X_Atom atom,
371                                Ecore_X_Window * lst, unsigned int len)
372 {
373    return ecore_x_window_prop_xid_get(win, atom, XA_WINDOW, lst, len);
374 }
375
376 /*
377  * Get Window (array) property
378  *
379  * If the property was successfully fetched the number of items stored in
380  * val is returned, otherwise -1 is returned.
381  * The returned array must be freed with free().
382  * Note: Return value 0 means that the property exists but has no elements.
383  */
384 EAPI int
385 ecore_x_window_prop_window_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
386                                     Ecore_X_Window ** plst)
387 {
388    return ecore_x_window_prop_xid_list_get(win, atom, XA_WINDOW, plst);
389 }
390
391 /**
392  * To be documented.
393  *
394  * FIXME: To be fixed.
395  */
396 EAPI Ecore_X_Atom
397 ecore_x_window_prop_any_type(void)
398 {
399    return AnyPropertyType;
400 }
401
402 /**
403  * To be documented.
404  *
405  * FIXME: To be fixed.
406  */
407 EAPI void
408 ecore_x_window_prop_property_set(Ecore_X_Window win, Ecore_X_Atom property, Ecore_X_Atom type, int size, void *data, int number)
409 {
410    if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
411    if (size != 32)
412      XChangeProperty(_ecore_x_disp, win, property, type, size, PropModeReplace,
413                      (unsigned char *)data, number);
414    else
415      {
416         unsigned long *dat;
417         int            i, *ptr;
418         
419         dat = malloc(sizeof(unsigned long) * number);
420         if (dat)
421           {
422              for (ptr = (int *)data, i = 0; i < number; i++) dat[i] = ptr[i];
423              XChangeProperty(_ecore_x_disp, win, property, type, size, 
424                              PropModeReplace, (unsigned char *)dat, number);
425              free(dat);
426           }
427      }
428 }
429
430 /**
431  * To be documented.
432  *
433  * FIXME: To be fixed.
434  */
435 EAPI int
436 ecore_x_window_prop_property_get(Ecore_X_Window win, Ecore_X_Atom property, Ecore_X_Atom type, int size __UNUSED__, unsigned char **data, int *num)
437 {
438    Atom type_ret = 0;
439    int ret, size_ret = 0;
440    unsigned long num_ret = 0, bytes = 0, i;
441    unsigned char *prop_ret = NULL;
442
443    /* make sure these are initialized */
444    if (num) *num = 0;
445
446    if (data)
447      *data = NULL;
448    else /* we can't store the retrieved data, so just return */
449      return 0;
450
451    if (!win) win = DefaultRootWindow(_ecore_x_disp);
452
453    ret = XGetWindowProperty(_ecore_x_disp, win, property, 0, LONG_MAX,
454                             False, type, &type_ret, &size_ret,
455                             &num_ret, &bytes, &prop_ret);
456
457    if (ret != Success)
458         return 0;
459
460    if (!num_ret) {
461       XFree(prop_ret);
462       return 0;
463    }
464    
465    if (!(*data = malloc(num_ret * size_ret / 8))) {
466       XFree(prop_ret);
467       return 0;
468    }
469    
470    switch (size_ret) {
471       case 8:
472          for (i = 0; i < num_ret; i++)
473            (*data)[i] = prop_ret[i];
474          break;
475       case 16:
476          for (i = 0; i < num_ret; i++)
477            ((unsigned short *) *data)[i] = ((unsigned short *) prop_ret)[i];
478          break;
479       case 32:
480          for (i = 0; i < num_ret; i++)
481            ((unsigned int *) *data)[i] = ((unsigned long *) prop_ret)[i];
482          break;
483    }
484
485    XFree(prop_ret);
486
487    if (num) *num = num_ret;
488    return size_ret;
489 }
490
491 EAPI void
492 ecore_x_window_prop_property_del(Ecore_X_Window win, Ecore_X_Atom property)
493 {
494    XDeleteProperty(_ecore_x_disp, win, property);
495 }
496
497 EAPI Ecore_X_Atom *
498 ecore_x_window_prop_list(Ecore_X_Window win, int *num_ret)
499 {
500    Ecore_X_Atom *atoms;
501    Atom *atom_ret;
502    int num = 0, i;
503         
504    if (num_ret) *num_ret = 0;
505
506    atom_ret = XListProperties(_ecore_x_disp, win, &num);
507    if (!atom_ret) return NULL;
508
509    atoms = malloc(num * sizeof(Ecore_X_Atom));
510    if (atoms)
511      {
512         for (i = 0; i < num; i++) atoms[i] = atom_ret[i];
513         if (num_ret) *num_ret = num;
514      }
515    XFree(atom_ret);
516    return atoms;
517 }
518
519 /**
520  * Set a window string property.
521  * @param win The window
522  * @param type The property
523  * @param str The string
524  * 
525  * Set a window string property
526  */
527 EAPI void
528 ecore_x_window_prop_string_set(Ecore_X_Window win, Ecore_X_Atom type, const char *str)
529 {
530    XTextProperty       xtp;
531
532    if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
533    xtp.value = (unsigned char *)str;
534    xtp.format = 8;
535    xtp.encoding = ECORE_X_ATOM_UTF8_STRING;
536    xtp.nitems = strlen(str);
537    XSetTextProperty(_ecore_x_disp, win, &xtp, type);
538 }
539
540 /**
541  * Get a window string property.
542  * @param win The window
543  * @param type The property
544  * 
545  * Return window string property of a window. String must be free'd when done.
546  */
547 EAPI char *
548 ecore_x_window_prop_string_get(Ecore_X_Window win, Ecore_X_Atom type)
549 {
550    XTextProperty       xtp;
551    char               *str = NULL;
552
553    if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
554    if (XGetTextProperty(_ecore_x_disp, win, &xtp, type))
555      {
556         int      items;
557         char   **list = NULL;
558         Status   s;
559         
560         if (xtp.encoding == ECORE_X_ATOM_UTF8_STRING)
561           {
562              str = strdup((char *)xtp.value);
563           }
564         else
565           {
566 #ifdef X_HAVE_UTF8_STRING
567              s = Xutf8TextPropertyToTextList(_ecore_x_disp, &xtp,
568                                              &list, &items);
569 #else
570              s = XmbTextPropertyToTextList(_ecore_x_disp, &xtp,
571                                            &list, &items);
572 #endif
573              if ((s == XLocaleNotSupported) ||
574                  (s == XNoMemory) || (s == XConverterNotFound))
575                {
576                   str = strdup((char *)xtp.value);
577                }
578              else if ((s >= Success) && (items > 0))
579                {
580                   str = strdup(list[0]);
581                }
582              if (list)
583                XFreeStringList(list);
584           }
585         XFree(xtp.value);
586      }
587    return str;
588 }
589
590 EAPI int
591 ecore_x_window_prop_protocol_isset(Ecore_X_Window win,
592                                    Ecore_X_WM_Protocol protocol)
593 {
594    Atom proto, *protos = NULL;
595    int i, ret = 0, protos_count = 0;
596
597    /* check for invalid values */
598    if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
599         return 0;
600
601    proto = _ecore_x_atoms_wm_protocols[protocol];
602
603    if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
604         return ret;
605
606    for (i = 0; i < protos_count; i++)
607         if (protos[i] == proto)
608           {
609              ret = 1;
610              break;
611           }
612
613    XFree(protos);
614
615    return ret;
616 }
617
618 /**
619  * To be documented.
620  *
621  * FIXME: To be fixed.
622  */
623 EAPI Ecore_X_WM_Protocol *
624 ecore_x_window_prop_protocol_list_get(Ecore_X_Window win, int *num_ret)
625 {
626    Atom *protos = NULL;
627    int i, protos_count = 0;
628    Ecore_X_WM_Protocol *prot_ret = NULL;
629    
630    if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
631      return NULL;
632
633    if ((!protos) || (protos_count <= 0)) return NULL;
634    prot_ret = calloc(1, protos_count * sizeof(Ecore_X_WM_Protocol));
635    if (!prot_ret)
636      {
637         XFree(protos);
638         return NULL;
639      }
640    for (i = 0; i < protos_count; i++)
641      {
642         Ecore_X_WM_Protocol j;
643         
644         prot_ret[i] = -1;
645         for (j = 0; j < ECORE_X_WM_PROTOCOL_NUM; j++)
646           {
647              if (_ecore_x_atoms_wm_protocols[j] == protos[i])
648                prot_ret[i] = j;
649           }
650      }
651    XFree(protos);
652    *num_ret = protos_count;
653    return prot_ret;
654 }