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