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