eolian: rename is_ref API to is_ptr to match syntax
[platform/upstream/efl.git] / src / lib / ecore_x / xcb / ecore_xcb_icccm.c
1 #include "ecore_xcb_private.h"
2 #include <xcb/xcb_icccm.h>
3
4 EAPI void
5 ecore_x_icccm_init(void)
6 {
7 }
8
9 /**
10  * Sets the WM_COMMAND property for @a win.
11  *
12  * @param win  The window.
13  * @param argc Number of arguments.
14  * @param argv Arguments.
15  */
16 EAPI void
17 ecore_x_icccm_command_set(Ecore_X_Window win,
18                           int            argc,
19                           char         **argv)
20 {
21    void *buf;
22    char *b;
23    int nbytes, i;
24
25    LOGFN(__FILE__, __LINE__, __FUNCTION__);
26    CHECK_XCB_CONN;
27
28    for (i = 0, nbytes = 0; i < argc; i++) 
29      if (argv[i]) nbytes += strlen(argv[i]) + 1;
30
31    buf = malloc(sizeof(char) * nbytes);
32    if (!buf) return;
33
34    b = (char *)buf;
35    for (i = 0; i < argc; i++)
36      {
37         if (argv[i])
38           {
39              strcpy(b, argv[i]);
40              b += strlen(argv[i]) + 1;
41           }
42         else
43           *b++ = '\0';
44      }
45    xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
46                        ECORE_X_ATOM_WM_COMMAND, ECORE_X_ATOM_STRING, 8,
47                        nbytes, buf);
48    free(buf);
49 }
50
51 /**
52  * Get the WM_COMMAND property for @a win.
53  *
54  * Return the command of a window. String must be free'd when done with.
55  *
56  * @param win  The window.
57  * @param argc Number of arguments.
58  * @param argv Arguments.
59  */
60 EAPI void
61 ecore_x_icccm_command_get(Ecore_X_Window win,
62                           int           *argc,
63                           char        ***argv)
64 {
65    xcb_get_property_cookie_t cookie;
66    xcb_get_property_reply_t *reply;
67    int len = 0;
68    char **v, *data, *cp, *start;
69    int c = 0, i = 0, j = 0;
70
71    LOGFN(__FILE__, __LINE__, __FUNCTION__);
72    CHECK_XCB_CONN;
73
74    if (argc) *argc = 0;
75    if (argv) *argv = NULL;
76
77    cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, win,
78                                        ECORE_X_ATOM_WM_COMMAND,
79                                        XCB_GET_PROPERTY_TYPE_ANY,
80                                        0, 1000000L);
81    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
82    if (!reply) return;
83
84    if ((reply->type != ECORE_X_ATOM_STRING) || (reply->format != 8))
85      {
86         free(reply);
87         return;
88      }
89
90    len = reply->value_len;
91    if (len < 1)
92      {
93         free(reply);
94         return;
95      }
96
97    data = (char *)xcb_get_property_value(reply);
98    if (len && (data[len - 1] == '\0'))
99      len--;
100
101    c = 1;
102    for (cp = (char *)data, i = len; i > 0; cp++, i--)
103      if (*cp == '\0') c++;
104
105    v = (char **)malloc((c + 1) * sizeof(char *));
106    if (!v)
107      {
108         free(reply);
109         return;
110      }
111
112    start = (char *)malloc((len + 1) * sizeof(char));
113    if (!start)
114      {
115         free(reply);
116         free(v);
117         return;
118      }
119
120    memcpy(start, (char *)data, len);
121    start[len] = '\0';
122    for (cp = start, i = len + 1, j = 0; i > 0; cp++, i--)
123      {
124         if (*cp == '\0')
125           {
126              v[j] = start;
127              start = (cp + 1);
128              j++;
129           }
130      }
131
132    if (c < 1)
133      {
134         free(reply);
135         free(v);
136         return;
137      }
138
139    if (argc) *argc = c;
140
141    if (argv)
142      {
143         (*argv) = malloc(c * sizeof(char *));
144         if (!*argv)
145           {
146              free(reply);
147              free(v);
148              if (argc) *argc = 0;
149              return;
150           }
151
152         for (i = 0; i < c; i++)
153           {
154              if (v[i])
155                (*argv)[i] = strdup(v[i]);
156              else
157                (*argv)[i] = strdup("");
158           }
159      }
160
161    free(reply);
162    free(v);
163 }
164
165 EAPI char *
166 ecore_x_icccm_title_get(Ecore_X_Window win)
167 {
168    xcb_get_property_cookie_t cookie;
169    xcb_icccm_get_text_property_reply_t prop;
170    uint8_t ret = 0;
171    char *title = NULL;
172
173    LOGFN(__FILE__, __LINE__, __FUNCTION__);
174    CHECK_XCB_CONN;
175
176    if (!win) return NULL;
177    cookie = xcb_icccm_get_wm_name_unchecked(_ecore_xcb_conn, win);
178    ret = xcb_icccm_get_wm_name_reply(_ecore_xcb_conn, cookie, &prop, NULL);
179    if (ret == 0) return NULL;
180    if (prop.name_len < 1)
181      {
182         xcb_icccm_get_text_property_reply_wipe(&prop);
183         return NULL;
184      }
185
186    if (!(title = malloc((prop.name_len + 1) * sizeof(char *))))
187      {
188         xcb_icccm_get_text_property_reply_wipe(&prop);
189         return NULL;
190      }
191    memcpy(title, prop.name, sizeof(char *) * prop.name_len);
192    title[prop.name_len] = '\0';
193
194    if (prop.encoding != ECORE_X_ATOM_UTF8_STRING)
195      {
196         Ecore_Xcb_Textproperty tp;
197         int count = 0;
198         char **list = NULL;
199         Eina_Bool ret = EINA_FALSE;
200
201         tp.value = strdup(title);
202         tp.nitems = prop.name_len;
203         tp.encoding = prop.encoding;
204 #ifdef HAVE_ICONV
205         ret = _ecore_xcb_utf8_textproperty_to_textlist(&tp, &list, &count);
206 #else
207         ret = _ecore_xcb_mb_textproperty_to_textlist(&tp, &list, &count);
208 #endif
209         if (ret)
210           {
211              if (count > 0)
212                title = strdup(list[0]);
213
214              if (list) free(list);
215           }
216      }
217
218    xcb_icccm_get_text_property_reply_wipe(&prop);
219    return title;
220 }
221
222 EAPI void
223 ecore_x_icccm_title_set(Ecore_X_Window win,
224                         const char    *title)
225 {
226    Ecore_Xcb_Textproperty prop;
227    char *list[1];
228    Eina_Bool ret = EINA_FALSE;
229
230    LOGFN(__FILE__, __LINE__, __FUNCTION__);
231    CHECK_XCB_CONN;
232
233    if (!title) return;
234
235    prop.value = NULL;
236    list[0] = strdup(title);
237
238 #ifdef HAVE_ICONV
239    ret = _ecore_xcb_utf8_textlist_to_textproperty(list, 1, XcbUTF8StringStyle,
240                                                   &prop);
241 #else
242    ret = _ecore_xcb_mb_textlist_to_textproperty(list, 1, XcbStdICCTextStyle,
243                                                 &prop);
244 #endif
245
246    if (ret)
247      {
248         xcb_icccm_set_wm_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, 8,
249                               strlen(prop.value), prop.value);
250         if (prop.value) free(prop.value);
251      }
252    else
253      xcb_icccm_set_wm_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, 8,
254                            strlen(title), title);
255    free(list[0]);
256 }
257
258 /**
259  * Get a window name & class.
260  * @param win The window
261  * @param n The name string
262  * @param c The class string
263  *
264  * Get a window name * class
265  */
266 EAPI void
267 ecore_x_icccm_name_class_get(Ecore_X_Window win,
268                              char         **name,
269                              char         **class)
270 {
271    xcb_get_property_cookie_t cookie;
272    xcb_icccm_get_wm_class_reply_t prop;
273    uint8_t ret = 0;
274
275    LOGFN(__FILE__, __LINE__, __FUNCTION__);
276    CHECK_XCB_CONN;
277
278    if (name) *name = NULL;
279    if (class) *class = NULL;
280
281    cookie = xcb_icccm_get_wm_class_unchecked(_ecore_xcb_conn, win);
282    ret = xcb_icccm_get_wm_class_reply(_ecore_xcb_conn, cookie, &prop, NULL);
283    if (ret == 0) return;
284
285    if (name) *name = strdup(prop.instance_name);
286    if (class) *class = strdup(prop.class_name);
287
288    xcb_icccm_get_wm_class_reply_wipe(&prop);
289 }
290
291 /**
292  * Set a window name & class.
293  * @param win The window
294  * @param n The name string
295  * @param c The class string
296  *
297  * Set a window name * class
298  */
299 EAPI void
300 ecore_x_icccm_name_class_set(Ecore_X_Window win,
301                              const char    *name,
302                              const char    *class)
303 {
304    char *class_string, *s;
305    int length_name = 0, length_class = 0;
306
307    LOGFN(__FILE__, __LINE__, __FUNCTION__);
308    CHECK_XCB_CONN;
309
310    if (name) length_name = strlen(name);
311    if (class) length_class = strlen(class);
312    class_string =
313      (char *)malloc(sizeof(char) * (length_name + length_class + 2));
314    if (!class_string) return;
315
316    s = class_string;
317    if (length_name)
318      {
319         strcpy(s, name);
320         s += length_name + 1;
321      }
322    else
323      *s++ = '\0';
324
325    if (length_class)
326      strcpy(s, class);
327    else
328      *s = '\0';
329
330    xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
331                        ECORE_X_ATOM_WM_CLASS, ECORE_X_ATOM_STRING, 8,
332                        length_name + length_class + 2, (void *)class_string);
333    free(class_string);
334 }
335
336 /**
337  * Specify that a window is transient for another top-level window and should be handled accordingly.
338  * @param win the transient window
339  * @param forwin the toplevel window
340  */
341 EAPI void
342 ecore_x_icccm_transient_for_set(Ecore_X_Window win,
343                                 Ecore_X_Window forwindow)
344 {
345    LOGFN(__FILE__, __LINE__, __FUNCTION__);
346    CHECK_XCB_CONN;
347
348    xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
349                        ECORE_X_ATOM_WM_TRANSIENT_FOR, ECORE_X_ATOM_WINDOW, 32,
350                        1, (void *)&forwindow);
351 }
352
353 /**
354  * Remove the transient_for setting from a window.
355  * @param win The window
356  */
357 EAPI void
358 ecore_x_icccm_transient_for_unset(Ecore_X_Window win)
359 {
360    LOGFN(__FILE__, __LINE__, __FUNCTION__);
361
362    ecore_x_window_prop_property_del(win, ECORE_X_ATOM_WM_TRANSIENT_FOR);
363 }
364
365 /**
366  * Get the window this window is transient for, if any.
367  * @param win The window to check
368  * @return The window ID of the top-level window, or 0 if the property does not exist.
369  */
370 EAPI Ecore_X_Window
371 ecore_x_icccm_transient_for_get(Ecore_X_Window win)
372 {
373    Ecore_X_Window forwin = 0;
374    xcb_get_property_cookie_t cookie;
375
376    LOGFN(__FILE__, __LINE__, __FUNCTION__);
377    CHECK_XCB_CONN;
378
379    cookie = xcb_icccm_get_wm_transient_for_unchecked(_ecore_xcb_conn, win);
380    xcb_icccm_get_wm_transient_for_reply(_ecore_xcb_conn, cookie, &forwin, NULL);
381
382    return forwin;
383 }
384
385 /**
386  * Get the window role.
387  * @param win The window
388  * @return The window's role string.
389  */
390 EAPI char *
391 ecore_x_icccm_window_role_get(Ecore_X_Window win)
392 {
393    LOGFN(__FILE__, __LINE__, __FUNCTION__);
394
395    return ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_WINDOW_ROLE);
396 }
397
398 /**
399  * Set the window role hint.
400  * @param win The window
401  * @param role The role string
402  */
403 EAPI void
404 ecore_x_icccm_window_role_set(Ecore_X_Window win,
405                               const char    *role)
406 {
407    LOGFN(__FILE__, __LINE__, __FUNCTION__);
408
409    ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_WINDOW_ROLE, role);
410 }
411
412 /**
413  * Get the window's client leader.
414  * @param win The window
415  * @return The window's client leader window, or 0 if unset
416  */
417 EAPI Ecore_X_Window
418 ecore_x_icccm_client_leader_get(Ecore_X_Window win)
419 {
420    Ecore_X_Window leader;
421
422    LOGFN(__FILE__, __LINE__, __FUNCTION__);
423
424    if (ecore_x_window_prop_window_get(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
425                                       &leader, 1) > 0)
426      return leader;
427
428    return 0;
429 }
430
431 /**
432  * Set the window's client leader.
433  * @param win The window
434  * @param l The client leader window
435  *
436  * All non-transient top-level windows created by an app other than
437  * the main window must have this property set to the app's main window.
438  */
439 EAPI void
440 ecore_x_icccm_client_leader_set(Ecore_X_Window win,
441                                 Ecore_X_Window leader)
442 {
443    LOGFN(__FILE__, __LINE__, __FUNCTION__);
444
445    ecore_x_window_prop_window_set(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
446                                   &leader, 1);
447 }
448
449 EAPI Ecore_X_Window_State_Hint
450 ecore_x_icccm_state_get(Ecore_X_Window win)
451 {
452    xcb_get_property_cookie_t cookie;
453    xcb_get_property_reply_t *reply;
454    Ecore_X_Window_State_Hint hint = ECORE_X_WINDOW_STATE_HINT_NONE;
455    uint8_t *prop;
456
457    LOGFN(__FILE__, __LINE__, __FUNCTION__);
458    CHECK_XCB_CONN;
459
460    cookie =
461      xcb_get_property_unchecked(_ecore_xcb_conn, 0, win,
462                                 ECORE_X_ATOM_WM_STATE, ECORE_X_ATOM_WM_STATE,
463                                 0L, 0x7fffffff);
464    reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
465    if (!reply) return hint;
466    if ((reply->type == 0) || (reply->format != 8) || (reply->value_len != 2))
467      {
468         free(reply);
469         return hint;
470      }
471
472    prop = (uint8_t *)xcb_get_property_value(reply);
473    switch (prop[0])
474      {
475       case XCB_ICCCM_WM_STATE_WITHDRAWN:
476         hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
477         break;
478
479       case XCB_ICCCM_WM_STATE_NORMAL:
480         hint = ECORE_X_WINDOW_STATE_HINT_NORMAL;
481         break;
482
483       case XCB_ICCCM_WM_STATE_ICONIC:
484         hint = ECORE_X_WINDOW_STATE_HINT_ICONIC;
485         break;
486
487       default:
488         break;
489      }
490
491    free(reply);
492    return hint;
493 }
494
495 EAPI void
496 ecore_x_icccm_state_set(Ecore_X_Window            win,
497                         Ecore_X_Window_State_Hint state)
498 {
499    xcb_icccm_wm_hints_t hints;
500
501    LOGFN(__FILE__, __LINE__, __FUNCTION__);
502    CHECK_XCB_CONN;
503
504    xcb_icccm_wm_hints_set_none(&hints);
505
506    hints.flags = XCB_ICCCM_WM_HINT_STATE;
507
508    if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
509      xcb_icccm_wm_hints_set_withdrawn(&hints);
510    else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
511      xcb_icccm_wm_hints_set_normal(&hints);
512    else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
513      xcb_icccm_wm_hints_set_iconic(&hints);
514
515    xcb_icccm_set_wm_hints(_ecore_xcb_conn, win, &hints);
516 }
517
518 EAPI void
519 ecore_x_icccm_delete_window_send(Ecore_X_Window win,
520                                  Ecore_X_Time   t)
521 {
522    LOGFN(__FILE__, __LINE__, __FUNCTION__);
523    ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
524                                  ECORE_X_EVENT_MASK_NONE,
525                                  ECORE_X_ATOM_WM_DELETE_WINDOW, t, 0, 0, 0);
526 }
527
528 EAPI void
529 ecore_x_icccm_hints_set(Ecore_X_Window            win,
530                         Eina_Bool                 accepts_focus,
531                         Ecore_X_Window_State_Hint initial_state,
532                         Ecore_X_Pixmap            icon_pixmap,
533                         Ecore_X_Pixmap            icon_mask,
534                         Ecore_X_Window            icon_window,
535                         Ecore_X_Window            window_group,
536                         Eina_Bool                 is_urgent)
537 {
538    xcb_icccm_wm_hints_t hints;
539
540    LOGFN(__FILE__, __LINE__, __FUNCTION__);
541    CHECK_XCB_CONN;
542
543    xcb_icccm_wm_hints_set_none(&hints);
544    xcb_icccm_wm_hints_set_input(&hints, accepts_focus);
545
546    if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
547      xcb_icccm_wm_hints_set_withdrawn(&hints);
548    else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
549      xcb_icccm_wm_hints_set_normal(&hints);
550    else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
551      xcb_icccm_wm_hints_set_iconic(&hints);
552
553    if (icon_pixmap != 0)
554      xcb_icccm_wm_hints_set_icon_pixmap(&hints, icon_pixmap);
555    if (icon_mask != 0)
556      xcb_icccm_wm_hints_set_icon_mask(&hints, icon_mask);
557    if (icon_window != 0)
558      xcb_icccm_wm_hints_set_icon_window(&hints, icon_window);
559    if (window_group != 0)
560      xcb_icccm_wm_hints_set_window_group(&hints, window_group);
561    if (is_urgent)
562      xcb_icccm_wm_hints_set_urgency(&hints);
563
564    xcb_icccm_set_wm_hints(_ecore_xcb_conn, win, &hints);
565 }
566
567 EAPI Eina_Bool
568 ecore_x_icccm_hints_get(Ecore_X_Window             win,
569                         Eina_Bool                 *accepts_focus,
570                         Ecore_X_Window_State_Hint *initial_state,
571                         Ecore_X_Pixmap            *icon_pixmap,
572                         Ecore_X_Pixmap            *icon_mask,
573                         Ecore_X_Window            *icon_window,
574                         Ecore_X_Window            *window_group,
575                         Eina_Bool                 *is_urgent)
576 {
577    xcb_get_property_cookie_t cookie;
578    xcb_icccm_wm_hints_t hints;
579    uint8_t ret = 0;
580
581    LOGFN(__FILE__, __LINE__, __FUNCTION__);
582    CHECK_XCB_CONN;
583
584    if (accepts_focus) *accepts_focus = EINA_TRUE;
585    if (initial_state) *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
586    if (icon_pixmap) *icon_pixmap = 0;
587    if (icon_mask) *icon_mask = 0;
588    if (icon_window) *icon_window = 0;
589    if (window_group) *window_group = 0;
590    if (is_urgent) *is_urgent = EINA_FALSE;
591
592    xcb_icccm_wm_hints_set_none(&hints);
593    cookie = xcb_icccm_get_wm_hints_unchecked(_ecore_xcb_conn, win);
594    ret = xcb_icccm_get_wm_hints_reply(_ecore_xcb_conn, cookie, &hints, NULL);
595    if (!ret) return EINA_FALSE;
596
597    if ((hints.flags & XCB_ICCCM_WM_HINT_INPUT) && (accepts_focus))
598      {
599         if (hints.input)
600           *accepts_focus = EINA_TRUE;
601         else
602           *accepts_focus = EINA_FALSE;
603      }
604
605    if ((hints.flags & XCB_ICCCM_WM_HINT_STATE) && (initial_state))
606      {
607         if (hints.initial_state == XCB_ICCCM_WM_STATE_WITHDRAWN)
608           *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
609         else if (hints.initial_state == XCB_ICCCM_WM_STATE_NORMAL)
610           *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
611         else if (hints.initial_state == XCB_ICCCM_WM_STATE_ICONIC)
612           *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
613      }
614
615    if ((hints.flags & XCB_ICCCM_WM_HINT_ICON_PIXMAP) && (icon_pixmap))
616      *icon_pixmap = hints.icon_pixmap;
617
618    if ((hints.flags & XCB_ICCCM_WM_HINT_ICON_MASK) && (icon_mask))
619      *icon_mask = hints.icon_mask;
620
621    if ((hints.flags & XCB_ICCCM_WM_HINT_ICON_WINDOW) && (icon_window))
622      *icon_window = hints.icon_window;
623
624    if ((hints.flags & XCB_ICCCM_WM_HINT_WINDOW_GROUP) && (window_group))
625      *window_group = hints.window_group;
626
627    if ((hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) && (is_urgent))
628      *is_urgent = EINA_TRUE;
629
630    return EINA_TRUE;
631 }
632
633 /**
634  * Get a window icon name.
635  * @param win The window
636  * @return The windows icon name string
637  *
638  * Return the icon name of a window. String must be free'd when done with.
639  */
640 EAPI char *
641 ecore_x_icccm_icon_name_get(Ecore_X_Window win)
642 {
643    xcb_get_property_cookie_t cookie;
644    xcb_icccm_get_text_property_reply_t prop;
645    uint8_t ret = 0;
646    char *tmp = NULL;
647
648    LOGFN(__FILE__, __LINE__, __FUNCTION__);
649    CHECK_XCB_CONN;
650
651    if (!win) return NULL;
652
653    cookie = xcb_icccm_get_wm_icon_name_unchecked(_ecore_xcb_conn, win);
654    ret = xcb_icccm_get_wm_icon_name_reply(_ecore_xcb_conn, cookie, &prop, NULL);
655    if (ret == 0) return NULL;
656
657    if (prop.name_len < 1)
658      {
659         xcb_icccm_get_text_property_reply_wipe(&prop);
660         return NULL;
661      }
662
663    if (!(tmp = malloc((prop.name_len + 1) * sizeof(char *))))
664      {
665         xcb_icccm_get_text_property_reply_wipe(&prop);
666         return NULL;
667      }
668    memcpy(tmp, prop.name, sizeof(char *) * prop.name_len);
669    tmp[prop.name_len] = '\0';
670
671    if (prop.encoding != ECORE_X_ATOM_UTF8_STRING)
672      {
673         Ecore_Xcb_Textproperty tp;
674         int count = 0;
675         char **list = NULL;
676         Eina_Bool ret = EINA_FALSE;
677
678         tp.value = strdup(tmp);
679         tp.nitems = prop.name_len;
680         tp.encoding = prop.encoding;
681 #ifdef HAVE_ICONV
682         ret = _ecore_xcb_utf8_textproperty_to_textlist(&tp, &list, &count);
683 #else
684         ret = _ecore_xcb_mb_textproperty_to_textlist(&tp, &list, &count);
685 #endif
686         if (ret)
687           {
688              if (count > 0)
689                tmp = strdup(list[0]);
690
691              if (list) free(list);
692           }
693      }
694
695    xcb_icccm_get_text_property_reply_wipe(&prop);
696    return tmp;
697 }
698
699 /**
700  * Set a window icon name.
701  * @param win The window
702  * @param t The icon name string
703  *
704  * Set a window icon name
705  */
706 EAPI void
707 ecore_x_icccm_icon_name_set(Ecore_X_Window win,
708                             const char    *name)
709 {
710    Ecore_Xcb_Textproperty prop;
711    char *list[1];
712    Eina_Bool ret = EINA_FALSE;
713
714    LOGFN(__FILE__, __LINE__, __FUNCTION__);
715    CHECK_XCB_CONN;
716
717    if ((!win) || (!name)) return;
718
719    prop.value = NULL;
720    list[0] = strdup(name);
721
722 #ifdef HAVE_ICONV
723    ret = _ecore_xcb_utf8_textlist_to_textproperty(list, 1, XcbUTF8StringStyle,
724                                                   &prop);
725 #else
726    ret = _ecore_xcb_mb_textlist_to_textproperty(list, 1, XcbStdICCTextStyle,
727                                                 &prop);
728 #endif
729
730    if (ret)
731      {
732         xcb_icccm_set_wm_icon_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING,
733                                    8, strlen(prop.value), prop.value);
734         if (prop.value) free(prop.value);
735      }
736    else
737      xcb_icccm_set_wm_icon_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING,
738                                 8, strlen(name), name);
739
740    free(list[0]);
741 }
742
743 EAPI void
744 ecore_x_icccm_iconic_request_send(Ecore_X_Window win,
745                                   Ecore_X_Window root)
746 {
747    xcb_client_message_event_t ev;
748
749    LOGFN(__FILE__, __LINE__, __FUNCTION__);
750    CHECK_XCB_CONN;
751
752    if (!win) return;
753    if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
754
755    memset(&ev, 0, sizeof(xcb_client_message_event_t));
756
757    ev.response_type = XCB_CLIENT_MESSAGE;
758    ev.format = 32;
759    ev.window = win;
760    ev.type = ECORE_X_ATOM_WM_CHANGE_STATE;
761    ev.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC;
762
763    xcb_send_event(_ecore_xcb_conn, 0, root,
764                   (XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
765                    XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT),
766                   (const char *)&ev);
767 //   ecore_x_flush();
768 }
769
770 /**
771  * Set or unset a wm protocol property.
772  * @param win The Window
773  * @param protocol The protocol to enable/disable
774  * @param on On/Off
775  */
776 EAPI void
777 ecore_x_icccm_protocol_set(Ecore_X_Window      win,
778                            Ecore_X_WM_Protocol protocol,
779                            Eina_Bool           on)
780 {
781    Ecore_X_Atom proto;
782    xcb_get_property_cookie_t cookie;
783    xcb_icccm_get_wm_protocols_reply_t protos;
784    int i = 0, count = 0, set = 0;
785
786    LOGFN(__FILE__, __LINE__, __FUNCTION__);
787    CHECK_XCB_CONN;
788
789    if (protocol >= ECORE_X_WM_PROTOCOL_NUM) return;
790    proto = _ecore_xcb_atoms_wm_protocol[protocol];
791    cookie = xcb_icccm_get_wm_protocols_unchecked(_ecore_xcb_conn, win, proto);
792    if (!xcb_icccm_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protos, NULL))
793      count = 0;
794    else
795      count = protos.atoms_len;
796
797    for (i = 0; i < count; i++)
798      {
799         if (protos.atoms[i] == proto)
800           {
801              set = 1;
802              break;
803           }
804      }
805
806    if (on)
807      {
808         if (!set)
809           {
810              Ecore_X_Atom *atoms = NULL;
811
812              atoms = malloc((count + 1) * sizeof(Ecore_X_Atom));
813              if (atoms)
814                {
815                   for (i = 0; i < count; i++)
816                     atoms[i] = protos.atoms[i];
817                   atoms[count] = proto;
818                   xcb_icccm_set_wm_protocols(_ecore_xcb_conn, win, 
819                                              ECORE_X_ATOM_WM_PROTOCOLS,
820                                              count, atoms);
821                   free(atoms);
822                }
823           }
824      }
825    else
826      {
827         if (set)
828           {
829              for (i = 0; i < count; i++)
830                {
831                   if (protos.atoms[i] == proto)
832                     {
833                        int j = 0;
834
835                        for (j = (i + 1); j < count; j++)
836                          protos.atoms[j - 1] = protos.atoms[j];
837                        if (count > 1)
838                          xcb_icccm_set_wm_protocols(_ecore_xcb_conn, win, 
839                                                     ECORE_X_ATOM_WM_PROTOCOLS,
840                                                     count - 1, protos.atoms);
841                        else
842                          ecore_x_window_prop_property_del(win,
843                                                           ECORE_X_ATOM_WM_PROTOCOLS);
844                        break;
845                     }
846                }
847           }
848      }
849
850    xcb_icccm_get_wm_protocols_reply_wipe(&protos);
851 }
852
853 /**
854  * Determines whether a protocol is set for a window.
855  * @param win The Window
856  * @param protocol The protocol to query
857  * @return 1 if the protocol is set, else 0.
858  */
859 EAPI Eina_Bool
860 ecore_x_icccm_protocol_isset(Ecore_X_Window      win,
861                              Ecore_X_WM_Protocol protocol)
862 {
863    Ecore_X_Atom proto;
864    Eina_Bool ret = EINA_FALSE;
865    xcb_get_property_cookie_t cookie;
866    xcb_icccm_get_wm_protocols_reply_t reply;
867    uint8_t val = 0;
868    unsigned int i = 0;
869
870    LOGFN(__FILE__, __LINE__, __FUNCTION__);
871    CHECK_XCB_CONN;
872
873    if (protocol >= ECORE_X_WM_PROTOCOL_NUM) return EINA_FALSE;
874
875    proto = _ecore_xcb_atoms_wm_protocol[protocol];
876    cookie = xcb_icccm_get_wm_protocols_unchecked(_ecore_xcb_conn, win, proto);
877    val = xcb_icccm_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &reply, NULL);
878    if (!val) return EINA_FALSE;
879
880    for (i = 0; i < reply.atoms_len; i++)
881      if (reply.atoms[i] == proto)
882        {
883           ret = EINA_TRUE;
884           break;
885        }
886
887    xcb_icccm_get_wm_protocols_reply_wipe(&reply);
888
889    return ret;
890 }
891
892 /**
893  * Set protocol atoms explicitly
894  * @param win The Window
895  * @param protos An array of protocol atoms
896  * @param num the number of members of the array
897  */
898 EAPI void
899 ecore_x_icccm_protocol_atoms_set(Ecore_X_Window win,
900                                  Ecore_X_Atom  *protos,
901                                  int            num)
902 {
903    LOGFN(__FILE__, __LINE__, __FUNCTION__);
904    CHECK_XCB_CONN;
905
906    if (num > 0)
907      xcb_icccm_set_wm_protocols(_ecore_xcb_conn, win,
908                                 ECORE_X_ATOM_WM_PROTOCOLS, num, protos);
909    else
910      ecore_x_window_prop_property_del(win, ECORE_X_ATOM_WM_PROTOCOLS);
911 }
912
913 EAPI Eina_Bool
914 ecore_x_icccm_size_pos_hints_get(Ecore_X_Window   win,
915                                  Eina_Bool       *request_pos,
916                                  Ecore_X_Gravity *gravity,
917                                  int             *min_w,
918                                  int             *min_h,
919                                  int             *max_w,
920                                  int             *max_h,
921                                  int             *base_w,
922                                  int             *base_h,
923                                  int             *step_x,
924                                  int             *step_y,
925                                  double          *min_aspect,
926                                  double          *max_aspect)
927 {
928    xcb_size_hints_t hints;
929    xcb_get_property_cookie_t cookie;
930    uint8_t ret = 0;
931    int32_t minw = 0, minh = 0;
932    int32_t maxw = 32767, maxh = 32767;
933    int32_t basew = -1, baseh = -1;
934    int32_t stepx = -1, stepy = -1;
935    double mina = 0.0, maxa = 0.0;
936
937    LOGFN(__FILE__, __LINE__, __FUNCTION__);
938    CHECK_XCB_CONN;
939
940    if (request_pos) *request_pos = EINA_FALSE;
941    if (gravity) *gravity = ECORE_X_GRAVITY_NW;
942    if (min_w) *min_w = minw;
943    if (min_h) *min_h = minh;
944    if (max_w) *max_w = maxw;
945    if (max_h) *max_h = maxh;
946    if (base_w) *base_w = basew;
947    if (base_h) *base_h = baseh;
948    if (step_x) *step_x = stepx;
949    if (step_y) *step_y = stepy;
950    if (min_aspect) *min_aspect = mina;
951    if (max_aspect) *max_aspect = maxa;
952
953    cookie = xcb_icccm_get_wm_normal_hints_unchecked(_ecore_xcb_conn, win);
954    ret = xcb_icccm_get_wm_normal_hints_reply(_ecore_xcb_conn, cookie,
955                                              &hints, NULL);
956    if (!ret) return EINA_FALSE;
957
958    if ((hints.flags & XCB_ICCCM_SIZE_HINT_US_POSITION) ||
959        (hints.flags & XCB_ICCCM_SIZE_HINT_P_POSITION))
960      {
961         if (request_pos) *request_pos = EINA_TRUE;
962      }
963
964    if (hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)
965      {
966         if (gravity) *gravity = hints.win_gravity;
967      }
968
969    if (hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)
970      {
971         minw = hints.min_width;
972         minh = hints.min_height;
973      }
974
975    if (hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)
976      {
977         maxw = hints.max_width;
978         maxh = hints.max_height;
979         if (maxw < minw) maxw = minw;
980         if (maxh < minh) maxh = minh;
981      }
982
983    if (hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE)
984      {
985         basew = hints.base_width;
986         baseh = hints.base_height;
987         if (basew > minw) minw = basew;
988         if (baseh > minh) minh = baseh;
989      }
990
991    if (hints.flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)
992      {
993         stepx = hints.width_inc;
994         stepy = hints.height_inc;
995         if (stepx < 1) stepx = 1;
996         if (stepy < 1) stepy = 1;
997      }
998
999    if (hints.flags & XCB_ICCCM_SIZE_HINT_P_ASPECT)
1000      {
1001         if (hints.min_aspect_den > 0)
1002           mina = ((double)hints.min_aspect_num) / ((double)hints.min_aspect_den);
1003
1004         if (hints.max_aspect_den > 0)
1005           maxa = ((double)hints.max_aspect_num) / ((double)hints.max_aspect_den);
1006      }
1007
1008    if (min_w) *min_w = minw;
1009    if (min_h) *min_h = minh;
1010    if (max_w) *max_w = maxw;
1011    if (max_h) *max_h = maxh;
1012    if (base_w) *base_w = basew;
1013    if (base_h) *base_h = baseh;
1014    if (step_x) *step_x = stepx;
1015    if (step_y) *step_y = stepy;
1016    if (min_aspect) *min_aspect = mina;
1017    if (max_aspect) *max_aspect = maxa;
1018
1019    return EINA_TRUE;
1020 }
1021
1022 EAPI void
1023 ecore_x_icccm_size_pos_hints_set(Ecore_X_Window  win,
1024                                  Eina_Bool       request_pos,
1025                                  Ecore_X_Gravity gravity,
1026                                  int             min_w,
1027                                  int             min_h,
1028                                  int             max_w,
1029                                  int             max_h,
1030                                  int             base_w,
1031                                  int             base_h,
1032                                  int             step_x,
1033                                  int             step_y,
1034                                  double          min_aspect,
1035                                  double          max_aspect)
1036 {
1037    xcb_get_property_cookie_t cookie;
1038    xcb_size_hints_t hints;
1039    uint8_t ret = 0;
1040
1041    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1042    CHECK_XCB_CONN;
1043
1044    cookie = xcb_icccm_get_wm_normal_hints_unchecked(_ecore_xcb_conn, win);
1045    ret = xcb_icccm_get_wm_normal_hints_reply(_ecore_xcb_conn, cookie,
1046                                              &hints, NULL);
1047    if (!ret) memset(&hints, 0, sizeof(xcb_size_hints_t));
1048
1049    hints.flags = 0;
1050
1051    if (request_pos)
1052      hints.flags |= XCB_ICCCM_SIZE_HINT_US_POSITION;
1053
1054    if (gravity != ECORE_X_GRAVITY_NW)
1055      xcb_icccm_size_hints_set_win_gravity(&hints, gravity);
1056    if ((min_w > 0) || (min_h > 0))
1057      xcb_icccm_size_hints_set_min_size(&hints, min_w, min_h);
1058    if ((max_w > 0) || (max_h > 0))
1059      xcb_icccm_size_hints_set_max_size(&hints, max_w, max_h);
1060    if ((base_w > 0) || (base_h > 0))
1061      xcb_icccm_size_hints_set_base_size(&hints, base_w, base_h);
1062    if ((step_x > 1) || (step_y > 1))
1063      xcb_icccm_size_hints_set_resize_inc(&hints, step_x, step_y);
1064    if ((min_aspect > 0.0) || (max_aspect > 0.0))
1065      xcb_icccm_size_hints_set_aspect(&hints,
1066                                      (int32_t)(min_aspect * 10000), 10000,
1067                                      (int32_t)(max_aspect * 10000), 10000);
1068
1069    xcb_icccm_set_wm_normal_hints(_ecore_xcb_conn, win, &hints);
1070 }
1071
1072 EAPI void
1073 ecore_x_icccm_move_resize_send(Ecore_X_Window win,
1074                                int            x,
1075                                int            y,
1076                                int            w,
1077                                int            h)
1078 {
1079    xcb_configure_notify_event_t ev;
1080
1081    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1082    CHECK_XCB_CONN;
1083
1084    if (!win) return;
1085
1086    memset(&ev, 0, sizeof(xcb_configure_notify_event_t));
1087
1088    ev.response_type = XCB_CONFIGURE_NOTIFY;
1089    ev.event = win;
1090    ev.window = win;
1091    ev.above_sibling = XCB_NONE;
1092    ev.x = x;
1093    ev.y = y;
1094    ev.width = w;
1095    ev.height = h;
1096    ev.border_width = 0;
1097    ev.override_redirect = 0;
1098
1099    xcb_send_event(_ecore_xcb_conn, 0, win,
1100                   XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *)&ev);
1101 //   ecore_x_flush();
1102 }
1103
1104 /**
1105  * Get a window client machine string.
1106  * @param win The window
1107  * @return The windows client machine string
1108  *
1109  * Return the client machine of a window. String must be free'd when done with.
1110  */
1111 EAPI char *
1112 ecore_x_icccm_client_machine_get(Ecore_X_Window win)
1113 {
1114    xcb_get_property_cookie_t cookie;
1115    xcb_icccm_get_text_property_reply_t prop;
1116    uint8_t ret = 0;
1117    char *tmp = NULL;
1118
1119    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1120    CHECK_XCB_CONN;
1121
1122    cookie = xcb_icccm_get_wm_client_machine_unchecked(_ecore_xcb_conn, win);
1123    ret = xcb_icccm_get_wm_client_machine_reply(_ecore_xcb_conn, cookie,
1124                                                &prop, NULL);
1125    if (ret == 0) return NULL;
1126
1127    tmp = malloc((prop.name_len + 1) * sizeof(char *));
1128    if (!tmp)
1129      {
1130         xcb_icccm_get_text_property_reply_wipe(&prop);
1131         return NULL;
1132      }
1133    memcpy(tmp, prop.name, sizeof(char *) * prop.name_len);
1134    tmp[prop.name_len] = '\0';
1135
1136    xcb_icccm_get_text_property_reply_wipe(&prop);
1137
1138    return tmp;
1139 }
1140
1141 EAPI void
1142 ecore_x_icccm_take_focus_send(Ecore_X_Window win,
1143                               Ecore_X_Time   t)
1144 {
1145    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1146    CHECK_XCB_CONN;
1147
1148    ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
1149                                  XCB_EVENT_MASK_NO_EVENT,
1150                                  ECORE_X_ATOM_WM_TAKE_FOCUS, t, 0, 0, 0);
1151 }
1152
1153 EAPI void
1154 ecore_x_icccm_save_yourself_send(Ecore_X_Window win,
1155                                  Ecore_X_Time   t)
1156 {
1157    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1158    ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
1159                                  XCB_EVENT_MASK_NO_EVENT,
1160                                  ECORE_X_ATOM_WM_SAVE_YOURSELF, t, 0, 0, 0);
1161 }
1162
1163 /**
1164  * Add a subwindow to the list of windows that need a different colormap installed.
1165  * @param win The toplevel window
1166  * @param subwin The subwindow to be added to the colormap windows list
1167  */
1168 EAPI void
1169 ecore_x_icccm_colormap_window_set(Ecore_X_Window win,
1170                                   Ecore_X_Window subwin)
1171 {
1172    int num = 0, i = 0;
1173    unsigned char *odata = NULL, *data = NULL;
1174    Ecore_X_Window *newset = NULL, *oldset = NULL;
1175
1176    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1177
1178    if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
1179                                          ECORE_X_ATOM_WINDOW, 32, &odata, &num))
1180      {
1181         if (!(newset = calloc(1, sizeof(Ecore_X_Window)))) return;
1182         newset[0] = subwin;
1183         num = 1;
1184         data = (unsigned char *)newset;
1185      }
1186    else
1187      {
1188         if (!(newset = calloc(num + 1, sizeof(Ecore_X_Window)))) return;
1189         oldset = (Ecore_X_Window *)odata;
1190         for (i = 0; i < num; i++)
1191           {
1192              if (oldset[i] == subwin)
1193                {
1194                   if (odata) free(odata);
1195                   odata = NULL;
1196                   free(newset);
1197                   return;
1198                }
1199              newset[i] = oldset[i];
1200           }
1201         newset[num++] = subwin;
1202         if (odata) free(odata);
1203         data = (unsigned char *)newset;
1204      }
1205    ecore_x_window_prop_property_set(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
1206                                     ECORE_X_ATOM_WINDOW, 32, data, num);
1207    free(newset);
1208 }
1209
1210 /**
1211  * Remove a window from the list of colormap windows.
1212  * @param win The toplevel window
1213  * @param subwin The window to be removed from the colormap window list.
1214  */
1215 EAPI void
1216 ecore_x_icccm_colormap_window_unset(Ecore_X_Window win,
1217                                     Ecore_X_Window subwin)
1218 {
1219    int num = 0, i = 0, j = 0, k = 0;
1220    unsigned char *odata = NULL, *data = NULL;
1221    Ecore_X_Window *newset = NULL, *oldset = NULL;
1222
1223    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1224
1225    if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
1226                                          ECORE_X_ATOM_WINDOW, 32, &odata, &num))
1227      return;
1228
1229    oldset = (Ecore_X_Window *)odata;
1230    for (i = 0; i < num; i++)
1231      {
1232         if (oldset[i] == subwin)
1233           {
1234              if (num == 1)
1235                {
1236                   ecore_x_window_prop_property_del(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS);
1237                   if (odata) free(odata);
1238                   odata = NULL;
1239                   return;
1240                }
1241              else
1242                {
1243                   newset = calloc(num - 1, sizeof(Ecore_X_Window));
1244                   data = (unsigned char *)newset;
1245                   for (j = 0; j < num; ++j)
1246                     if (oldset[j] != subwin)
1247                       newset[k++] = oldset[j];
1248
1249                   ecore_x_window_prop_property_set(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
1250                                                    ECORE_X_ATOM_WINDOW, 32, data, k);
1251                   if (odata) free(odata);
1252                   odata = NULL;
1253                   free(newset);
1254                   return;
1255                }
1256           }
1257      }
1258    if (odata) free(odata);
1259 }