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